| Differences between
and this patch
- Source/JavaScriptCore/ChangeLog +330 lines
Lines 1-3 Source/JavaScriptCore/ChangeLog_sec1
1
2015-09-17  Filip Pizlo  <fpizlo@apple.com>
2
3
        JSC should infer property types
4
        https://bugs.webkit.org/show_bug.cgi?id=148610
5
6
        Reviewed by Geoffrey Garen.
7
8
        This change brings recursive type inference to JavaScript object properties in JSC. We check that a
9
        value being stored into a property obeys a property's type before we do the store. If it doesn't,
10
        we broaden the property's type to include the new value. If optimized code was relying on the old
11
        type, we deoptimize that code.
12
13
        The type system that this supports includes important primitive types like Int32 and Boolean. But
14
        it goes further and also includes a type kind called ObjectWithStructure, which means that we
15
        expect the property to always point to objects with a particular structure. This only works for
16
        leaf structures (i.e. structures that have a valid transition watchpoint set). Invalidation of the
17
        transition set causes the property type to become Object (meaning an object with any structure).
18
        This capability gives us recursive type inference. It's possible for an expression like "o.f.g.h"
19
        to execute without any type checks if .f and .g are both ObjectWithStructure.
20
21
        The type inference of a property is tracked by an InferredType instance, which is a JSCell. This
22
        means that it manages its own memory. That's convenient. For example, when the DFG is interested in
23
        one of these, it can just list the InferredType as a weak reference in addition to setting a
24
        watchpoint. This ensures that even if the InferredType is dropped by the owning structure, the DFG
25
        won't read a dangling pointer. A mapping from property name to InferredType is implemented by
26
        InferredTypeTable, which is also a JSCell. Each Structure may point to some InferredTypeTable.
27
28
        This feature causes programs to be happier (run faster without otherwise doing bad things like
29
        using lots of memory) when four conditions hold:
30
31
        1) A property converges to one of the types that we support.
32
        2) The property is loaded from more frequently than it is stored to.
33
        3) The stores are all cached, so that we statically emit a type check.
34
        4) We don't allocate a lot of meta-data for the property's type.
35
36
        We maximize the likelihood of (1) by having a rich type system. But having a rich type system means
37
        that a reflective put to a property has to have a large switch over the inferred type to decide how
38
        to do the type check. That's why we need (3). We ensure (3) by having every reflective property
39
        store (i.e. putDirectInternal in any context that isn't PutById) force the inferred type to become
40
        Top. We don't really worry about ensuring (2); this is statistically true for most programs
41
        already.
42
43
        Probably the most subtle trickery goes into (4). Logically we'd like to say that each
44
        (Structure, Property) maps to its own InferredType. If structure S1 has a transition edge to S2,
45
        then we could ensure that the InferredType I1 where (S1, Property)->I1 has a data flow constraint
46
        to I2 where (S2, Property)->I2. That would work, but it would involve a lot of memory. And when I1
47
        gets invalidated in some way, it would have to tell I2 about it, and then I2 might tell other
48
        InferredType objects downstream. That's madness. So, the first major compromise that we make here
49
        is to say that if some property has some InferredType at some Structure, then anytime we
50
        transition from that Structure, the new Structure shares the same InferredType for that property.
51
        This unifies the type of the property over the entire transition tree starting at the Structure at
52
        which the property was added. But this would still mean that each Structure would have its own
53
        InferredTypeTable. We don't want that because experience with PropertyTable shows that this can be
54
        a major memory hog. So, we don't create an InferredTypeTable until someone adds a property that is
55
        subject to type inference (i.e. it was added non-reflectively), and we share that InferredTypeTable
56
        with the entire structure transition tree rooted at the Structure that had the first inferred
57
        property. We also drop the InferredTypeTable anytime that we do a dictionary transition, and we
58
        don't allow further property type inference if a structure had ever been a dictionary.
59
60
        This is a 3% speed-up on Octane and a 12% speed-up on Kraken on my setup. It's not a significant
61
        slow-down on any benchmark I ran.
62
63
        * CMakeLists.txt:
64
        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
65
        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
66
        * JavaScriptCore.xcodeproj/project.pbxproj:
67
        * assembler/MacroAssemblerARM64.h:
68
        (JSC::MacroAssemblerARM64::branchTest64):
69
        * assembler/MacroAssemblerX86_64.h:
70
        (JSC::MacroAssemblerX86_64::branchTest64):
71
        (JSC::MacroAssemblerX86_64::test64):
72
        * bytecode/PolymorphicAccess.cpp:
73
        (JSC::AccessCase::generate):
74
        * bytecode/PutByIdFlags.cpp:
75
        (WTF::printInternal):
76
        * bytecode/PutByIdFlags.h:
77
        (JSC::encodeStructureID):
78
        (JSC::decodeStructureID):
79
        * bytecode/PutByIdStatus.cpp:
80
        (JSC::PutByIdStatus::computeFromLLInt):
81
        (JSC::PutByIdStatus::computeFor):
82
        (JSC::PutByIdStatus::computeForStubInfo):
83
        * bytecode/PutByIdVariant.cpp:
84
        (JSC::PutByIdVariant::operator=):
85
        (JSC::PutByIdVariant::replace):
86
        (JSC::PutByIdVariant::transition):
87
        (JSC::PutByIdVariant::setter):
88
        (JSC::PutByIdVariant::attemptToMerge):
89
        (JSC::PutByIdVariant::dumpInContext):
90
        * bytecode/PutByIdVariant.h:
91
        (JSC::PutByIdVariant::newStructure):
92
        (JSC::PutByIdVariant::requiredType):
93
        * bytecode/UnlinkedCodeBlock.h:
94
        (JSC::UnlinkedInstruction::UnlinkedInstruction):
95
        * bytecode/Watchpoint.h:
96
        (JSC::InlineWatchpointSet::touch):
97
        (JSC::InlineWatchpointSet::isBeingWatched):
98
        * bytecompiler/BytecodeGenerator.cpp:
99
        (JSC::BytecodeGenerator::addConstantValue):
100
        (JSC::BytecodeGenerator::emitPutById):
101
        (JSC::BytecodeGenerator::emitDirectPutById):
102
        * dfg/DFGAbstractInterpreter.h:
103
        (JSC::DFG::AbstractInterpreter::filter):
104
        (JSC::DFG::AbstractInterpreter::filterByValue):
105
        * dfg/DFGAbstractInterpreterInlines.h:
106
        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
107
        (JSC::DFG::AbstractInterpreter<AbstractStateType>::filter):
108
        * dfg/DFGAbstractValue.cpp:
109
        (JSC::DFG::AbstractValue::setType):
110
        (JSC::DFG::AbstractValue::set):
111
        (JSC::DFG::AbstractValue::fixTypeForRepresentation):
112
        (JSC::DFG::AbstractValue::mergeOSREntryValue):
113
        (JSC::DFG::AbstractValue::isType):
114
        (JSC::DFG::AbstractValue::filter):
115
        (JSC::DFG::AbstractValue::filterValueByType):
116
        * dfg/DFGAbstractValue.h:
117
        (JSC::DFG::AbstractValue::setType):
118
        (JSC::DFG::AbstractValue::isType):
119
        (JSC::DFG::AbstractValue::validate):
120
        * dfg/DFGByteCodeParser.cpp:
121
        (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
122
        (JSC::DFG::ByteCodeParser::handleGetByOffset):
123
        (JSC::DFG::ByteCodeParser::handlePutByOffset):
124
        (JSC::DFG::ByteCodeParser::load):
125
        (JSC::DFG::ByteCodeParser::store):
126
        (JSC::DFG::ByteCodeParser::handleGetById):
127
        (JSC::DFG::ByteCodeParser::handlePutById):
128
        * dfg/DFGClobbersExitState.cpp:
129
        (JSC::DFG::clobbersExitState):
130
        * dfg/DFGConstantFoldingPhase.cpp:
131
        (JSC::DFG::ConstantFoldingPhase::foldConstants):
132
        (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
133
        (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
134
        (JSC::DFG::ConstantFoldingPhase::addBaseCheck):
135
        * dfg/DFGDesiredInferredType.h: Added.
136
        (JSC::DFG::DesiredInferredType::DesiredInferredType):
137
        (JSC::DFG::DesiredInferredType::operator bool):
138
        (JSC::DFG::DesiredInferredType::object):
139
        (JSC::DFG::DesiredInferredType::expected):
140
        (JSC::DFG::DesiredInferredType::isStillValid):
141
        (JSC::DFG::DesiredInferredType::add):
142
        (JSC::DFG::DesiredInferredType::operator==):
143
        (JSC::DFG::DesiredInferredType::operator!=):
144
        (JSC::DFG::DesiredInferredType::isHashTableDeletedValue):
145
        (JSC::DFG::DesiredInferredType::hash):
146
        (JSC::DFG::DesiredInferredType::dumpInContext):
147
        (JSC::DFG::DesiredInferredType::dump):
148
        (JSC::DFG::DesiredInferredTypeHash::hash):
149
        (JSC::DFG::DesiredInferredTypeHash::equal):
150
        * dfg/DFGDesiredWatchpoints.cpp:
151
        (JSC::DFG::AdaptiveStructureWatchpointAdaptor::add):
152
        (JSC::DFG::InferredTypeAdaptor::add):
153
        (JSC::DFG::DesiredWatchpoints::DesiredWatchpoints):
154
        (JSC::DFG::DesiredWatchpoints::~DesiredWatchpoints):
155
        (JSC::DFG::DesiredWatchpoints::addLazily):
156
        (JSC::DFG::DesiredWatchpoints::consider):
157
        (JSC::DFG::DesiredWatchpoints::reallyAdd):
158
        (JSC::DFG::DesiredWatchpoints::areStillValid):
159
        (JSC::DFG::DesiredWatchpoints::dumpInContext):
160
        * dfg/DFGDesiredWatchpoints.h:
161
        (JSC::DFG::AdaptiveStructureWatchpointAdaptor::dumpInContext):
162
        (JSC::DFG::InferredTypeAdaptor::hasBeenInvalidated):
163
        (JSC::DFG::InferredTypeAdaptor::dumpInContext):
164
        (JSC::DFG::DesiredWatchpoints::isWatched):
165
        * dfg/DFGFixupPhase.cpp:
166
        (JSC::DFG::FixupPhase::fixupNode):
167
        * dfg/DFGGraph.cpp:
168
        (JSC::DFG::Graph::dump):
169
        (JSC::DFG::Graph::isSafeToLoad):
170
        (JSC::DFG::Graph::inferredTypeFor):
171
        (JSC::DFG::Graph::livenessFor):
172
        (JSC::DFG::Graph::tryGetConstantProperty):
173
        (JSC::DFG::Graph::inferredValueForProperty):
174
        (JSC::DFG::Graph::tryGetConstantClosureVar):
175
        * dfg/DFGGraph.h:
176
        (JSC::DFG::Graph::registerInferredType):
177
        (JSC::DFG::Graph::inferredTypeForProperty):
178
        * dfg/DFGInferredTypeCheck.cpp: Added.
179
        (JSC::DFG::insertInferredTypeCheck):
180
        * dfg/DFGInferredTypeCheck.h: Added.
181
        * dfg/DFGNode.h:
182
        * dfg/DFGObjectAllocationSinkingPhase.cpp:
183
        * dfg/DFGPropertyTypeKey.h: Added.
184
        (JSC::DFG::PropertyTypeKey::PropertyTypeKey):
185
        (JSC::DFG::PropertyTypeKey::operator bool):
186
        (JSC::DFG::PropertyTypeKey::structure):
187
        (JSC::DFG::PropertyTypeKey::uid):
188
        (JSC::DFG::PropertyTypeKey::operator==):
189
        (JSC::DFG::PropertyTypeKey::operator!=):
190
        (JSC::DFG::PropertyTypeKey::hash):
191
        (JSC::DFG::PropertyTypeKey::isHashTableDeletedValue):
192
        (JSC::DFG::PropertyTypeKey::dumpInContext):
193
        (JSC::DFG::PropertyTypeKey::dump):
194
        (JSC::DFG::PropertyTypeKey::deletedUID):
195
        (JSC::DFG::PropertyTypeKeyHash::hash):
196
        (JSC::DFG::PropertyTypeKeyHash::equal):
197
        * dfg/DFGSafeToExecute.h:
198
        (JSC::DFG::SafeToExecuteEdge::operator()):
199
        (JSC::DFG::safeToExecute):
200
        * dfg/DFGSpeculativeJIT.cpp:
201
        (JSC::DFG::SpeculativeJIT::compileTypeOf):
202
        (JSC::DFG::SpeculativeJIT::compileCheckStructure):
203
        (JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
204
        (JSC::DFG::SpeculativeJIT::speculateCell):
205
        (JSC::DFG::SpeculativeJIT::speculateCellOrOther):
206
        (JSC::DFG::SpeculativeJIT::speculateObject):
207
        (JSC::DFG::SpeculativeJIT::speculate):
208
        * dfg/DFGSpeculativeJIT.h:
209
        * dfg/DFGSpeculativeJIT32_64.cpp:
210
        (JSC::DFG::SpeculativeJIT::compile):
211
        * dfg/DFGSpeculativeJIT64.cpp:
212
        (JSC::DFG::SpeculativeJIT::compile):
213
        * dfg/DFGStoreBarrierInsertionPhase.cpp:
214
        * dfg/DFGStructureAbstractValue.h:
215
        (JSC::DFG::StructureAbstractValue::at):
216
        (JSC::DFG::StructureAbstractValue::operator[]):
217
        (JSC::DFG::StructureAbstractValue::onlyStructure):
218
        (JSC::DFG::StructureAbstractValue::forEach):
219
        * dfg/DFGUseKind.cpp:
220
        (WTF::printInternal):
221
        * dfg/DFGUseKind.h:
222
        (JSC::DFG::typeFilterFor):
223
        * dfg/DFGValidate.cpp:
224
        (JSC::DFG::Validate::validate):
225
        * ftl/FTLCapabilities.cpp:
226
        (JSC::FTL::canCompile):
227
        * ftl/FTLLowerDFGToLLVM.cpp:
228
        (JSC::FTL::DFG::LowerDFGToLLVM::compileCheckStructure):
229
        (JSC::FTL::DFG::LowerDFGToLLVM::compileCheckCell):
230
        (JSC::FTL::DFG::LowerDFGToLLVM::compileMultiPutByOffset):
231
        (JSC::FTL::DFG::LowerDFGToLLVM::numberOrNotCellToInt32):
232
        (JSC::FTL::DFG::LowerDFGToLLVM::checkInferredType):
233
        (JSC::FTL::DFG::LowerDFGToLLVM::loadProperty):
234
        (JSC::FTL::DFG::LowerDFGToLLVM::speculate):
235
        (JSC::FTL::DFG::LowerDFGToLLVM::speculateCell):
236
        (JSC::FTL::DFG::LowerDFGToLLVM::speculateCellOrOther):
237
        (JSC::FTL::DFG::LowerDFGToLLVM::speculateMachineInt):
238
        (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExit):
239
        * jit/AssemblyHelpers.cpp:
240
        (JSC::AssemblyHelpers::decodedCodeMapFor):
241
        (JSC::AssemblyHelpers::branchIfNotType):
242
        (JSC::AssemblyHelpers::purifyNaN):
243
        * jit/AssemblyHelpers.h:
244
        (JSC::AssemblyHelpers::branchIfEqual):
245
        (JSC::AssemblyHelpers::branchIfNotCell):
246
        (JSC::AssemblyHelpers::branchIfCell):
247
        (JSC::AssemblyHelpers::branchIfNotOther):
248
        (JSC::AssemblyHelpers::branchIfInt32):
249
        (JSC::AssemblyHelpers::branchIfNotInt32):
250
        (JSC::AssemblyHelpers::branchIfNumber):
251
        (JSC::AssemblyHelpers::branchIfNotNumber):
252
        (JSC::AssemblyHelpers::branchIfEmpty):
253
        (JSC::AssemblyHelpers::branchStructure):
254
        * jit/Repatch.cpp:
255
        (JSC::tryCachePutByID):
256
        * llint/LLIntSlowPaths.cpp:
257
        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
258
        * llint/LowLevelInterpreter.asm:
259
        * llint/LowLevelInterpreter32_64.asm:
260
        * llint/LowLevelInterpreter64.asm:
261
        * runtime/InferredType.cpp: Added.
262
        (JSC::InferredType::create):
263
        (JSC::InferredType::destroy):
264
        (JSC::InferredType::createStructure):
265
        (JSC::InferredType::visitChildren):
266
        (JSC::InferredType::kindForFlags):
267
        (JSC::InferredType::Descriptor::forValue):
268
        (JSC::InferredType::Descriptor::forFlags):
269
        (JSC::InferredType::Descriptor::putByIdFlags):
270
        (JSC::InferredType::Descriptor::merge):
271
        (JSC::InferredType::Descriptor::removeStructure):
272
        (JSC::InferredType::Descriptor::subsumes):
273
        (JSC::InferredType::Descriptor::dumpInContext):
274
        (JSC::InferredType::Descriptor::dump):
275
        (JSC::InferredType::InferredType):
276
        (JSC::InferredType::~InferredType):
277
        (JSC::InferredType::canWatch):
278
        (JSC::InferredType::addWatchpoint):
279
        (JSC::InferredType::dump):
280
        (JSC::InferredType::willStoreValueSlow):
281
        (JSC::InferredType::makeTopSlow):
282
        (JSC::InferredType::set):
283
        (JSC::InferredType::removeStructure):
284
        (JSC::InferredType::InferredStructureWatchpoint::fireInternal):
285
        (JSC::InferredType::InferredStructureFinalizer::finalizeUnconditionally):
286
        (JSC::InferredType::InferredStructure::InferredStructure):
287
        (WTF::printInternal):
288
        * runtime/InferredType.h: Added.
289
        * runtime/InferredTypeTable.cpp: Added.
290
        (JSC::InferredTypeTable::create):
291
        (JSC::InferredTypeTable::destroy):
292
        (JSC::InferredTypeTable::createStructure):
293
        (JSC::InferredTypeTable::visitChildren):
294
        (JSC::InferredTypeTable::get):
295
        (JSC::InferredTypeTable::willStoreValue):
296
        (JSC::InferredTypeTable::makeTop):
297
        (JSC::InferredTypeTable::InferredTypeTable):
298
        (JSC::InferredTypeTable::~InferredTypeTable):
299
        * runtime/InferredTypeTable.h: Added.
300
        * runtime/JSObject.h:
301
        (JSC::JSObject::putDirectInternal):
302
        (JSC::JSObject::putDirectWithoutTransition):
303
        * runtime/Structure.cpp:
304
        (JSC::Structure::materializePropertyMap):
305
        (JSC::Structure::addPropertyTransition):
306
        (JSC::Structure::removePropertyTransition):
307
        (JSC::Structure::startWatchingInternalProperties):
308
        (JSC::Structure::willStoreValueSlow):
309
        (JSC::Structure::visitChildren):
310
        (JSC::Structure::prototypeChainMayInterceptStoreTo):
311
        * runtime/Structure.h:
312
        (JSC::PropertyMapEntry::PropertyMapEntry):
313
        * runtime/StructureInlines.h:
314
        (JSC::Structure::get):
315
        * runtime/VM.cpp:
316
        (JSC::VM::VM):
317
        * runtime/VM.h:
318
        * tests/stress/prop-type-boolean-then-string.js: Added.
319
        * tests/stress/prop-type-int32-then-string.js: Added.
320
        * tests/stress/prop-type-number-then-string.js: Added.
321
        * tests/stress/prop-type-object-or-other-then-string.js: Added.
322
        * tests/stress/prop-type-object-then-string.js: Added.
323
        * tests/stress/prop-type-other-then-string.js: Added.
324
        * tests/stress/prop-type-string-then-object.js: Added.
325
        * tests/stress/prop-type-struct-or-other-then-string.js: Added.
326
        * tests/stress/prop-type-struct-then-object.js: Added.
327
        * tests/stress/prop-type-struct-then-object-opt.js: Added.
328
        * tests/stress/prop-type-struct-then-object-opt-fold.js: Added.
329
        * tests/stress/prop-type-struct-then-object-opt-multi.js: Added.
330
1
2015-09-20  Sukolsak Sakshuwong  <sukolsak@gmail.com>
331
2015-09-20  Sukolsak Sakshuwong  <sukolsak@gmail.com>
2
332
3
        Implement SetLocal and SetGlobal expressions in WebAssembly
333
        Implement SetLocal and SetGlobal expressions in WebAssembly
- Source/JavaScriptCore/CMakeLists.txt +3 lines
Lines 192-197 set(JavaScriptCore_SOURCES Source/JavaScriptCore/CMakeLists.txt_sec1
192
    dfg/DFGGraphSafepoint.cpp
192
    dfg/DFGGraphSafepoint.cpp
193
    dfg/DFGHeapLocation.cpp
193
    dfg/DFGHeapLocation.cpp
194
    dfg/DFGInPlaceAbstractState.cpp
194
    dfg/DFGInPlaceAbstractState.cpp
195
    dfg/DFGInferredTypeCheck.cpp
195
    dfg/DFGInsertionSet.cpp
196
    dfg/DFGInsertionSet.cpp
196
    dfg/DFGIntegerCheckCombiningPhase.cpp
197
    dfg/DFGIntegerCheckCombiningPhase.cpp
197
    dfg/DFGIntegerRangeOptimizationPhase.cpp
198
    dfg/DFGIntegerRangeOptimizationPhase.cpp
Lines 501-506 set(JavaScriptCore_RUNTIME_SOURCES Source/JavaScriptCore/CMakeLists.txt_sec2
501
    runtime/Identifier.cpp
502
    runtime/Identifier.cpp
502
    runtime/IndexingType.cpp
503
    runtime/IndexingType.cpp
503
    runtime/InferredValue.cpp
504
    runtime/InferredValue.cpp
505
    runtime/InferredType.cpp
506
    runtime/InferredTypeTable.cpp
504
    runtime/InitializeThreading.cpp
507
    runtime/InitializeThreading.cpp
505
    runtime/InspectorInstrumentationObject.cpp
508
    runtime/InspectorInstrumentationObject.cpp
506
    runtime/InternalFunction.cpp
509
    runtime/InternalFunction.cpp
- Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj +8 lines
Lines 428-433 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj_sec1
428
    <ClCompile Include="..\dfg\DFGGraphSafepoint.cpp" />
428
    <ClCompile Include="..\dfg\DFGGraphSafepoint.cpp" />
429
    <ClCompile Include="..\dfg\DFGHeapLocation.cpp" />
429
    <ClCompile Include="..\dfg\DFGHeapLocation.cpp" />
430
    <ClCompile Include="..\dfg\DFGInPlaceAbstractState.cpp" />
430
    <ClCompile Include="..\dfg\DFGInPlaceAbstractState.cpp" />
431
    <ClCompile Include="..\dfg\DFGInferredTypeCheck.cpp" />
431
    <ClCompile Include="..\dfg\DFGInsertionSet.cpp" />
432
    <ClCompile Include="..\dfg\DFGInsertionSet.cpp" />
432
    <ClCompile Include="..\dfg\DFGIntegerCheckCombiningPhase.cpp" />
433
    <ClCompile Include="..\dfg\DFGIntegerCheckCombiningPhase.cpp" />
433
    <ClCompile Include="..\dfg\DFGIntegerRangeOptimizationPhase.cpp" />
434
    <ClCompile Include="..\dfg\DFGIntegerRangeOptimizationPhase.cpp" />
Lines 750-755 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj_sec2
750
    <ClCompile Include="..\runtime\Identifier.cpp" />
751
    <ClCompile Include="..\runtime\Identifier.cpp" />
751
    <ClCompile Include="..\runtime\IndexingType.cpp" />
752
    <ClCompile Include="..\runtime\IndexingType.cpp" />
752
    <ClCompile Include="..\runtime\InferredValue.cpp" />
753
    <ClCompile Include="..\runtime\InferredValue.cpp" />
754
    <ClCompile Include="..\runtime\InferredType.cpp" />
755
    <ClCompile Include="..\runtime\InferredTypeTable.cpp" />
753
    <ClCompile Include="..\runtime\InitializeThreading.cpp" />
756
    <ClCompile Include="..\runtime\InitializeThreading.cpp" />
754
    <ClCompile Include="..\runtime\InspectorInstrumentationObject.cpp" />
757
    <ClCompile Include="..\runtime\InspectorInstrumentationObject.cpp" />
755
    <ClCompile Include="..\runtime\InternalFunction.cpp" />
758
    <ClCompile Include="..\runtime\InternalFunction.cpp" />
Lines 1137-1142 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj_sec3
1137
    <ClInclude Include="..\dfg\DFGCSEPhase.h" />
1140
    <ClInclude Include="..\dfg\DFGCSEPhase.h" />
1138
    <ClInclude Include="..\dfg\DFGDCEPhase.h" />
1141
    <ClInclude Include="..\dfg\DFGDCEPhase.h" />
1139
    <ClInclude Include="..\dfg\DFGDesiredIdentifiers.h" />
1142
    <ClInclude Include="..\dfg\DFGDesiredIdentifiers.h" />
1143
    <ClInclude Include="..\dfg\DFGDesiredInferredType.h" />
1140
    <ClInclude Include="..\dfg\DFGDesiredTransitions.h" />
1144
    <ClInclude Include="..\dfg\DFGDesiredTransitions.h" />
1141
    <ClInclude Include="..\dfg\DFGDesiredWatchpoints.h" />
1145
    <ClInclude Include="..\dfg\DFGDesiredWatchpoints.h" />
1142
    <ClInclude Include="..\dfg\DFGDesiredWeakReferences.h" />
1146
    <ClInclude Include="..\dfg\DFGDesiredWeakReferences.h" />
Lines 1166-1171 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj_sec4
1166
    <ClInclude Include="..\dfg\DFGGraphSafepoint.h" />
1170
    <ClInclude Include="..\dfg\DFGGraphSafepoint.h" />
1167
    <ClInclude Include="..\dfg\DFGHeapLocation.h" />
1171
    <ClInclude Include="..\dfg\DFGHeapLocation.h" />
1168
    <ClInclude Include="..\dfg\DFGInPlaceAbstractState.h" />
1172
    <ClInclude Include="..\dfg\DFGInPlaceAbstractState.h" />
1173
    <ClInclude Include="..\dfg\DFGInferredTypeCheck.h" />
1169
    <ClInclude Include="..\dfg\DFGInsertionSet.h" />
1174
    <ClInclude Include="..\dfg\DFGInsertionSet.h" />
1170
    <ClInclude Include="..\dfg\DFGIntegerCheckCombiningPhase.h" />
1175
    <ClInclude Include="..\dfg\DFGIntegerCheckCombiningPhase.h" />
1171
    <ClInclude Include="..\dfg\DFGIntegerRangeOptimizationPhase.h" />
1176
    <ClInclude Include="..\dfg\DFGIntegerRangeOptimizationPhase.h" />
Lines 1217-1222 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj_sec5
1217
    <ClInclude Include="..\dfg\DFGPredictionInjectionPhase.h" />
1222
    <ClInclude Include="..\dfg\DFGPredictionInjectionPhase.h" />
1218
    <ClInclude Include="..\dfg\DFGPredictionPropagationPhase.h" />
1223
    <ClInclude Include="..\dfg\DFGPredictionPropagationPhase.h" />
1219
    <ClInclude Include="..\dfg\DFGPromotedHeapLocation.h" />
1224
    <ClInclude Include="..\dfg\DFGPromotedHeapLocation.h" />
1225
    <ClInclude Include="..\dfg\DFGPropertyTypeKey.h" />
1220
    <ClInclude Include="..\dfg\DFGPureValue.h" />
1226
    <ClInclude Include="..\dfg\DFGPureValue.h" />
1221
    <ClInclude Include="..\dfg\DFGPutStackSinkingPhase.h" />
1227
    <ClInclude Include="..\dfg\DFGPutStackSinkingPhase.h" />
1222
    <ClInclude Include="..\dfg\DFGRegisterBank.h" />
1228
    <ClInclude Include="..\dfg\DFGRegisterBank.h" />
Lines 1591-1596 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj_sec6
1591
    <ClInclude Include="..\runtime\IndexingHeaderInlines.h" />
1597
    <ClInclude Include="..\runtime\IndexingHeaderInlines.h" />
1592
    <ClInclude Include="..\runtime\IndexingType.h" />
1598
    <ClInclude Include="..\runtime\IndexingType.h" />
1593
    <ClInclude Include="..\runtime\InferredValue.h" />
1599
    <ClInclude Include="..\runtime\InferredValue.h" />
1600
    <ClInclude Include="..\runtime\InferredType.h" />
1601
    <ClInclude Include="..\runtime\InferredTypeTable.h" />
1594
    <ClInclude Include="..\runtime\InitializeThreading.h" />
1602
    <ClInclude Include="..\runtime\InitializeThreading.h" />
1595
    <ClInclude Include="..\runtime\Int16Array.h" />
1603
    <ClInclude Include="..\runtime\Int16Array.h" />
1596
    <ClInclude Include="..\runtime\Int32Array.h" />
1604
    <ClInclude Include="..\runtime\Int32Array.h" />
- Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters +16 lines
Lines 1269-1274 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters_sec1
1269
    <ClCompile Include="..\dfg\DFGInPlaceAbstractState.cpp">
1269
    <ClCompile Include="..\dfg\DFGInPlaceAbstractState.cpp">
1270
      <Filter>dfg</Filter>
1270
      <Filter>dfg</Filter>
1271
    </ClCompile>
1271
    </ClCompile>
1272
    <ClCompile Include="..\dfg\DFGInferredTypeCheck.cpp">
1273
      <Filter>dfg</Filter>
1274
    </ClCompile>
1272
    <ClCompile Include="..\dfg\DFGInvalidationPointInjectionPhase.cpp">
1275
    <ClCompile Include="..\dfg\DFGInvalidationPointInjectionPhase.cpp">
1273
      <Filter>dfg</Filter>
1276
      <Filter>dfg</Filter>
1274
    </ClCompile>
1277
    </ClCompile>
Lines 1866-1871 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters_sec2
1866
    <ClCompile Include="..\runtime\DirectArguments.cpp" />
1869
    <ClCompile Include="..\runtime\DirectArguments.cpp" />
1867
    <ClCompile Include="..\runtime\DirectArgumentsOffset.cpp" />
1870
    <ClCompile Include="..\runtime\DirectArgumentsOffset.cpp" />
1868
    <ClCompile Include="..\runtime\InferredValue.cpp" />
1871
    <ClCompile Include="..\runtime\InferredValue.cpp" />
1872
    <ClCompile Include="..\runtime\InferredType.cpp" />
1873
    <ClCompile Include="..\runtime\InferredTypeTable.cpp" />
1869
    <ClCompile Include="..\runtime\ScopeOffset.cpp" />
1874
    <ClCompile Include="..\runtime\ScopeOffset.cpp" />
1870
    <ClCompile Include="..\runtime\ScopedArguments.cpp" />
1875
    <ClCompile Include="..\runtime\ScopedArguments.cpp" />
1871
    <ClCompile Include="..\runtime\ScopedArgumentsTable.cpp" />
1876
    <ClCompile Include="..\runtime\ScopedArgumentsTable.cpp" />
Lines 3676-3681 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters_sec3
3676
    <ClInclude Include="..\dfg\DFGDesiredIdentifiers.h">
3681
    <ClInclude Include="..\dfg\DFGDesiredIdentifiers.h">
3677
      <Filter>dfg</Filter>
3682
      <Filter>dfg</Filter>
3678
    </ClInclude>
3683
    </ClInclude>
3684
    <ClInclude Include="..\dfg\DFGDesiredInferredType.h">
3685
      <Filter>dfg</Filter>
3686
    </ClInclude>
3679
    <ClInclude Include="..\dfg\DFGDesiredTransitions.h">
3687
    <ClInclude Include="..\dfg\DFGDesiredTransitions.h">
3680
      <Filter>dfg</Filter>
3688
      <Filter>dfg</Filter>
3681
    </ClInclude>
3689
    </ClInclude>
Lines 3742-3747 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters_sec4
3742
    <ClInclude Include="..\dfg\DFGInPlaceAbstractState.h">
3750
    <ClInclude Include="..\dfg\DFGInPlaceAbstractState.h">
3743
      <Filter>dfg</Filter>
3751
      <Filter>dfg</Filter>
3744
    </ClInclude>
3752
    </ClInclude>
3753
    <ClInclude Include="..\dfg\DFGInferredTypeCheck.h">
3754
      <Filter>dfg</Filter>
3755
    </ClInclude>
3745
    <ClInclude Include="..\dfg\DFGInvalidationPointInjectionPhase.h">
3756
    <ClInclude Include="..\dfg\DFGInvalidationPointInjectionPhase.h">
3746
      <Filter>dfg</Filter>
3757
      <Filter>dfg</Filter>
3747
    </ClInclude>
3758
    </ClInclude>
Lines 4424-4429 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters_sec5
4424
    <ClInclude Include="..\dfg\DFGPromotedHeapLocation.h">
4435
    <ClInclude Include="..\dfg\DFGPromotedHeapLocation.h">
4425
      <Filter>dfg</Filter>
4436
      <Filter>dfg</Filter>
4426
    </ClInclude>
4437
    </ClInclude>
4438
    <ClInclude Include="..\dfg\DFGPropertyTypeKey.h">
4439
      <Filter>dfg</Filter>
4440
    </ClInclude>
4427
    <ClInclude Include="..\ftl\FTLExitPropertyValue.h">
4441
    <ClInclude Include="..\ftl\FTLExitPropertyValue.h">
4428
      <Filter>ftl</Filter>
4442
      <Filter>ftl</Filter>
4429
    </ClInclude>
4443
    </ClInclude>
Lines 4467-4472 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters_sec6
4467
    <ClInclude Include="..\runtime\GenericArgumentsInlines.h" />
4481
    <ClInclude Include="..\runtime\GenericArgumentsInlines.h" />
4468
    <ClInclude Include="..\runtime\GenericOffset.h" />
4482
    <ClInclude Include="..\runtime\GenericOffset.h" />
4469
    <ClInclude Include="..\runtime\InferredValue.h" />
4483
    <ClInclude Include="..\runtime\InferredValue.h" />
4484
    <ClInclude Include="..\runtime\InferredType.h" />
4485
    <ClInclude Include="..\runtime\InferredTypeTable.h" />
4470
    <ClInclude Include="..\runtime\ScopeOffset.h" />
4486
    <ClInclude Include="..\runtime\ScopeOffset.h" />
4471
    <ClInclude Include="..\runtime\ScopedArguments.h" />
4487
    <ClInclude Include="..\runtime\ScopedArguments.h" />
4472
    <ClInclude Include="..\runtime\ScopedArgumentsTable.h" />
4488
    <ClInclude Include="..\runtime\ScopedArgumentsTable.h" />
- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj -6 / +38 lines
Lines 86-91 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
86
		0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */; settings = {ATTRIBUTES = (Private, ); }; };
86
		0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */; settings = {ATTRIBUTES = (Private, ); }; };
87
		0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
87
		0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
88
		0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
88
		0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
89
		0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0A75201B94BFA900110660 /* InferredType.cpp */; };
90
		0F0A75231B94BFA900110660 /* InferredType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0A75211B94BFA900110660 /* InferredType.h */; settings = {ATTRIBUTES = (Private, ); }; };
89
		0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
91
		0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
90
		0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839814BCF45A00885B4F /* LLIntThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
92
		0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839814BCF45A00885B4F /* LLIntThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
91
		0F0B83A714BCF50700885B4F /* CodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A514BCF50400885B4F /* CodeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
93
		0F0B83A714BCF50700885B4F /* CodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A514BCF50400885B4F /* CodeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 543-548 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
543
		0FC712E317CD8793008CC93C /* JITToDFGDeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
545
		0FC712E317CD8793008CC93C /* JITToDFGDeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
544
		0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */; settings = {ATTRIBUTES = (Private, ); }; };
546
		0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */; settings = {ATTRIBUTES = (Private, ); }; };
545
		0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */; };
547
		0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */; };
548
		0FC841681BA8C3210061837D /* DFGInferredTypeCheck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC841661BA8C3210061837D /* DFGInferredTypeCheck.cpp */; };
549
		0FC841691BA8C3210061837D /* DFGInferredTypeCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC841671BA8C3210061837D /* DFGInferredTypeCheck.h */; settings = {ATTRIBUTES = (Private, ); }; };
546
		0FC97F33182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */; };
550
		0FC97F33182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */; };
547
		0FC97F34182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
551
		0FC97F34182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
548
		0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */; };
552
		0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */; };
Lines 742-747 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
742
		0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
746
		0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
743
		0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
747
		0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
744
		0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
748
		0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
749
		0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */; };
750
		0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
751
		0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */; settings = {ATTRIBUTES = (Private, ); }; };
752
		0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
745
		0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
753
		0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
746
		0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
754
		0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
747
		0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
755
		0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 1924-1929 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
1924
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1932
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1925
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1933
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1926
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1934
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1935
		0F0A75201B94BFA900110660 /* InferredType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredType.cpp; sourceTree = "<group>"; };
1936
		0F0A75211B94BFA900110660 /* InferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredType.h; sourceTree = "<group>"; };
1927
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1937
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1928
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1938
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1929
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
1939
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
Lines 2390-2395 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
2390
		0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JITToDFGDeferredCompilationCallback.h; sourceTree = "<group>"; };
2400
		0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JITToDFGDeferredCompilationCallback.h; sourceTree = "<group>"; };
2391
		0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierSupport.cpp; sourceTree = "<group>"; };
2401
		0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierSupport.cpp; sourceTree = "<group>"; };
2392
		0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierSupport.h; sourceTree = "<group>"; };
2402
		0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierSupport.h; sourceTree = "<group>"; };
2403
		0FC841661BA8C3210061837D /* DFGInferredTypeCheck.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInferredTypeCheck.cpp; path = dfg/DFGInferredTypeCheck.cpp; sourceTree = "<group>"; };
2404
		0FC841671BA8C3210061837D /* DFGInferredTypeCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInferredTypeCheck.h; path = dfg/DFGInferredTypeCheck.h; sourceTree = "<group>"; };
2393
		0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlockJettisoningWatchpoint.cpp; sourceTree = "<group>"; };
2405
		0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlockJettisoningWatchpoint.cpp; sourceTree = "<group>"; };
2394
		0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockJettisoningWatchpoint.h; sourceTree = "<group>"; };
2406
		0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockJettisoningWatchpoint.h; sourceTree = "<group>"; };
2395
		0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInvalidationPointInjectionPhase.cpp; path = dfg/DFGInvalidationPointInjectionPhase.cpp; sourceTree = "<group>"; };
2407
		0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInvalidationPointInjectionPhase.cpp; path = dfg/DFGInvalidationPointInjectionPhase.cpp; sourceTree = "<group>"; };
Lines 2577-2582 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec6
2577
		0FF9CE721B9CD6D0004EDCA6 /* PolymorphicAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicAccess.h; sourceTree = "<group>"; };
2589
		0FF9CE721B9CD6D0004EDCA6 /* PolymorphicAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicAccess.h; sourceTree = "<group>"; };
2578
		0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = "<group>"; };
2590
		0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = "<group>"; };
2579
		0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = "<group>"; };
2591
		0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = "<group>"; };
2592
		0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredTypeTable.cpp; sourceTree = "<group>"; };
2593
		0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredTypeTable.h; sourceTree = "<group>"; };
2594
		0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredInferredType.h; path = dfg/DFGDesiredInferredType.h; sourceTree = "<group>"; };
2595
		0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPropertyTypeKey.h; path = dfg/DFGPropertyTypeKey.h; sourceTree = "<group>"; };
2580
		0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
2596
		0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
2581
		0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; };
2597
		0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; };
2582
		0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = "<group>"; };
2598
		0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = "<group>"; };
Lines 4671-4678 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec7
4671
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4687
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4672
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4688
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4673
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4689
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4674
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4675
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4690
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4691
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4676
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4692
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4677
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4693
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4678
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
4694
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
Lines 4706-4711 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec8
4706
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4722
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4707
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4723
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4708
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4724
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4725
				0F0A75201B94BFA900110660 /* InferredType.cpp */,
4726
				0F0A75211B94BFA900110660 /* InferredType.h */,
4727
				0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */,
4728
				0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */,
4709
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4729
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4710
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4730
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4711
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
4731
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
Lines 4756-4765 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec9
4756
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4776
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4757
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4777
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4758
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4778
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4759
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4760
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4761
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4779
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4762
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4780
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4781
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4782
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4763
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4783
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4764
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4784
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4765
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
4785
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
Lines 5062-5070 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec10
5062
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5082
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5063
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5083
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5064
				E18E3A560DF9278C00D90B34 /* VM.h */,
5084
				E18E3A560DF9278C00D90B34 /* VM.h */,
5065
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5066
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5085
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5067
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5086
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5087
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5068
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5088
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5069
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5089
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5070
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
5090
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
Lines 5216-5221 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec11
5216
				0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
5236
				0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
5217
				0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
5237
				0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
5218
				0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
5238
				0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
5239
				0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */,
5219
				C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
5240
				C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
5220
				C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
5241
				C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
5221
				0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
5242
				0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
Lines 5262-5267 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec12
5262
				0F2FCCF318A60070001A27F8 /* DFGGraphSafepoint.h */,
5283
				0F2FCCF318A60070001A27F8 /* DFGGraphSafepoint.h */,
5263
				0FB1765C196B8F9E0091052A /* DFGHeapLocation.cpp */,
5284
				0FB1765C196B8F9E0091052A /* DFGHeapLocation.cpp */,
5264
				0FB1765D196B8F9E0091052A /* DFGHeapLocation.h */,
5285
				0FB1765D196B8F9E0091052A /* DFGHeapLocation.h */,
5286
				0FC841661BA8C3210061837D /* DFGInferredTypeCheck.cpp */,
5287
				0FC841671BA8C3210061837D /* DFGInferredTypeCheck.h */,
5265
				0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */,
5288
				0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */,
5266
				0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */,
5289
				0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */,
5267
				A704D90017A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp */,
5290
				A704D90017A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp */,
Lines 5294-5303 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec13
5294
				0FB4B51D16B62772003F696B /* DFGLongLivedState.h */,
5317
				0FB4B51D16B62772003F696B /* DFGLongLivedState.h */,
5295
				A767B5B317A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.cpp */,
5318
				A767B5B317A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.cpp */,
5296
				A767B5B417A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h */,
5319
				A767B5B417A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h */,
5297
				0F5874EB194FEB1200AAB2C1 /* DFGMayExit.cpp */,
5298
				0F5874EC194FEB1200AAB2C1 /* DFGMayExit.h */,
5299
				79F8FC1C1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp */,
5320
				79F8FC1C1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp */,
5300
				79F8FC1D1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h */,
5321
				79F8FC1D1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h */,
5322
				0F5874EB194FEB1200AAB2C1 /* DFGMayExit.cpp */,
5323
				0F5874EC194FEB1200AAB2C1 /* DFGMayExit.h */,
5301
				0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */,
5324
				0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */,
5302
				0F2BDC3D1522801700CD8910 /* DFGMinifiedGraph.h */,
5325
				0F2BDC3D1522801700CD8910 /* DFGMinifiedGraph.h */,
5303
				0FB4B51016B3A964003F696B /* DFGMinifiedID.h */,
5326
				0FB4B51016B3A964003F696B /* DFGMinifiedID.h */,
Lines 5365-5370 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec14
5365
				0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */,
5388
				0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */,
5366
				0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */,
5389
				0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */,
5367
				0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */,
5390
				0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */,
5391
				0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */,
5368
				0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
5392
				0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
5369
				0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
5393
				0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
5370
				0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
5394
				0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
Lines 5957-5962 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec15
5957
				FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */,
5981
				FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */,
5958
				C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
5982
				C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
5959
				FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */,
5983
				FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */,
5984
				0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */,
5960
				79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
5985
				79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
5961
				52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
5986
				52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
5962
				52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
5987
				52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
Lines 6071-6076 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec16
6071
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6096
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6072
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6097
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6073
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6098
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6099
				0F0A75231B94BFA900110660 /* InferredType.h in Headers */,
6074
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6100
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6075
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6101
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6076
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
6102
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
Lines 6351-6362 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec17
6351
				0F25F1B4181635F300522F39 /* FTLSlowPathCallKey.h in Headers */,
6377
				0F25F1B4181635F300522F39 /* FTLSlowPathCallKey.h in Headers */,
6352
				0F9D339B1803ADB70073C2BC /* FTLStackMaps.h in Headers */,
6378
				0F9D339B1803ADB70073C2BC /* FTLStackMaps.h in Headers */,
6353
				0FEA0A12170513DB00BB722C /* FTLState.h in Headers */,
6379
				0FEA0A12170513DB00BB722C /* FTLState.h in Headers */,
6380
				0FC841691BA8C3210061837D /* DFGInferredTypeCheck.h in Headers */,
6354
				A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */,
6381
				A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */,
6355
				0F235BE217178E1C00690C7F /* FTLThunks.h in Headers */,
6382
				0F235BE217178E1C00690C7F /* FTLThunks.h in Headers */,
6356
				0FEA0A201708B00700BB722C /* FTLTypedPointer.h in Headers */,
6383
				0FEA0A201708B00700BB722C /* FTLTypedPointer.h in Headers */,
6357
				0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */,
6384
				0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */,
6358
				0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
6385
				0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
6359
				0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */,
6386
				0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */,
6387
				0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */,
6360
				0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
6388
				0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
6361
				0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
6389
				0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
6362
				0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
6390
				0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
Lines 6521-6526 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec18
6521
				BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
6549
				BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
6522
				A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
6550
				A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
6523
				0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
6551
				0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
6552
				0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */,
6524
				0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
6553
				0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
6525
				0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
6554
				0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
6526
				0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
6555
				0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
Lines 7463-7468 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec19
7463
				1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
7492
				1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
7464
				A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
7493
				A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
7465
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
7494
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
7495
				0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */,
7466
				2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
7496
				2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
7467
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
7497
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
7468
				0F2B66DE17B6B5AB00A7AE3F /* DataView.cpp in Sources */,
7498
				0F2B66DE17B6B5AB00A7AE3F /* DataView.cpp in Sources */,
Lines 7847-7852 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec20
7847
				0FF054F91AC35B4400E5BE57 /* ExecutableAllocationFuzz.cpp in Sources */,
7877
				0FF054F91AC35B4400E5BE57 /* ExecutableAllocationFuzz.cpp in Sources */,
7848
				86E3C61A167BABEE006D760A /* JSValue.mm in Sources */,
7878
				86E3C61A167BABEE006D760A /* JSValue.mm in Sources */,
7849
				0FF8BDEA1AD4CF7100DFE884 /* InferredValue.cpp in Sources */,
7879
				0FF8BDEA1AD4CF7100DFE884 /* InferredValue.cpp in Sources */,
7880
				0FC841681BA8C3210061837D /* DFGInferredTypeCheck.cpp in Sources */,
7850
				0F8F14351ADF090100ED792C /* DFGMovHintRemovalPhase.cpp in Sources */,
7881
				0F8F14351ADF090100ED792C /* DFGMovHintRemovalPhase.cpp in Sources */,
7851
				14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */,
7882
				14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */,
7852
				147F39D7107EC37600427A48 /* JSEnvironmentRecord.cpp in Sources */,
7883
				147F39D7107EC37600427A48 /* JSEnvironmentRecord.cpp in Sources */,
Lines 7881-7886 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec21
7881
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7912
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7882
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7913
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7883
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7914
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7915
				0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */,
7884
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7916
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7885
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7917
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7886
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
7918
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
- Source/JavaScriptCore/assembler/MacroAssemblerARM64.h -1 / +7 lines
Lines 1-5 Source/JavaScriptCore/assembler/MacroAssemblerARM64.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
2
 * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 1853-1858 public: Source/JavaScriptCore/assembler/MacroAssemblerARM64.h_sec2
1853
        return Jump(makeBranch(cond));
1853
        return Jump(makeBranch(cond));
1854
    }
1854
    }
1855
1855
1856
    Jump branchTest64(ResultCondition cond, RegisterID reg, TrustedImm64 mask)
1857
    {
1858
        move(mask, getCachedDataTempRegisterIDAndInvalidate());
1859
        return branchTest64(cond, reg, dataTempRegister);
1860
    }
1861
1856
    Jump branchTest64(ResultCondition cond, Address address, RegisterID mask)
1862
    Jump branchTest64(ResultCondition cond, Address address, RegisterID mask)
1857
    {
1863
    {
1858
        load64(address, getCachedDataTempRegisterIDAndInvalidate());
1864
        load64(address, getCachedDataTempRegisterIDAndInvalidate());
- Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h +6 lines
Lines 605-610 public: Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h_sec1
605
        return Jump(m_assembler.jCC(x86Condition(cond)));
605
        return Jump(m_assembler.jCC(x86Condition(cond)));
606
    }
606
    }
607
607
608
    Jump branchTest64(ResultCondition cond, RegisterID reg, TrustedImm64 mask)
609
    {
610
        move(mask, scratchRegister);
611
        return branchTest64(cond, reg, scratchRegister);
612
    }
613
608
    void test64(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
614
    void test64(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
609
    {
615
    {
610
        if (mask.m_value == -1)
616
        if (mask.m_value == -1)
- Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp +18 lines
Lines 691-696 void AccessCase::generate(AccessGenerati Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp_sec1
691
    }
691
    }
692
692
693
    case Replace: {
693
    case Replace: {
694
        if (InferredType* type = structure()->inferredTypeFor(ident.impl())) {
695
            if (verbose)
696
                dataLog("Have type: ", type->descriptor(), "\n");
697
            state.failAndRepatch.append(
698
                jit.branchIfNotType(
699
                    valueRegs, scratchGPR, type->descriptor(), CCallHelpers::DoNotHaveTagRegisters));
700
        } else if (verbose)
701
            dataLog("Don't have type.\n");
702
        
694
        if (isInlineOffset(m_offset)) {
703
        if (isInlineOffset(m_offset)) {
695
            jit.storeValue(
704
            jit.storeValue(
696
                valueRegs,
705
                valueRegs,
Lines 714-719 void AccessCase::generate(AccessGenerati Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp_sec2
714
        RELEASE_ASSERT(GPRInfo::numberOfRegisters >= 6 || !structure()->outOfLineCapacity() || structure()->outOfLineCapacity() == newStructure()->outOfLineCapacity());
723
        RELEASE_ASSERT(GPRInfo::numberOfRegisters >= 6 || !structure()->outOfLineCapacity() || structure()->outOfLineCapacity() == newStructure()->outOfLineCapacity());
715
        RELEASE_ASSERT(!structure()->couldHaveIndexingHeader());
724
        RELEASE_ASSERT(!structure()->couldHaveIndexingHeader());
716
725
726
        if (InferredType* type = newStructure()->inferredTypeFor(ident.impl())) {
727
            if (verbose)
728
                dataLog("Have type: ", type->descriptor(), "\n");
729
            state.failAndRepatch.append(
730
                jit.branchIfNotType(
731
                    valueRegs, scratchGPR, type->descriptor(), CCallHelpers::DoNotHaveTagRegisters));
732
        } else if (verbose)
733
            dataLog("Don't have type.\n");
734
        
717
        CCallHelpers::JumpList slowPath;
735
        CCallHelpers::JumpList slowPath;
718
736
719
        ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters);
737
        ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters);
- Source/JavaScriptCore/bytecode/PutByIdFlags.cpp -7 / +6 lines
Lines 26-31 Source/JavaScriptCore/bytecode/PutByIdFlags.cpp_sec1
26
#include "config.h"
26
#include "config.h"
27
#include "PutByIdFlags.h"
27
#include "PutByIdFlags.h"
28
28
29
#include "InferredType.h"
29
#include <wtf/CommaPrinter.h>
30
#include <wtf/CommaPrinter.h>
30
#include <wtf/PrintStream.h>
31
#include <wtf/PrintStream.h>
31
#include <wtf/StringPrintStream.h>
32
#include <wtf/StringPrintStream.h>
Lines 35-50 namespace WTF { Source/JavaScriptCore/bytecode/PutByIdFlags.cpp_sec2
35
using namespace JSC;
36
using namespace JSC;
36
37
37
void printInternal(PrintStream& out, PutByIdFlags flags) {
38
void printInternal(PrintStream& out, PutByIdFlags flags) {
38
    StringPrintStream stringOut;
39
    CommaPrinter comma("|");
39
    CommaPrinter comma("|");
40
    if (flags & PutByIdIsDirect)
40
    if (flags & PutByIdIsDirect)
41
        stringOut.print(comma, "IsDirect");
41
        out.print(comma, "IsDirect");
42
42
43
    CString string = stringOut.toCString();
43
    InferredType::Kind kind = InferredType::kindForFlags(flags);
44
    if (!string.length())
44
    out.print(comma, kind);
45
        out.print("None");
45
    if (InferredType::hasStructure(kind))
46
    else
46
        out.print(":", bitwise_cast<int32_t>(decodeStructureID(flags)));
47
        out.print(string);
48
}
47
}
49
48
50
} // namespace WTF
49
} // namespace WTF
- Source/JavaScriptCore/bytecode/PutByIdFlags.h -2 / +59 lines
Lines 26-38 Source/JavaScriptCore/bytecode/PutByIdFlags.h_sec1
26
#ifndef PutByIdFlags_h
26
#ifndef PutByIdFlags_h
27
#define PutByIdFlags_h
27
#define PutByIdFlags_h
28
28
29
#include "StructureIDTable.h"
30
29
namespace JSC {
31
namespace JSC {
30
32
31
enum PutByIdFlags {
33
enum PutByIdFlags : intptr_t {
32
    PutByIdNone = 0,
34
    PutByIdNone = 0,
33
    PutByIdIsDirect = 1
35
36
    // This flag indicates that the put_by_id is direct. That means that we store the property without
37
    // checking if the prototype chain has a setter.
38
    PutByIdIsDirect = 0x1,
39
    PutByIdPersistentFlagsMask = 0x1,
40
41
    // NOTE: The values below must be in sync with what is in LowLevelInterpreter.asm.
42
43
    // Determining the required inferred type involves first checking the primary type mask, and then
44
    // using that to figure out the meaning of the secondary mask:
45
    // switch (flags & PutByIdPrimaryTypeMask) {
46
    // case PutByIdPrimaryTypeSecondary:
47
    //     switch (flags & PutByIdSecondaryTypeMask) {
48
    //     ...
49
    //     }
50
    //     break;
51
    // case PutByIdPrimaryTypeObjectWithStructure:
52
    // case PutByIdPrimaryTypeObjectWithStructureOrOther:
53
    //     StructureID structureID = decodeStructureID(flags);
54
    //     break;
55
    // }
56
    PutByIdPrimaryTypeMask = 0x6,
57
    PutByIdPrimaryTypeSecondary = 0x0, // Need to check the secondary type mask for the type.
58
    PutByIdPrimaryTypeObjectWithStructure = 0x2, // Secondary type has structure ID.
59
    PutByIdPrimaryTypeObjectWithStructureOrOther = 0x4, // Secondary type has structure ID.
60
61
    PutByIdSecondaryTypeMask = -0x8,
62
    PutByIdSecondaryTypeBottom = 0x0,
63
    PutByIdSecondaryTypeBoolean = 0x8,
64
    PutByIdSecondaryTypeOther = 0x10,
65
    PutByIdSecondaryTypeInt32 = 0x18,
66
    PutByIdSecondaryTypeNumber = 0x20,
67
    PutByIdSecondaryTypeString = 0x28,
68
    PutByIdSecondaryTypeObject = 0x30,
69
    PutByIdSecondaryTypeObjectOrOther = 0x38,
70
    PutByIdSecondaryTypeTop = 0x40
34
};
71
};
35
72
73
inline PutByIdFlags encodeStructureID(StructureID id)
74
{
75
#if USE(JSVALUE64)
76
    return static_cast<PutByIdFlags>(static_cast<PutByIdFlags>(id) << 3);
77
#else
78
    PutByIdFlags result = bitwise_cast<PutByIdFlags>(id);
79
    ASSERT(!(result & ~PutByIdSecondaryTypeMask));
80
    return result;
81
#endif
82
}
83
84
inline StructureID decodeStructureID(PutByIdFlags flags)
85
{
86
#if USE(JSVALUE64)
87
    return static_cast<StructureID>(flags >> 3);
88
#else
89
    return bitwise_cast<StructureID>(flags & PutByIdSecondaryTypeMask);
90
#endif
91
}
92
36
} // namespace JSC
93
} // namespace JSC
37
94
38
namespace WTF {
95
namespace WTF {
- Source/JavaScriptCore/bytecode/PutByIdStatus.cpp -9 / +17 lines
Lines 83-89 PutByIdStatus PutByIdStatus::computeFrom Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec1
83
        if (!isValidOffset(offset))
83
        if (!isValidOffset(offset))
84
            return PutByIdStatus(NoInformation);
84
            return PutByIdStatus(NoInformation);
85
        
85
        
86
        return PutByIdVariant::replace(structure, offset);
86
        return PutByIdVariant::replace(structure, offset, structure->inferredTypeDescriptorFor(uid));
87
    }
87
    }
88
88
89
    Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
89
    Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
Lines 103-109 PutByIdStatus PutByIdStatus::computeFrom Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec2
103
            return PutByIdStatus(NoInformation);
103
            return PutByIdStatus(NoInformation);
104
    }
104
    }
105
    
105
    
106
    return PutByIdVariant::transition(structure, newStructure, conditionSet, offset);
106
    return PutByIdVariant::transition(
107
        structure, newStructure, conditionSet, offset, newStructure->inferredTypeDescriptorFor(uid));
107
}
108
}
108
109
109
PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& map, unsigned bytecodeIndex, UniquedStringImpl* uid)
110
PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& map, unsigned bytecodeIndex, UniquedStringImpl* uid)
Lines 162-168 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec3
162
            stubInfo->u.byIdSelf.baseObjectStructure->getConcurrently(uid);
163
            stubInfo->u.byIdSelf.baseObjectStructure->getConcurrently(uid);
163
        if (isValidOffset(offset)) {
164
        if (isValidOffset(offset)) {
164
            return PutByIdVariant::replace(
165
            return PutByIdVariant::replace(
165
                stubInfo->u.byIdSelf.baseObjectStructure.get(), offset);
166
                stubInfo->u.byIdSelf.baseObjectStructure.get(), offset, InferredType::Top);
166
        }
167
        }
167
        return PutByIdStatus(TakesSlowPath);
168
        return PutByIdStatus(TakesSlowPath);
168
    }
169
    }
Lines 193-199 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec4
193
                PropertyOffset offset = structure->getConcurrently(uid);
194
                PropertyOffset offset = structure->getConcurrently(uid);
194
                if (!isValidOffset(offset))
195
                if (!isValidOffset(offset))
195
                    return PutByIdStatus(slowPathState);
196
                    return PutByIdStatus(slowPathState);
196
                variant = PutByIdVariant::replace(structure, offset);
197
                variant = PutByIdVariant::replace(
198
                    structure, offset, structure->inferredTypeDescriptorFor(uid));
197
                break;
199
                break;
198
            }
200
            }
199
                
201
                
Lines 206-212 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec5
206
                if (!conditionSet.structuresEnsureValidity())
208
                if (!conditionSet.structuresEnsureValidity())
207
                    return PutByIdStatus(slowPathState);
209
                    return PutByIdStatus(slowPathState);
208
                variant = PutByIdVariant::transition(
210
                variant = PutByIdVariant::transition(
209
                    access.structure(), access.newStructure(), conditionSet, offset);
211
                    access.structure(), access.newStructure(), conditionSet, offset,
212
                    access.newStructure()->inferredTypeDescriptorFor(uid));
210
                break;
213
                break;
211
            }
214
            }
212
                
215
                
Lines 329-336 PutByIdStatus PutByIdStatus::computeFor( Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec6
329
                // So, better leave this alone and take slow path.
332
                // So, better leave this alone and take slow path.
330
                return PutByIdStatus(TakesSlowPath);
333
                return PutByIdStatus(TakesSlowPath);
331
            }
334
            }
332
            
335
333
            if (!result.appendVariant(PutByIdVariant::replace(structure, offset)))
336
            PutByIdVariant variant =
337
                PutByIdVariant::replace(structure, offset, structure->inferredTypeDescriptorFor(uid));
338
            if (!result.appendVariant(variant))
334
                return PutByIdStatus(TakesSlowPath);
339
                return PutByIdStatus(TakesSlowPath);
335
            continue;
340
            continue;
336
        }
341
        }
Lines 356-368 PutByIdStatus PutByIdStatus::computeFor( Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec7
356
        }
361
        }
357
    
362
    
358
        // We only optimize if there is already a structure that the transition is cached to.
363
        // We only optimize if there is already a structure that the transition is cached to.
359
        Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
364
        Structure* transition =
365
            Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
360
        if (!transition)
366
        if (!transition)
361
            return PutByIdStatus(TakesSlowPath);
367
            return PutByIdStatus(TakesSlowPath);
362
        ASSERT(isValidOffset(offset));
368
        ASSERT(isValidOffset(offset));
363
    
369
    
364
        bool didAppend = result.appendVariant(
370
        bool didAppend = result.appendVariant(
365
            PutByIdVariant::transition(structure, transition, conditionSet, offset));
371
            PutByIdVariant::transition(
372
                structure, transition, conditionSet, offset,
373
                transition->inferredTypeDescriptorFor(uid)));
366
        if (!didAppend)
374
        if (!didAppend)
367
            return PutByIdStatus(TakesSlowPath);
375
            return PutByIdStatus(TakesSlowPath);
368
    }
376
    }
- Source/JavaScriptCore/bytecode/PutByIdVariant.cpp -5 / +17 lines
Lines 45-50 PutByIdVariant& PutByIdVariant::operator Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec1
45
    m_newStructure = other.m_newStructure;
45
    m_newStructure = other.m_newStructure;
46
    m_conditionSet = other.m_conditionSet;
46
    m_conditionSet = other.m_conditionSet;
47
    m_offset = other.m_offset;
47
    m_offset = other.m_offset;
48
    m_requiredType = other.m_requiredType;
48
    if (other.m_callLinkStatus)
49
    if (other.m_callLinkStatus)
49
        m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus);
50
        m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus);
50
    else
51
    else
Lines 52-69 PutByIdVariant& PutByIdVariant::operator Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec2
52
    return *this;
53
    return *this;
53
}
54
}
54
55
55
PutByIdVariant PutByIdVariant::replace(const StructureSet& structure, PropertyOffset offset)
56
PutByIdVariant PutByIdVariant::replace(
57
    const StructureSet& structure, PropertyOffset offset, const InferredType::Descriptor& requiredType)
56
{
58
{
57
    PutByIdVariant result;
59
    PutByIdVariant result;
58
    result.m_kind = Replace;
60
    result.m_kind = Replace;
59
    result.m_oldStructure = structure;
61
    result.m_oldStructure = structure;
60
    result.m_offset = offset;
62
    result.m_offset = offset;
63
    result.m_requiredType = requiredType;
61
    return result;
64
    return result;
62
}
65
}
63
66
64
PutByIdVariant PutByIdVariant::transition(
67
PutByIdVariant PutByIdVariant::transition(
65
    const StructureSet& oldStructure, Structure* newStructure,
68
    const StructureSet& oldStructure, Structure* newStructure,
66
    const ObjectPropertyConditionSet& conditionSet, PropertyOffset offset)
69
    const ObjectPropertyConditionSet& conditionSet, PropertyOffset offset,
70
    const InferredType::Descriptor& requiredType)
67
{
71
{
68
    PutByIdVariant result;
72
    PutByIdVariant result;
69
    result.m_kind = Transition;
73
    result.m_kind = Transition;
Lines 71-76 PutByIdVariant PutByIdVariant::transitio Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec3
71
    result.m_newStructure = newStructure;
75
    result.m_newStructure = newStructure;
72
    result.m_conditionSet = conditionSet;
76
    result.m_conditionSet = conditionSet;
73
    result.m_offset = offset;
77
    result.m_offset = offset;
78
    result.m_requiredType = requiredType;
74
    return result;
79
    return result;
75
}
80
}
76
81
Lines 85-90 PutByIdVariant PutByIdVariant::setter( Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec4
85
    result.m_conditionSet = conditionSet;
90
    result.m_conditionSet = conditionSet;
86
    result.m_offset = offset;
91
    result.m_offset = offset;
87
    result.m_callLinkStatus = WTF::move(callLinkStatus);
92
    result.m_callLinkStatus = WTF::move(callLinkStatus);
93
    result.m_requiredType = InferredType::Top;
88
    return result;
94
    return result;
89
}
95
}
90
96
Lines 134-142 bool PutByIdVariant::attemptToMerge(cons Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec5
134
{
140
{
135
    if (m_offset != other.m_offset)
141
    if (m_offset != other.m_offset)
136
        return false;
142
        return false;
143
144
    if (m_requiredType != other.m_requiredType)
145
        return false;
137
    
146
    
138
    switch (m_kind) {
147
    switch (m_kind) {
139
    case Replace:
148
    case Replace: {
140
        switch (other.m_kind) {
149
        switch (other.m_kind) {
141
        case Replace: {
150
        case Replace: {
142
            ASSERT(m_conditionSet.isEmpty());
151
            ASSERT(m_conditionSet.isEmpty());
Lines 158-163 bool PutByIdVariant::attemptToMerge(cons Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec6
158
        default:
167
        default:
159
            return false;
168
            return false;
160
        }
169
        }
170
    }
161
        
171
        
162
    case Transition:
172
    case Transition:
163
        switch (other.m_kind) {
173
        switch (other.m_kind) {
Lines 210-223 void PutByIdVariant::dumpInContext(Print Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec7
210
        
220
        
211
    case Replace:
221
    case Replace:
212
        out.print(
222
        out.print(
213
            "<Replace: ", inContext(structure(), context), ", offset = ", offset(), ">");
223
            "<Replace: ", inContext(structure(), context), ", offset = ", offset(), ", ",
224
            inContext(requiredType(), context), ">");
214
        return;
225
        return;
215
        
226
        
216
    case Transition:
227
    case Transition:
217
        out.print(
228
        out.print(
218
            "<Transition: ", inContext(oldStructure(), context), " -> ",
229
            "<Transition: ", inContext(oldStructure(), context), " -> ",
219
            pointerDumpInContext(newStructure(), context), ", [",
230
            pointerDumpInContext(newStructure(), context), ", [",
220
            inContext(m_conditionSet, context), "], offset = ", offset(), ">");
231
            inContext(m_conditionSet, context), "], offset = ", offset(), ", ",
232
            inContext(requiredType(), context), ">");
221
        return;
233
        return;
222
        
234
        
223
    case Setter:
235
    case Setter:
- Source/JavaScriptCore/bytecode/PutByIdVariant.h -2 / +8 lines
Lines 53-63 public: Source/JavaScriptCore/bytecode/PutByIdVariant.h_sec1
53
    PutByIdVariant(const PutByIdVariant&);
53
    PutByIdVariant(const PutByIdVariant&);
54
    PutByIdVariant& operator=(const PutByIdVariant&);
54
    PutByIdVariant& operator=(const PutByIdVariant&);
55
55
56
    static PutByIdVariant replace(const StructureSet&, PropertyOffset);
56
    static PutByIdVariant replace(const StructureSet&, PropertyOffset, const InferredType::Descriptor&);
57
    
57
    
58
    static PutByIdVariant transition(
58
    static PutByIdVariant transition(
59
        const StructureSet& oldStructure, Structure* newStructure,
59
        const StructureSet& oldStructure, Structure* newStructure,
60
        const ObjectPropertyConditionSet&, PropertyOffset);
60
        const ObjectPropertyConditionSet&, PropertyOffset, const InferredType::Descriptor&);
61
    
61
    
62
    static PutByIdVariant setter(
62
    static PutByIdVariant setter(
63
        const StructureSet&, PropertyOffset, const ObjectPropertyConditionSet&,
63
        const StructureSet&, PropertyOffset, const ObjectPropertyConditionSet&,
Lines 99-104 public: Source/JavaScriptCore/bytecode/PutByIdVariant.h_sec2
99
        return m_newStructure;
99
        return m_newStructure;
100
    }
100
    }
101
101
102
    InferredType::Descriptor requiredType() const
103
    {
104
        return m_requiredType;
105
    }
106
102
    bool writesStructures() const;
107
    bool writesStructures() const;
103
    bool reallocatesStorage() const;
108
    bool reallocatesStorage() const;
104
    bool makesCalls() const;
109
    bool makesCalls() const;
Lines 130-135 private: Source/JavaScriptCore/bytecode/PutByIdVariant.h_sec3
130
    Structure* m_newStructure;
135
    Structure* m_newStructure;
131
    ObjectPropertyConditionSet m_conditionSet;
136
    ObjectPropertyConditionSet m_conditionSet;
132
    PropertyOffset m_offset;
137
    PropertyOffset m_offset;
138
    InferredType::Descriptor m_requiredType;
133
    std::unique_ptr<CallLinkStatus> m_callLinkStatus;
139
    std::unique_ptr<CallLinkStatus> m_callLinkStatus;
134
};
140
};
135
141
- Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h -3 lines
Lines 36-42 Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h_sec1
36
#include "JSCell.h"
36
#include "JSCell.h"
37
#include "JSString.h"
37
#include "JSString.h"
38
#include "ParserModes.h"
38
#include "ParserModes.h"
39
#include "PutByIdFlags.h"
40
#include "RegExp.h"
39
#include "RegExp.h"
41
#include "SpecialPointer.h"
40
#include "SpecialPointer.h"
42
#include "UnlinkedFunctionExecutable.h"
41
#include "UnlinkedFunctionExecutable.h"
Lines 98-109 struct UnlinkedInstruction { Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h_sec2
98
    UnlinkedInstruction() { u.operand = 0; }
97
    UnlinkedInstruction() { u.operand = 0; }
99
    UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
98
    UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
100
    UnlinkedInstruction(int operand) { u.operand = operand; }
99
    UnlinkedInstruction(int operand) { u.operand = operand; }
101
    UnlinkedInstruction(PutByIdFlags flags) { u.putByIdFlags = flags; }
102
    union {
100
    union {
103
        OpcodeID opcode;
101
        OpcodeID opcode;
104
        int32_t operand;
102
        int32_t operand;
105
        unsigned index;
103
        unsigned index;
106
        PutByIdFlags putByIdFlags;
107
    } u;
104
    } u;
108
};
105
};
109
106
- Source/JavaScriptCore/bytecode/Watchpoint.h -1 / +33 lines
Lines 336-342 public: Source/JavaScriptCore/bytecode/Watchpoint.h_sec1
336
    {
336
    {
337
        touch(StringFireDetail(reason));
337
        touch(StringFireDetail(reason));
338
    }
338
    }
339
    
339
340
    // Note that for any watchpoint that is visible from the DFG, it would be incorrect to write code like:
341
    //
342
    // if (w.isBeingWatched())
343
    //     w.fireAll()
344
    //
345
    // Concurrently to this, the DFG could do:
346
    //
347
    // if (w.isStillValid())
348
    //     perform optimizations;
349
    // if (!w.isStillValid())
350
    //     retry compilation;
351
    //
352
    // Note that the DFG algorithm is widespread, and sound, because fireAll() and invalidate() will leave
353
    // the watchpoint in a !isStillValid() state. Hence, if fireAll() or invalidate() interleaved between
354
    // the first isStillValid() check and the second one, then it would simply cause the DFG to retry
355
    // compilation later.
356
    //
357
    // But, if you change some piece of state that the DFG might optimize for, but invalidate the
358
    // watchpoint by doing:
359
    //
360
    // if (w.isBeingWatched())
361
    //     w.fireAll()
362
    //
363
    // then the DFG would never know that you invalidated state between the two checks.
364
    //
365
    // There are two ways to work around this:
366
    //
367
    // - Call fireAll() without a isBeingWatched() check. Then, the DFG will know that the watchpoint has
368
    //   been invalidated when it does its second check.
369
    //
370
    // - Do not expose the watchpoint set to the DFG directly, and have your own way of validating whether
371
    //   the assumptions that the DFG thread used are still valid when the DFG code is installed.
340
    bool isBeingWatched() const
372
    bool isBeingWatched() const
341
    {
373
    {
342
        if (isFat())
374
        if (isFat())
- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp -2 / +2 lines
Lines 2114-2120 RegisterID* BytecodeGenerator::emitPutBy Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp_sec1
2114
    instructions().append(0); // offset
2114
    instructions().append(0); // offset
2115
    instructions().append(0); // new structure
2115
    instructions().append(0); // new structure
2116
    instructions().append(0); // structure chain
2116
    instructions().append(0); // structure chain
2117
    instructions().append(PutByIdNone); // is not direct
2117
    instructions().append(static_cast<int>(PutByIdNone)); // is not direct
2118
2118
2119
    return value;
2119
    return value;
2120
}
2120
}
Lines 2136-2142 RegisterID* BytecodeGenerator::emitDirec Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp_sec2
2136
    instructions().append(0); // offset
2136
    instructions().append(0); // offset
2137
    instructions().append(0); // new structure
2137
    instructions().append(0); // new structure
2138
    instructions().append(0); // structure chain (unused if direct)
2138
    instructions().append(0); // structure chain (unused if direct)
2139
    instructions().append((putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto) ? PutByIdIsDirect : PutByIdNone);
2139
    instructions().append(static_cast<int>((putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto) ? PutByIdIsDirect : PutByIdNone));
2140
    return value;
2140
    return value;
2141
}
2141
}
2142
2142
- Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h -3 / +3 lines
Lines 116-124 public: Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h_sec1
116
    void dump(PrintStream& out);
116
    void dump(PrintStream& out);
117
    
117
    
118
    template<typename T>
118
    template<typename T>
119
    FiltrationResult filter(T node, const StructureSet& set)
119
    FiltrationResult filter(T node, const StructureSet& set, SpeculatedType admittedTypes = SpecNone)
120
    {
120
    {
121
        return filter(forNode(node), set);
121
        return filter(forNode(node), set, admittedTypes);
122
    }
122
    }
123
    
123
    
124
    template<typename T>
124
    template<typename T>
Lines 139-145 public: Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h_sec2
139
        return filterByValue(forNode(node), value);
139
        return filterByValue(forNode(node), value);
140
    }
140
    }
141
    
141
    
142
    FiltrationResult filter(AbstractValue&, const StructureSet&);
142
    FiltrationResult filter(AbstractValue&, const StructureSet&, SpeculatedType admittedTypes = SpecNone);
143
    FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
143
    FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
144
    FiltrationResult filter(AbstractValue&, SpeculatedType);
144
    FiltrationResult filter(AbstractValue&, SpeculatedType);
145
    FiltrationResult filterByValue(AbstractValue&, FrozenValue);
145
    FiltrationResult filterByValue(AbstractValue&, FrozenValue);
- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h -44 / +84 lines
Lines 1829-1838 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec1
1829
        }
1829
        }
1830
        
1830
        
1831
        AbstractValue& value = forNode(node->child1());
1831
        AbstractValue& value = forNode(node->child1());
1832
        if (!value.m_structure.isTop() && !value.m_structure.isClobbered()
1832
        if (value.m_structure.isFinite()
1833
            && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
1833
            && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
1834
            GetByIdStatus status = GetByIdStatus::computeFor(
1834
            UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
1835
                value.m_structure.set(), m_graph.identifiers()[node->identifierNumber()]);
1835
            GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.set(), uid);
1836
            if (status.isSimple()) {
1836
            if (status.isSimple()) {
1837
                // Figure out what the result is going to be - is it TOP, a constant, or maybe
1837
                // Figure out what the result is going to be - is it TOP, a constant, or maybe
1838
                // something more subtle?
1838
                // something more subtle?
Lines 1841-1862 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec2
1841
                    // This thing won't give us a variant that involves prototypes. If it did, we'd
1841
                    // This thing won't give us a variant that involves prototypes. If it did, we'd
1842
                    // have more work to do here.
1842
                    // have more work to do here.
1843
                    DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
1843
                    DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
1844
                    
1844
1845
                    JSValue constantResult =
1845
                    result.merge(
1846
                        m_graph.tryGetConstantProperty(value, status[i].offset());
1846
                        m_graph.inferredValueForProperty(
1847
                    if (!constantResult) {
1847
                            value, uid, status[i].offset(), m_state.structureClobberState()));
1848
                        result.makeHeapTop();
1849
                        break;
1850
                    }
1851
                    
1852
                    AbstractValue thisResult;
1853
                    thisResult.set(
1854
                        m_graph, *m_graph.freeze(constantResult),
1855
                        m_state.structureClobberState());
1856
                    result.merge(thisResult);
1857
                }
1848
                }
1858
                if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
1849
                m_state.setFoundConstants(true);
1859
                    m_state.setFoundConstants(true);
1860
                forNode(node) = result;
1850
                forNode(node) = result;
1861
                break;
1851
                break;
1862
            }
1852
            }
Lines 1880-1886 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec3
1880
        
1870
        
1881
    case CheckStructure: {
1871
    case CheckStructure: {
1882
        AbstractValue& value = forNode(node->child1());
1872
        AbstractValue& value = forNode(node->child1());
1883
        ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1884
1873
1885
        StructureSet& set = node->structureSet();
1874
        StructureSet& set = node->structureSet();
1886
        
1875
        
Lines 1888-1899 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec4
1888
        // that includes the set we're testing. In that case we could make the structure check
1877
        // that includes the set we're testing. In that case we could make the structure check
1889
        // more efficient. We currently don't.
1878
        // more efficient. We currently don't.
1890
        
1879
        
1891
        if (value.m_structure.isSubsetOf(set)) {
1880
        if (value.m_structure.isSubsetOf(set))
1892
            m_state.setFoundConstants(true);
1881
            m_state.setFoundConstants(true);
1882
1883
        SpeculatedType admittedTypes = SpecNone;
1884
        switch (node->child1().useKind()) {
1885
        case CellUse:
1886
        case KnownCellUse:
1887
            admittedTypes = SpecNone;
1888
            break;
1889
        case CellOrOtherUse:
1890
            admittedTypes = SpecOther;
1891
            break;
1892
        default:
1893
            DFG_CRASH(m_graph, node, "Bad use kind");
1893
            break;
1894
            break;
1894
        }
1895
        }
1895
1896
        
1896
        filter(value, set);
1897
        filter(value, set, admittedTypes);
1897
        break;
1898
        break;
1898
    }
1899
    }
1899
        
1900
        
Lines 2084-2096 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec5
2084
        
2085
        
2085
    case GetByOffset: {
2086
    case GetByOffset: {
2086
        StorageAccessData& data = node->storageAccessData();
2087
        StorageAccessData& data = node->storageAccessData();
2087
        JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
2088
        UniquedStringImpl* uid = m_graph.identifiers()[data.identifierNumber];
2088
        if (result) {
2089
2089
            setConstant(node, *m_graph.freeze(result));
2090
        // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
2090
            break;
2091
        // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
2091
        }
2092
        // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
2092
        
2093
        // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
2093
        forNode(node).makeHeapTop();
2094
        // on the type that ByteCodeParser was able to prove.
2095
        AbstractValue value = m_graph.inferredValueForProperty(
2096
            forNode(node->child2()), uid, data.offset, m_state.structureClobberState());
2097
2098
        // It's possible that the type that ByteCodeParser came up with is better.
2099
        AbstractValue typeFromParsing;
2100
        typeFromParsing.set(m_graph, data.inferredType, m_state.structureClobberState());
2101
        value.filter(typeFromParsing);
2102
2103
        // If we decide that there does not exist any value that this can return, then it's probably
2104
        // because the compilation was already invalidated.
2105
        if (value.isClear())
2106
            m_state.setIsValid(false);
2107
2108
        forNode(node) = value;
2109
        if (value.m_value)
2110
            m_state.setFoundConstants(true);
2094
        break;
2111
        break;
2095
    }
2112
    }
2096
        
2113
        
Lines 2120-2125 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec6
2120
        // because of the effect on compile times, but this node is FTL-only.
2137
        // because of the effect on compile times, but this node is FTL-only.
2121
        m_state.setFoundConstants(true);
2138
        m_state.setFoundConstants(true);
2122
        
2139
        
2140
        UniquedStringImpl* uid = m_graph.identifiers()[node->multiGetByOffsetData().identifierNumber];
2141
2123
        AbstractValue base = forNode(node->child1());
2142
        AbstractValue base = forNode(node->child1());
2124
        StructureSet baseSet;
2143
        StructureSet baseSet;
2125
        AbstractValue result;
2144
        AbstractValue result;
Lines 2129-2146 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec7
2129
            if (set.isEmpty())
2148
            if (set.isEmpty())
2130
                continue;
2149
                continue;
2131
            baseSet.merge(set);
2150
            baseSet.merge(set);
2132
            
2151
2133
            if (getCase.method().kind() != GetByOffsetMethod::Constant) {
2152
            switch (getCase.method().kind()) {
2134
                result.makeHeapTop();
2153
            case GetByOffsetMethod::Constant: {
2135
                continue;
2154
                AbstractValue thisResult;
2155
                thisResult.set(
2156
                    m_graph,
2157
                    *getCase.method().constant(),
2158
                    m_state.structureClobberState());
2159
                result.merge(thisResult);
2160
                break;
2136
            }
2161
            }
2137
            
2162
2138
            AbstractValue thisResult;
2163
            case GetByOffsetMethod::Load: {
2139
            thisResult.set(
2164
                result.merge(
2140
                m_graph,
2165
                    m_graph.inferredValueForProperty(
2141
                *getCase.method().constant(),
2166
                        set, uid, m_state.structureClobberState()));
2142
                m_state.structureClobberState());
2167
                break;
2143
            result.merge(thisResult);
2168
            }
2169
2170
            default: {
2171
                result.makeHeapTop();
2172
                break;
2173
            } }
2144
        }
2174
        }
2145
        
2175
        
2146
        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
2176
        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
Lines 2163-2168 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec8
2163
        m_state.setFoundConstants(true);
2193
        m_state.setFoundConstants(true);
2164
        
2194
        
2165
        AbstractValue base = forNode(node->child1());
2195
        AbstractValue base = forNode(node->child1());
2196
        AbstractValue originalValue = forNode(node->child2());
2197
        AbstractValue resultingValue;
2166
        
2198
        
2167
        for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2199
        for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2168
            const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
2200
            const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
Lines 2170-2175 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec9
2170
            thisSet.filter(base);
2202
            thisSet.filter(base);
2171
            if (thisSet.isEmpty())
2203
            if (thisSet.isEmpty())
2172
                continue;
2204
                continue;
2205
2206
            AbstractValue thisValue = originalValue;
2207
            thisValue.filter(m_graph, variant.requiredType());
2208
            resultingValue.merge(thisValue);
2209
            
2173
            if (variant.kind() == PutByIdVariant::Transition) {
2210
            if (variant.kind() == PutByIdVariant::Transition) {
2174
                if (thisSet.onlyStructure() != variant.newStructure()) {
2211
                if (thisSet.onlyStructure() != variant.newStructure()) {
2175
                    transitions.append(
2212
                    transitions.append(
Lines 2185-2190 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec10
2185
        observeTransitions(clobberLimit, transitions);
2222
        observeTransitions(clobberLimit, transitions);
2186
        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2223
        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2187
            m_state.setIsValid(false);
2224
            m_state.setIsValid(false);
2225
        forNode(node->child2()) = resultingValue;
2226
        if (!!originalValue && !resultingValue)
2227
            m_state.setIsValid(false);
2188
        break;
2228
        break;
2189
    }
2229
    }
2190
        
2230
        
Lines 2264-2276 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec11
2264
    case PutByIdFlush:
2304
    case PutByIdFlush:
2265
    case PutByIdDirect: {
2305
    case PutByIdDirect: {
2266
        AbstractValue& value = forNode(node->child1());
2306
        AbstractValue& value = forNode(node->child1());
2267
        if (!value.m_structure.isTop() && !value.m_structure.isClobbered()) {
2307
        if (value.m_structure.isFinite()) {
2268
            PutByIdStatus status = PutByIdStatus::computeFor(
2308
            PutByIdStatus status = PutByIdStatus::computeFor(
2269
                m_graph.globalObjectFor(node->origin.semantic),
2309
                m_graph.globalObjectFor(node->origin.semantic),
2270
                value.m_structure.set(),
2310
                value.m_structure.set(),
2271
                m_graph.identifiers()[node->identifierNumber()],
2311
                m_graph.identifiers()[node->identifierNumber()],
2272
                node->op() == PutByIdDirect);
2312
                node->op() == PutByIdDirect);
2273
            
2313
2274
            if (status.isSimple()) {
2314
            if (status.isSimple()) {
2275
                StructureSet newSet;
2315
                StructureSet newSet;
2276
                TransitionVector transitions;
2316
                TransitionVector transitions;
Lines 2615-2623 void AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec12
2615
2655
2616
template<typename AbstractStateType>
2656
template<typename AbstractStateType>
2617
FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2657
FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2618
    AbstractValue& value, const StructureSet& set)
2658
    AbstractValue& value, const StructureSet& set, SpeculatedType admittedTypes)
2619
{
2659
{
2620
    if (value.filter(m_graph, set) == FiltrationOK)
2660
    if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
2621
        return FiltrationOK;
2661
        return FiltrationOK;
2622
    m_state.setIsValid(false);
2662
    m_state.setIsValid(false);
2623
    return Contradiction;
2663
    return Contradiction;
- Source/JavaScriptCore/dfg/DFGAbstractValue.cpp -2 / +73 lines
Lines 117-122 void AbstractValue::setType(Graph& graph Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec1
117
    checkConsistency();
117
    checkConsistency();
118
}
118
}
119
119
120
void AbstractValue::set(Graph& graph, const InferredType::Descriptor& descriptor)
121
{
122
    switch (descriptor.kind()) {
123
    case InferredType::Bottom:
124
        clear();
125
        return;
126
    case InferredType::Boolean:
127
        setType(SpecBoolean);
128
        return;
129
    case InferredType::Other:
130
        setType(SpecOther);
131
        return;
132
    case InferredType::Int32:
133
        setType(SpecInt32);
134
        return;
135
    case InferredType::Number:
136
        setType(SpecBytecodeNumber);
137
        return;
138
    case InferredType::String:
139
        set(graph, graph.m_vm.stringStructure.get());
140
        return;
141
    case InferredType::ObjectWithStructure:
142
        set(graph, descriptor.structure());
143
        return;
144
    case InferredType::ObjectWithStructureOrOther:
145
        set(graph, descriptor.structure());
146
        merge(SpecOther);
147
        return;
148
    case InferredType::Object:
149
        setType(graph, SpecObject);
150
        return;
151
    case InferredType::ObjectOrOther:
152
        setType(graph, SpecObject | SpecOther);
153
        return;
154
    case InferredType::Top:
155
        makeHeapTop();
156
        return;
157
    }
158
159
    RELEASE_ASSERT_NOT_REACHED();
160
}
161
162
void AbstractValue::set(
163
    Graph& graph, const InferredType::Descriptor& descriptor, StructureClobberState clobberState)
164
{
165
    set(graph, descriptor);
166
    if (clobberState == StructuresAreClobbered)
167
        clobberStructures();
168
}
169
120
void AbstractValue::fixTypeForRepresentation(Graph& graph, NodeFlags representation, Node* node)
170
void AbstractValue::fixTypeForRepresentation(Graph& graph, NodeFlags representation, Node* node)
121
{
171
{
122
    if (representation == NodeResultDouble) {
172
    if (representation == NodeResultDouble) {
Lines 189-196 bool AbstractValue::mergeOSREntryValue(G Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec2
189
    return oldMe != *this;
239
    return oldMe != *this;
190
}
240
}
191
241
192
FiltrationResult AbstractValue::filter(Graph& graph, const StructureSet& other)
242
bool AbstractValue::isType(Graph& graph, const InferredType::Descriptor& inferredType) const
193
{
243
{
244
    AbstractValue typeValue;
245
    typeValue.set(graph, inferredType);
246
247
    AbstractValue mergedValue = *this;
248
    mergedValue.merge(typeValue);
249
250
    return mergedValue == typeValue;
251
}
252
253
FiltrationResult AbstractValue::filter(
254
    Graph& graph, const StructureSet& other, SpeculatedType admittedTypes)
255
{
256
    ASSERT(!(admittedTypes & SpecCell));
257
    
194
    if (isClear())
258
    if (isClear())
195
        return FiltrationOK;
259
        return FiltrationOK;
196
    
260
    
Lines 198-204 FiltrationResult AbstractValue::filter(G Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec3
198
    // having structures, array modes, or a specific value.
262
    // having structures, array modes, or a specific value.
199
    // https://bugs.webkit.org/show_bug.cgi?id=109663
263
    // https://bugs.webkit.org/show_bug.cgi?id=109663
200
    
264
    
201
    m_type &= other.speculationFromStructures();
265
    m_type &= other.speculationFromStructures() | admittedTypes;
202
    m_arrayModes &= other.arrayModesFromStructures();
266
    m_arrayModes &= other.arrayModesFromStructures();
203
    m_structure.filter(other);
267
    m_structure.filter(other);
204
    
268
    
Lines 315-320 FiltrationResult AbstractValue::filter(c Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec4
315
    return Contradiction;
379
    return Contradiction;
316
}
380
}
317
381
382
FiltrationResult AbstractValue::filter(Graph& graph, const InferredType::Descriptor& descriptor)
383
{
384
    AbstractValue filterValue;
385
    filterValue.set(graph, descriptor);
386
    return filter(filterValue);
387
}
388
318
void AbstractValue::filterValueByType()
389
void AbstractValue::filterValueByType()
319
{
390
{
320
    // We could go further, and ensure that if the futurePossibleStructure contravenes
391
    // We could go further, and ensure that if the futurePossibleStructure contravenes
- Source/JavaScriptCore/dfg/DFGAbstractValue.h -3 / +17 lines
Lines 34-39 Source/JavaScriptCore/dfg/DFGAbstractValue.h_sec1
34
#include "DFGNodeFlags.h"
34
#include "DFGNodeFlags.h"
35
#include "DFGStructureAbstractValue.h"
35
#include "DFGStructureAbstractValue.h"
36
#include "DFGStructureClobberState.h"
36
#include "DFGStructureClobberState.h"
37
#include "InferredType.h"
37
#include "JSCell.h"
38
#include "JSCell.h"
38
#include "SpeculatedType.h"
39
#include "SpeculatedType.h"
39
#include "DumpContext.h"
40
#include "DumpContext.h"
Lines 214-220 struct AbstractValue { Source/JavaScriptCore/dfg/DFGAbstractValue.h_sec2
214
        m_value = JSValue();
215
        m_value = JSValue();
215
        checkConsistency();
216
        checkConsistency();
216
    }
217
    }
217
    
218
219
    void set(Graph&, const InferredType::Descriptor&);
220
    void set(Graph&, const InferredType::Descriptor&, StructureClobberState);
221
218
    void fixTypeForRepresentation(Graph&, NodeFlags representation, Node* = nullptr);
222
    void fixTypeForRepresentation(Graph&, NodeFlags representation, Node* = nullptr);
219
    void fixTypeForRepresentation(Graph&, Node*);
223
    void fixTypeForRepresentation(Graph&, Node*);
220
    
224
    
Lines 280-296 struct AbstractValue { Source/JavaScriptCore/dfg/DFGAbstractValue.h_sec3
280
    {
284
    {
281
        return !(m_type & ~desiredType);
285
        return !(m_type & ~desiredType);
282
    }
286
    }
287
288
    bool isType(Graph&, const InferredType::Descriptor&) const;
289
290
    // Filters the value using the given structure set. If the admittedTypes argument is not passed, this
291
    // implicitly filters by the types implied by the structure set, which are usually a subset of
292
    // SpecCell. Hence, after this call, the value will no longer have any non-cell members. But, you can
293
    // use admittedTypes to preserve some non-cell types. Note that it's wrong for admittedTypes to overlap
294
    // with SpecCell.
295
    FiltrationResult filter(Graph&, const StructureSet&, SpeculatedType admittedTypes = SpecNone);
283
    
296
    
284
    FiltrationResult filter(Graph&, const StructureSet&);
285
    FiltrationResult filterArrayModes(ArrayModes);
297
    FiltrationResult filterArrayModes(ArrayModes);
286
    FiltrationResult filter(SpeculatedType);
298
    FiltrationResult filter(SpeculatedType);
287
    FiltrationResult filterByValue(const FrozenValue& value);
299
    FiltrationResult filterByValue(const FrozenValue& value);
288
    FiltrationResult filter(const AbstractValue&);
300
    FiltrationResult filter(const AbstractValue&);
301
302
    FiltrationResult filter(Graph&, const InferredType::Descriptor&);
289
    
303
    
290
    FiltrationResult changeStructure(Graph&, const StructureSet&);
304
    FiltrationResult changeStructure(Graph&, const StructureSet&);
291
    
305
    
292
    bool contains(Structure*) const;
306
    bool contains(Structure*) const;
293
    
307
294
    bool validate(JSValue value) const
308
    bool validate(JSValue value) const
295
    {
309
    {
296
        if (isHeapTop())
310
        if (isHeapTop())
- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp -10 / +32 lines
Lines 206-214 private: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec1
206
    bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks);
206
    bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks);
207
    template<typename ChecksFunctor>
207
    template<typename ChecksFunctor>
208
    bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, const ChecksFunctor& insertChecks);
208
    bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, const ChecksFunctor& insertChecks);
209
    Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, Node* value);
209
    Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, const InferredType::Descriptor&, Node* value);
210
    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, NodeType = GetByOffset);
210
    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, const InferredType::Descriptor&, NodeType = GetByOffset);
211
    Node* handleGetByOffset(SpeculatedType, Node* base, UniquedStringImpl*, PropertyOffset, NodeType = GetByOffset);
212
211
213
    // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
212
    // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
214
    // check the validity of the condition, but it may return a null one if it encounters a contradiction.
213
    // check the validity of the condition, but it may return a null one if it encounters a contradiction.
Lines 2306-2312 bool ByteCodeParser::handleConstantInter Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec2
2306
    return false;
2305
    return false;
2307
}
2306
}
2308
2307
2309
Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset, NodeType op)
2308
Node* ByteCodeParser::handleGetByOffset(
2309
    SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset,
2310
    const InferredType::Descriptor& inferredType, NodeType op)
2310
{
2311
{
2311
    Node* propertyStorage;
2312
    Node* propertyStorage;
2312
    if (isInlineOffset(offset))
2313
    if (isInlineOffset(offset))
Lines 2317-2329 Node* ByteCodeParser::handleGetByOffset( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec3
2317
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2318
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2318
    data->offset = offset;
2319
    data->offset = offset;
2319
    data->identifierNumber = identifierNumber;
2320
    data->identifierNumber = identifierNumber;
2321
    data->inferredType = inferredType;
2322
    m_graph.registerInferredType(inferredType);
2320
    
2323
    
2321
    Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
2324
    Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
2322
2325
2323
    return getByOffset;
2326
    return getByOffset;
2324
}
2327
}
2325
2328
2326
Node* ByteCodeParser::handlePutByOffset(Node* base, unsigned identifier, PropertyOffset offset, Node* value)
2329
Node* ByteCodeParser::handlePutByOffset(
2330
    Node* base, unsigned identifier, PropertyOffset offset, const InferredType::Descriptor& inferredType,
2331
    Node* value)
2327
{
2332
{
2328
    Node* propertyStorage;
2333
    Node* propertyStorage;
2329
    if (isInlineOffset(offset))
2334
    if (isInlineOffset(offset))
Lines 2334-2339 Node* ByteCodeParser::handlePutByOffset( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec4
2334
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2339
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2335
    data->offset = offset;
2340
    data->offset = offset;
2336
    data->identifierNumber = identifier;
2341
    data->identifierNumber = identifier;
2342
    data->inferredType = inferredType;
2343
    m_graph.registerInferredType(inferredType);
2337
    
2344
    
2338
    Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
2345
    Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
2339
    
2346
    
Lines 2448-2454 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec5
2448
        return addToGraph(JSConstant, OpInfo(method.constant()));
2455
        return addToGraph(JSConstant, OpInfo(method.constant()));
2449
    case GetByOffsetMethod::LoadFromPrototype: {
2456
    case GetByOffsetMethod::LoadFromPrototype: {
2450
        Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
2457
        Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
2451
        return handleGetByOffset(prediction, baseNode, identifierNumber, method.offset(), op);
2458
        return handleGetByOffset(
2459
            prediction, baseNode, identifierNumber, method.offset(), InferredType::Top, op);
2452
    }
2460
    }
2453
    case GetByOffsetMethod::Load:
2461
    case GetByOffsetMethod::Load:
2454
        // Will never see this from planLoad().
2462
        // Will never see this from planLoad().
Lines 2554-2566 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec6
2554
    
2562
    
2555
    bool needStructureCheck = true;
2563
    bool needStructureCheck = true;
2556
    
2564
    
2565
    UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
2566
    
2557
    if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>()) {
2567
    if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>()) {
2558
        // Try to optimize away the structure check. Note that it's not worth doing anything about this
2568
        // Try to optimize away the structure check. Note that it's not worth doing anything about this
2559
        // if the base's structure is watched.
2569
        // if the base's structure is watched.
2560
        Structure* structure = base->constant()->structure();
2570
        Structure* structure = base->constant()->structure();
2561
        if (!structure->dfgShouldWatch()) {
2571
        if (!structure->dfgShouldWatch()) {
2562
            UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
2563
            
2564
            if (!variant.conditionSet().isEmpty()) {
2572
            if (!variant.conditionSet().isEmpty()) {
2565
                // This means that we're loading from a prototype. We expect the base not to have the
2573
                // This means that we're loading from a prototype. We expect the base not to have the
2566
                // property. We can only use ObjectPropertyCondition if all of the structures in the
2574
                // property. We can only use ObjectPropertyCondition if all of the structures in the
Lines 2625-2633 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec7
2625
            if (constant)
2633
            if (constant)
2626
                return weakJSConstant(constant);
2634
                return weakJSConstant(constant);
2627
        }
2635
        }
2636
2637
        InferredType::Descriptor inferredType;
2638
        if (needStructureCheck) {
2639
            for (Structure* structure : variant.structureSet()) {
2640
                InferredType::Descriptor thisType = m_graph.inferredTypeForProperty(structure, uid);
2641
                inferredType.merge(thisType);
2642
            }
2643
        } else
2644
            inferredType = InferredType::Top;
2628
        
2645
        
2629
        loadedValue = handleGetByOffset(
2646
        loadedValue = handleGetByOffset(
2630
            loadPrediction, base, identifierNumber, variant.offset(), loadOp);
2647
            loadPrediction, base, identifierNumber, variant.offset(), inferredType, loadOp);
2631
    }
2648
    }
2632
2649
2633
    return loadedValue;
2650
    return loadedValue;
Lines 2638-2644 Node* ByteCodeParser::store(Node* base, Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec8
2638
    RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
2655
    RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
2639
2656
2640
    checkPresenceLike(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
2657
    checkPresenceLike(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
2641
    return handlePutByOffset(base, identifier, variant.offset(), value);
2658
    return handlePutByOffset(base, identifier, variant.offset(), variant.requiredType(), value);
2642
}
2659
}
2643
2660
2644
void ByteCodeParser::handleGetById(
2661
void ByteCodeParser::handleGetById(
Lines 2797-2802 void ByteCodeParser::handlePutById( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec9
2797
        
2814
        
2798
        if (m_graph.compilation())
2815
        if (m_graph.compilation())
2799
            m_graph.compilation()->noticeInlinedPutById();
2816
            m_graph.compilation()->noticeInlinedPutById();
2817
2818
        for (const PutByIdVariant& variant : putByIdStatus.variants())
2819
            m_graph.registerInferredType(variant.requiredType());
2800
        
2820
        
2801
        MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
2821
        MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
2802
        data->variants = putByIdStatus.variants();
2822
        data->variants = putByIdStatus.variants();
Lines 2853-2858 void ByteCodeParser::handlePutById( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec10
2853
        StorageAccessData* data = m_graph.m_storageAccessData.add();
2873
        StorageAccessData* data = m_graph.m_storageAccessData.add();
2854
        data->offset = variant.offset();
2874
        data->offset = variant.offset();
2855
        data->identifierNumber = identifierNumber;
2875
        data->identifierNumber = identifierNumber;
2876
        data->inferredType = variant.requiredType();
2877
        m_graph.registerInferredType(data->inferredType);
2856
        
2878
        
2857
        addToGraph(
2879
        addToGraph(
2858
            PutByOffset,
2880
            PutByOffset,
- Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp +2 lines
Lines 64-69 bool clobbersExitState(Graph& graph, Nod Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp_sec1
64
    case PhantomCreateActivation:
64
    case PhantomCreateActivation:
65
    case MaterializeCreateActivation:
65
    case MaterializeCreateActivation:
66
    case CountExecution:
66
    case CountExecution:
67
    case AllocatePropertyStorage:
68
    case ReallocatePropertyStorage:
67
        // These do clobber memory, but nothing that is observable. It may be nice to separate the
69
        // These do clobber memory, but nothing that is observable. It may be nice to separate the
68
        // heaps into those that are observable and those that aren't, but we don't do that right now.
70
        // heaps into those that are observable and those that aren't, but we don't do that right now.
69
        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=148440
71
        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=148440
- Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp -4 / +13 lines
Lines 33-38 Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec1
33
#include "DFGBasicBlock.h"
33
#include "DFGBasicBlock.h"
34
#include "DFGGraph.h"
34
#include "DFGGraph.h"
35
#include "DFGInPlaceAbstractState.h"
35
#include "DFGInPlaceAbstractState.h"
36
#include "DFGInferredTypeCheck.h"
36
#include "DFGInsertionSet.h"
37
#include "DFGInsertionSet.h"
37
#include "DFGPhase.h"
38
#include "DFGPhase.h"
38
#include "GetByIdStatus.h"
39
#include "GetByIdStatus.h"
Lines 373-379 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec2
373
                        && variant.oldStructure().onlyStructure() == variant.newStructure()) {
374
                        && variant.oldStructure().onlyStructure() == variant.newStructure()) {
374
                        variant = PutByIdVariant::replace(
375
                        variant = PutByIdVariant::replace(
375
                            variant.oldStructure(),
376
                            variant.oldStructure(),
376
                            variant.offset());
377
                            variant.offset(),
378
                            variant.requiredType());
377
                        changed = true;
379
                        changed = true;
378
                    }
380
                    }
379
                }
381
                }
Lines 448-453 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec3
448
                ASSERT(childEdge.useKind() == CellUse);
450
                ASSERT(childEdge.useKind() == CellUse);
449
                
451
                
450
                AbstractValue baseValue = m_state.forNode(child);
452
                AbstractValue baseValue = m_state.forNode(child);
453
                AbstractValue valueValue = m_state.forNode(node->child2());
451
454
452
                m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
455
                m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
453
                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
456
                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
Lines 463-469 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec4
463
                
466
                
464
                if (!status.isSimple())
467
                if (!status.isSimple())
465
                    break;
468
                    break;
466
                
469
467
                ASSERT(status.numVariants());
470
                ASSERT(status.numVariants());
468
                
471
                
469
                if (status.numVariants() > 1 && !isFTL(m_graph.m_plan.mode))
472
                if (status.numVariants() > 1 && !isFTL(m_graph.m_plan.mode))
Lines 640-646 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec5
640
        emitGetByOffset(indexInBlock, node, childEdge, identifierNumber, variant.offset());
643
        emitGetByOffset(indexInBlock, node, childEdge, identifierNumber, variant.offset());
641
    }
644
    }
642
    
645
    
643
    void emitGetByOffset(unsigned indexInBlock, Node* node, Edge childEdge, unsigned identifierNumber, PropertyOffset offset)
646
    void emitGetByOffset(
647
        unsigned indexInBlock, Node* node, Edge childEdge, unsigned identifierNumber,
648
        PropertyOffset offset, const InferredType::Descriptor& inferredType = InferredType::Top)
644
    {
649
    {
645
        childEdge.setUseKind(KnownCellUse);
650
        childEdge.setUseKind(KnownCellUse);
646
        
651
        
Lines 656-661 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec6
656
        StorageAccessData& data = *m_graph.m_storageAccessData.add();
661
        StorageAccessData& data = *m_graph.m_storageAccessData.add();
657
        data.offset = offset;
662
        data.offset = offset;
658
        data.identifierNumber = identifierNumber;
663
        data.identifierNumber = identifierNumber;
664
        data.inferredType = inferredType;
659
        
665
        
660
        node->convertToGetByOffset(data, propertyStorage);
666
        node->convertToGetByOffset(data, propertyStorage);
661
    }
667
    }
Lines 664-671 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec7
664
    {
670
    {
665
        NodeOrigin origin = node->origin;
671
        NodeOrigin origin = node->origin;
666
        Edge childEdge = node->child1();
672
        Edge childEdge = node->child1();
667
        
673
668
        addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
674
        addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
675
        insertInferredTypeCheck(
676
            m_insertionSet, indexInBlock, origin, node->child2().node(), variant.requiredType());
669
677
670
        node->child1().setUseKind(KnownCellUse);
678
        node->child1().setUseKind(KnownCellUse);
671
        childEdge.setUseKind(KnownCellUse);
679
        childEdge.setUseKind(KnownCellUse);
Lines 730-735 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec8
730
            // Arises when we prune MultiGetByOffset. We could have a
738
            // Arises when we prune MultiGetByOffset. We could have a
731
            // MultiGetByOffset with a single variant that checks for structure S,
739
            // MultiGetByOffset with a single variant that checks for structure S,
732
            // and the input has structures S and T, for example.
740
            // and the input has structures S and T, for example.
741
            ASSERT(node->child1());
733
            m_insertionSet.insertNode(
742
            m_insertionSet.insertNode(
734
                indexInBlock, SpecNone, CheckStructure, node->origin,
743
                indexInBlock, SpecNone, CheckStructure, node->origin,
735
                OpInfo(m_graph.addStructureSet(set)), node->child1());
744
                OpInfo(m_graph.addStructureSet(set)), node->child1());
- Source/JavaScriptCore/dfg/DFGDesiredInferredType.h +132 lines
Line 0 Source/JavaScriptCore/dfg/DFGDesiredInferredType.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef DFGDesiredInferredType_h
27
#define DFGDesiredInferredType_h
28
29
#if ENABLE(DFG_JIT)
30
31
#include "InferredType.h"
32
#include <wtf/HashMap.h>
33
34
namespace JSC { namespace DFG {
35
36
// This documents the DFG's expectation for an InferredType: specifically, that we want it to have a live
37
// InferredType object and that this object has the type that we originally saw.
38
39
class DesiredInferredType {
40
public:
41
    DesiredInferredType()
42
        : m_object(nullptr)
43
    {
44
    }
45
    
46
    DesiredInferredType(InferredType* object, const InferredType::Descriptor& expected)
47
        : m_object(object)
48
        , m_expected(expected)
49
    {
50
    }
51
52
    DesiredInferredType(WTF::HashTableDeletedValueType)
53
        : m_object(nullptr)
54
        , m_expected(InferredType::Top)
55
    {
56
    }
57
58
    explicit operator bool() const { return m_object && m_expected; }
59
60
    InferredType* object() const { return m_object; }
61
    InferredType::Descriptor expected() const { return m_expected; }
62
63
    bool isStillValid() const
64
    {
65
        return m_object->canWatch(m_expected);
66
    }
67
68
    void add(Watchpoint* watchpoint) const
69
    {
70
        m_object->addWatchpoint(watchpoint);
71
    }
72
73
    bool operator==(const DesiredInferredType& other) const
74
    {
75
        return m_object == other.m_object
76
            && m_expected == other.m_expected;
77
    }
78
79
    bool operator!=(const DesiredInferredType& other) const
80
    {
81
        return !(*this == other);
82
    }
83
84
    bool isHashTableDeletedValue() const
85
    {
86
        return !m_object && m_expected == InferredType::Top;
87
    }
88
89
    unsigned hash() const
90
    {
91
        return WTF::PtrHash<InferredType*>::hash(m_object) + m_expected.hash() * 7;
92
    }
93
94
    void dumpInContext(PrintStream& out, DumpContext* context) const
95
    {
96
        out.print(inContext(m_expected, context), " for ", RawPointer(m_object));
97
    }
98
99
    void dump(PrintStream& out) const
100
    {
101
        dumpInContext(out, nullptr);
102
    }
103
104
private:
105
    InferredType* m_object;
106
    InferredType::Descriptor m_expected;
107
};
108
109
struct DesiredInferredTypeHash {
110
    static unsigned hash(const DesiredInferredType& key) { return key.hash(); }
111
    static bool equal(const DesiredInferredType& a, const DesiredInferredType& b) { return a == b; }
112
    static const bool safeToCompareToEmptyOrDeleted = true;
113
};
114
115
} } // namespace JSC::DFG
116
117
namespace WTF {
118
119
template<typename T> struct DefaultHash;
120
template<> struct DefaultHash<JSC::DFG::DesiredInferredType> {
121
    typedef JSC::DFG::DesiredInferredTypeHash Hash;
122
};
123
124
template<typename T> struct HashTraits;
125
template<> struct HashTraits<JSC::DFG::DesiredInferredType> : SimpleClassHashTraits<JSC::DFG::DesiredInferredType> { };
126
127
} // namespace WTF
128
129
#endif // ENABLE(DFG_JIT)
130
131
#endif // DFGDesiredInferredType_h
132
- Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp -1 / +14 lines
Lines 65-70 void AdaptiveStructureWatchpointAdaptor: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec1
65
    }
65
    }
66
}
66
}
67
67
68
void InferredTypeAdaptor::add(CodeBlock* codeBlock, const DesiredInferredType& key, CommonData& common)
69
{
70
    key.add(common.watchpoints.add(codeBlock));
71
}
72
68
DesiredWatchpoints::DesiredWatchpoints() { }
73
DesiredWatchpoints::DesiredWatchpoints() { }
69
DesiredWatchpoints::~DesiredWatchpoints() { }
74
DesiredWatchpoints::~DesiredWatchpoints() { }
70
75
Lines 93-98 void DesiredWatchpoints::addLazily(const Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec2
93
    m_adaptiveStructureSets.addLazily(key);
98
    m_adaptiveStructureSets.addLazily(key);
94
}
99
}
95
100
101
void DesiredWatchpoints::addLazily(const DesiredInferredType& key)
102
{
103
    m_inferredTypes.addLazily(key);
104
}
105
96
bool DesiredWatchpoints::consider(Structure* structure)
106
bool DesiredWatchpoints::consider(Structure* structure)
97
{
107
{
98
    if (!structure->dfgShouldWatch())
108
    if (!structure->dfgShouldWatch())
Lines 108-113 void DesiredWatchpoints::reallyAdd(CodeB Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec3
108
    m_inferredValues.reallyAdd(codeBlock, commonData);
118
    m_inferredValues.reallyAdd(codeBlock, commonData);
109
    m_bufferViews.reallyAdd(codeBlock, commonData);
119
    m_bufferViews.reallyAdd(codeBlock, commonData);
110
    m_adaptiveStructureSets.reallyAdd(codeBlock, commonData);
120
    m_adaptiveStructureSets.reallyAdd(codeBlock, commonData);
121
    m_inferredTypes.reallyAdd(codeBlock, commonData);
111
}
122
}
112
123
113
bool DesiredWatchpoints::areStillValid() const
124
bool DesiredWatchpoints::areStillValid() const
Lines 116-122 bool DesiredWatchpoints::areStillValid() Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec4
116
        && m_inlineSets.areStillValid()
127
        && m_inlineSets.areStillValid()
117
        && m_inferredValues.areStillValid()
128
        && m_inferredValues.areStillValid()
118
        && m_bufferViews.areStillValid()
129
        && m_bufferViews.areStillValid()
119
        && m_adaptiveStructureSets.areStillValid();
130
        && m_adaptiveStructureSets.areStillValid()
131
        && m_inferredTypes.areStillValid();
120
}
132
}
121
133
122
void DesiredWatchpoints::dumpInContext(PrintStream& out, DumpContext* context) const
134
void DesiredWatchpoints::dumpInContext(PrintStream& out, DumpContext* context) const
Lines 127-132 void DesiredWatchpoints::dumpInContext(P Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec5
127
    out.print("    Inferred values: ", inContext(m_inferredValues, context), "\n");
139
    out.print("    Inferred values: ", inContext(m_inferredValues, context), "\n");
128
    out.print("    Buffer views: ", inContext(m_bufferViews, context), "\n");
140
    out.print("    Buffer views: ", inContext(m_bufferViews, context), "\n");
129
    out.print("    Object property conditions: ", inContext(m_adaptiveStructureSets, context), "\n");
141
    out.print("    Object property conditions: ", inContext(m_adaptiveStructureSets, context), "\n");
142
    out.print("    Inferred types: ", inContext(m_inferredTypes, context), "\n");
130
}
143
}
131
144
132
} } // namespace JSC::DFG
145
} } // namespace JSC::DFG
- Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h +22 lines
Lines 30-35 Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec1
30
30
31
#include "CodeOrigin.h"
31
#include "CodeOrigin.h"
32
#include "DFGCommonData.h"
32
#include "DFGCommonData.h"
33
#include "DFGDesiredInferredType.h"
33
#include "InferredValue.h"
34
#include "InferredValue.h"
34
#include "JSArrayBufferView.h"
35
#include "JSArrayBufferView.h"
35
#include "ObjectPropertyCondition.h"
36
#include "ObjectPropertyCondition.h"
Lines 91-96 struct AdaptiveStructureWatchpointAdapto Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec2
91
    }
92
    }
92
};
93
};
93
94
95
struct InferredTypeAdaptor {
96
    static void add(CodeBlock*, const DesiredInferredType&, CommonData&);
97
    static bool hasBeenInvalidated(const DesiredInferredType& key)
98
    {
99
        return !key.isStillValid();
100
    }
101
    static void dumpInContext(PrintStream& out, const DesiredInferredType& key, DumpContext* context)
102
    {
103
        out.print(inContext(key, context));
104
    }
105
};
106
94
template<typename WatchpointSetType, typename Adaptor = SetPointerAdaptor<WatchpointSetType>>
107
template<typename WatchpointSetType, typename Adaptor = SetPointerAdaptor<WatchpointSetType>>
95
class GenericDesiredWatchpoints {
108
class GenericDesiredWatchpoints {
96
#if !ASSERT_DISABLED
109
#if !ASSERT_DISABLED
Lines 159-164 public: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec3
159
    // It's recommended that you don't call this directly. Use Graph::watchCondition(), which does
172
    // It's recommended that you don't call this directly. Use Graph::watchCondition(), which does
160
    // the required GC magic as well as some other bookkeeping.
173
    // the required GC magic as well as some other bookkeeping.
161
    void addLazily(const ObjectPropertyCondition&);
174
    void addLazily(const ObjectPropertyCondition&);
175
176
    // It's recommended that you don't call this directly. Use Graph::inferredTypeFor(), which does
177
    // the required GC magic.
178
    void addLazily(const DesiredInferredType&);
162
    
179
    
163
    bool consider(Structure*);
180
    bool consider(Structure*);
164
    
181
    
Lines 186-191 public: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec4
186
    {
203
    {
187
        return m_adaptiveStructureSets.isWatched(key);
204
        return m_adaptiveStructureSets.isWatched(key);
188
    }
205
    }
206
    bool isWatched(const DesiredInferredType& key)
207
    {
208
        return m_inferredTypes.isWatched(key);
209
    }
189
210
190
    void dumpInContext(PrintStream&, DumpContext*) const;
211
    void dumpInContext(PrintStream&, DumpContext*) const;
191
    void dump(PrintStream&) const;
212
    void dump(PrintStream&) const;
Lines 196-201 private: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec5
196
    GenericDesiredWatchpoints<InferredValue*, InferredValueAdaptor> m_inferredValues;
217
    GenericDesiredWatchpoints<InferredValue*, InferredValueAdaptor> m_inferredValues;
197
    GenericDesiredWatchpoints<JSArrayBufferView*, ArrayBufferViewWatchpointAdaptor> m_bufferViews;
218
    GenericDesiredWatchpoints<JSArrayBufferView*, ArrayBufferViewWatchpointAdaptor> m_bufferViews;
198
    GenericDesiredWatchpoints<ObjectPropertyCondition, AdaptiveStructureWatchpointAdaptor> m_adaptiveStructureSets;
219
    GenericDesiredWatchpoints<ObjectPropertyCondition, AdaptiveStructureWatchpointAdaptor> m_adaptiveStructureSets;
220
    GenericDesiredWatchpoints<DesiredInferredType, InferredTypeAdaptor> m_inferredTypes;
199
};
221
};
200
222
201
} } // namespace JSC::DFG
223
} } // namespace JSC::DFG
- Source/JavaScriptCore/dfg/DFGFixupPhase.cpp +4 lines
Lines 30-35 Source/JavaScriptCore/dfg/DFGFixupPhase.cpp_sec1
30
30
31
#include "ArrayPrototype.h"
31
#include "ArrayPrototype.h"
32
#include "DFGGraph.h"
32
#include "DFGGraph.h"
33
#include "DFGInferredTypeCheck.h"
33
#include "DFGInsertionSet.h"
34
#include "DFGInsertionSet.h"
34
#include "DFGPhase.h"
35
#include "DFGPhase.h"
35
#include "DFGPredictionPropagationPhase.h"
36
#include "DFGPredictionPropagationPhase.h"
Lines 1092-1097 private: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp_sec2
1092
            if (!node->child1()->hasStorageResult())
1093
            if (!node->child1()->hasStorageResult())
1093
                fixEdge<KnownCellUse>(node->child1());
1094
                fixEdge<KnownCellUse>(node->child1());
1094
            fixEdge<KnownCellUse>(node->child2());
1095
            fixEdge<KnownCellUse>(node->child2());
1096
            insertInferredTypeCheck(
1097
                m_insertionSet, m_indexInBlock, node->origin, node->child3().node(),
1098
                node->storageAccessData().inferredType);
1095
            speculateForBarrier(node->child3());
1099
            speculateForBarrier(node->child3());
1096
            break;
1100
            break;
1097
        }
1101
        }
- Source/JavaScriptCore/dfg/DFGGraph.cpp -2 / +69 lines
Lines 261-272 void Graph::dump(PrintStream& out, const Source/JavaScriptCore/dfg/DFGGraph.cpp_sec1
261
        StorageAccessData& storageAccessData = node->storageAccessData();
261
        StorageAccessData& storageAccessData = node->storageAccessData();
262
        out.print(comma, "id", storageAccessData.identifierNumber, "{", identifiers()[storageAccessData.identifierNumber], "}");
262
        out.print(comma, "id", storageAccessData.identifierNumber, "{", identifiers()[storageAccessData.identifierNumber], "}");
263
        out.print(", ", static_cast<ptrdiff_t>(storageAccessData.offset));
263
        out.print(", ", static_cast<ptrdiff_t>(storageAccessData.offset));
264
        out.print(", inferredType = ", inContext(storageAccessData.inferredType, context));
264
    }
265
    }
265
    if (node->hasMultiGetByOffsetData()) {
266
    if (node->hasMultiGetByOffsetData()) {
266
        MultiGetByOffsetData& data = node->multiGetByOffsetData();
267
        MultiGetByOffsetData& data = node->multiGetByOffsetData();
267
        out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
268
        out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
268
        for (unsigned i = 0; i < data.cases.size(); ++i)
269
        for (unsigned i = 0; i < data.cases.size(); ++i) {
269
            out.print(comma, inContext(data.cases[i], context));
270
            out.print(comma, inContext(data.cases[i], context));
271
            if (data.cases[i].method().kind() == GetByOffsetMethod::Load)
272
                out.print(" (inferred value = ", inContext(inferredValueForProperty(data.cases[i].set(), identifiers()[data.identifierNumber]), context), ")");
273
        }
270
    }
274
    }
271
    if (node->hasMultiPutByOffsetData()) {
275
    if (node->hasMultiPutByOffsetData()) {
272
        MultiPutByOffsetData& data = node->multiPutByOffsetData();
276
        MultiPutByOffsetData& data = node->multiPutByOffsetData();
Lines 887-892 bool Graph::isSafeToLoad(JSObject* base, Source/JavaScriptCore/dfg/DFGGraph.cpp_sec2
887
    return m_safeToLoad.contains(std::make_pair(base, offset));
891
    return m_safeToLoad.contains(std::make_pair(base, offset));
888
}
892
}
889
893
894
InferredType::Descriptor Graph::inferredTypeFor(const PropertyTypeKey& key)
895
{
896
    assertIsRegistered(key.structure());
897
    
898
    auto iter = m_inferredTypes.find(key);
899
    if (iter != m_inferredTypes.end())
900
        return iter->value;
901
902
    InferredType* typeObject = key.structure()->inferredTypeFor(key.uid());
903
    if (!typeObject) {
904
        m_inferredTypes.add(key, InferredType::Top);
905
        return InferredType::Top;
906
    }
907
908
    InferredType::Descriptor typeDescriptor = typeObject->descriptor();
909
    if (typeDescriptor.kind() == InferredType::Top) {
910
        m_inferredTypes.add(key, InferredType::Top);
911
        return InferredType::Top;
912
    }
913
    
914
    m_inferredTypes.add(key, typeDescriptor);
915
916
    m_plan.weakReferences.addLazily(typeObject);
917
    registerInferredType(typeDescriptor);
918
919
    // Note that we may already be watching this desired inferred type, because multiple structures may
920
    // point to the same InferredType instance.
921
    m_plan.watchpoints.addLazily(DesiredInferredType(typeObject, typeDescriptor));
922
923
    return typeDescriptor;
924
}
925
890
FullBytecodeLiveness& Graph::livenessFor(CodeBlock* codeBlock)
926
FullBytecodeLiveness& Graph::livenessFor(CodeBlock* codeBlock)
891
{
927
{
892
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>>::iterator iter = m_bytecodeLiveness.find(codeBlock);
928
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>>::iterator iter = m_bytecodeLiveness.find(codeBlock);
Lines 1061-1067 JSValue Graph::tryGetConstantProperty(JS Source/JavaScriptCore/dfg/DFGGraph.cpp_sec3
1061
JSValue Graph::tryGetConstantProperty(
1097
JSValue Graph::tryGetConstantProperty(
1062
    JSValue base, const StructureAbstractValue& structure, PropertyOffset offset)
1098
    JSValue base, const StructureAbstractValue& structure, PropertyOffset offset)
1063
{
1099
{
1064
    if (structure.isTop() || structure.isClobbered()) {
1100
    if (structure.isInfinite()) {
1065
        // FIXME: If we just converted the offset to a uid, we could do ObjectPropertyCondition
1101
        // FIXME: If we just converted the offset to a uid, we could do ObjectPropertyCondition
1066
        // watching to constant-fold the property.
1102
        // watching to constant-fold the property.
1067
        // https://bugs.webkit.org/show_bug.cgi?id=147271
1103
        // https://bugs.webkit.org/show_bug.cgi?id=147271
Lines 1076-1081 JSValue Graph::tryGetConstantProperty(co Source/JavaScriptCore/dfg/DFGGraph.cpp_sec4
1076
    return tryGetConstantProperty(base.m_value, base.m_structure, offset);
1112
    return tryGetConstantProperty(base.m_value, base.m_structure, offset);
1077
}
1113
}
1078
1114
1115
AbstractValue Graph::inferredValueForProperty(
1116
    const StructureSet& base, UniquedStringImpl* uid, StructureClobberState clobberState)
1117
{
1118
    AbstractValue result;
1119
    base.forEach(
1120
        [&] (Structure* structure) {
1121
            AbstractValue value;
1122
            value.set(*this, inferredTypeForProperty(structure, uid));
1123
            result.merge(value);
1124
        });
1125
    if (clobberState == StructuresAreClobbered)
1126
        result.clobberStructures();
1127
    return result;
1128
}
1129
1130
AbstractValue Graph::inferredValueForProperty(
1131
    const AbstractValue& base, UniquedStringImpl* uid, PropertyOffset offset,
1132
    StructureClobberState clobberState)
1133
{
1134
    if (JSValue value = tryGetConstantProperty(base, offset)) {
1135
        AbstractValue result;
1136
        result.set(*this, *freeze(value), clobberState);
1137
        return result;
1138
    }
1139
1140
    if (base.m_structure.isFinite())
1141
        return inferredValueForProperty(base.m_structure.set(), uid, clobberState);
1142
1143
    return AbstractValue::heapTop();
1144
}
1145
1079
JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset)
1146
JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset)
1080
{
1147
{
1081
    // This has an awesome concurrency story. See comment for GetGlobalVar in ByteCodeParser.
1148
    // This has an awesome concurrency story. See comment for GetGlobalVar in ByteCodeParser.
- Source/JavaScriptCore/dfg/DFGGraph.h +23 lines
Lines 41-46 Source/JavaScriptCore/dfg/DFGGraph.h_sec1
41
#include "DFGNodeAllocator.h"
41
#include "DFGNodeAllocator.h"
42
#include "DFGPlan.h"
42
#include "DFGPlan.h"
43
#include "DFGPrePostNumbering.h"
43
#include "DFGPrePostNumbering.h"
44
#include "DFGPropertyTypeKey.h"
44
#include "DFGScannable.h"
45
#include "DFGScannable.h"
45
#include "FullBytecodeLiveness.h"
46
#include "FullBytecodeLiveness.h"
46
#include "JSStack.h"
47
#include "JSStack.h"
Lines 675-680 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec2
675
    // Checks if it's known that loading from the given object at the given offset is fine. This is
676
    // Checks if it's known that loading from the given object at the given offset is fine. This is
676
    // computed by tracking which conditions we track with watchCondition().
677
    // computed by tracking which conditions we track with watchCondition().
677
    bool isSafeToLoad(JSObject* base, PropertyOffset);
678
    bool isSafeToLoad(JSObject* base, PropertyOffset);
679
680
    void registerInferredType(const InferredType::Descriptor& type)
681
    {
682
        if (type.structure())
683
            registerStructure(type.structure());
684
    }
685
686
    // Tells us what inferred type we are able to prove the property to have now and in the future.
687
    InferredType::Descriptor inferredTypeFor(const PropertyTypeKey&);
688
    InferredType::Descriptor inferredTypeForProperty(Structure* structure, UniquedStringImpl* uid)
689
    {
690
        return inferredTypeFor(PropertyTypeKey(structure, uid));
691
    }
692
693
    AbstractValue inferredValueForProperty(
694
        const StructureSet& base, UniquedStringImpl* uid, StructureClobberState = StructuresAreWatched);
695
696
    // This uses either constant property inference or property type inference to derive a good abstract
697
    // value for some property accessed with the given abstract value base.
698
    AbstractValue inferredValueForProperty(
699
        const AbstractValue& base, UniquedStringImpl* uid, PropertyOffset, StructureClobberState);
678
    
700
    
679
    FullBytecodeLiveness& livenessFor(CodeBlock*);
701
    FullBytecodeLiveness& livenessFor(CodeBlock*);
680
    FullBytecodeLiveness& livenessFor(InlineCallFrame*);
702
    FullBytecodeLiveness& livenessFor(InlineCallFrame*);
Lines 856-861 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec3
856
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
878
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
857
    HashMap<CodeBlock*, std::unique_ptr<BytecodeKills>> m_bytecodeKills;
879
    HashMap<CodeBlock*, std::unique_ptr<BytecodeKills>> m_bytecodeKills;
858
    HashSet<std::pair<JSObject*, PropertyOffset>> m_safeToLoad;
880
    HashSet<std::pair<JSObject*, PropertyOffset>> m_safeToLoad;
881
    HashMap<PropertyTypeKey, InferredType::Descriptor> m_inferredTypes;
859
    Dominators m_dominators;
882
    Dominators m_dominators;
860
    PrePostNumbering m_prePostNumbering;
883
    PrePostNumbering m_prePostNumbering;
861
    NaturalLoops m_naturalLoops;
884
    NaturalLoops m_naturalLoops;
- Source/JavaScriptCore/dfg/DFGInferredTypeCheck.cpp +98 lines
Line 0 Source/JavaScriptCore/dfg/DFGInferredTypeCheck.cpp_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "DFGInferredTypeCheck.h"
28
29
#if ENABLE(DFG_JIT)
30
31
#include "JSCInlines.h"
32
33
namespace JSC { namespace DFG {
34
35
void insertInferredTypeCheck(
36
    InsertionSet& insertionSet, unsigned nodeIndex, NodeOrigin origin, Node* baseNode,
37
    const InferredType::Descriptor& type)
38
{
39
    insertionSet.graph().registerInferredType(type);
40
    
41
    switch (type.kind()) {
42
    case InferredType::Bottom:
43
        insertionSet.insertNode(nodeIndex, SpecNone, ForceOSRExit, origin);
44
        return;
45
46
    case InferredType::Boolean:
47
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, BooleanUse));
48
        return;
49
50
    case InferredType::Other:
51
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, OtherUse));
52
        return;
53
54
    case InferredType::Int32:
55
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, Int32Use));
56
        return;
57
58
    case InferredType::Number:
59
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, NumberUse));
60
        return;
61
62
    case InferredType::String:
63
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, StringUse));
64
        return;
65
66
    case InferredType::ObjectWithStructure:
67
        insertionSet.insertNode(
68
            nodeIndex, SpecNone, CheckStructure, origin,
69
            OpInfo(insertionSet.graph().addStructureSet(type.structure())),
70
            Edge(baseNode, CellUse));
71
        return;
72
73
    case InferredType::ObjectWithStructureOrOther:
74
        insertionSet.insertNode(
75
            nodeIndex, SpecNone, CheckStructure, origin,
76
            OpInfo(insertionSet.graph().addStructureSet(type.structure())),
77
            Edge(baseNode, CellOrOtherUse));
78
        return;
79
80
    case InferredType::Object:
81
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, ObjectUse));
82
        return;
83
84
    case InferredType::ObjectOrOther:
85
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, ObjectOrOtherUse));
86
        return;
87
88
    case InferredType::Top:
89
        return;
90
    }
91
92
    DFG_CRASH(insertionSet.graph(), baseNode, "Bad inferred type");
93
}
94
95
} } // namespace JSC::DFG
96
97
#endif // ENABLE(DFG_JIT)
98
- Source/JavaScriptCore/dfg/DFGInferredTypeCheck.h +45 lines
Line 0 Source/JavaScriptCore/dfg/DFGInferredTypeCheck.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#ifndef DFGInferredTypeCheck_h
27
#define DFGInferredTypeCheck_h
28
29
#if ENABLE(DFG_JIT)
30
31
#include "DFGInsertionSet.h"
32
#include "InferredType.h"
33
34
namespace JSC { namespace DFG {
35
36
// Inserts a type check that ensures that baseNode has the given inferred type.
37
void insertInferredTypeCheck(
38
    InsertionSet&, unsigned nodeIndex, NodeOrigin, Node* baseNode, const InferredType::Descriptor&);
39
40
} } // namespace JSC::DFG
41
42
#endif // ENABLE(DFG_JIT)
43
44
#endif // DFGInferredTypeCheck_h
45
- Source/JavaScriptCore/dfg/DFGNode.h +5 lines
Lines 64-69 struct BasicBlock; Source/JavaScriptCore/dfg/DFGNode.h_sec1
64
struct StorageAccessData {
64
struct StorageAccessData {
65
    PropertyOffset offset;
65
    PropertyOffset offset;
66
    unsigned identifierNumber;
66
    unsigned identifierNumber;
67
68
    // This needs to know the inferred type. For puts, this is necessary because we need to remember
69
    // what check is needed. For gets, this is necessary because otherwise AI might forget what type is
70
    // guaranteed.
71
    InferredType::Descriptor inferredType;
67
};
72
};
68
73
69
struct MultiPutByOffsetData {
74
struct MultiPutByOffsetData {
- Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp -2 / +8 lines
Lines 2135-2148 private: Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp_sec1
2135
                for (Structure* structure : structures) {
2135
                for (Structure* structure : structures) {
2136
                    PropertyOffset offset = structure->getConcurrently(uid);
2136
                    PropertyOffset offset = structure->getConcurrently(uid);
2137
                    if (offset != currentOffset) {
2137
                    if (offset != currentOffset) {
2138
                        // Because our analysis treats MultiPutByOffset like an escape, we only have to
2139
                        // deal with storing results that would have been previously stored by PutByOffset
2140
                        // nodes. Those nodes were guarded by the appropriate type checks. This means that
2141
                        // at this point, we can simply trust that the incoming value has the right type
2142
                        // for whatever structure we are using.
2138
                        data->variants.append(
2143
                        data->variants.append(
2139
                            PutByIdVariant::replace(currentSet, currentOffset));
2144
                            PutByIdVariant::replace(currentSet, currentOffset, InferredType::Top));
2140
                        currentOffset = offset;
2145
                        currentOffset = offset;
2141
                        currentSet.clear();
2146
                        currentSet.clear();
2142
                    }
2147
                    }
2143
                    currentSet.add(structure);
2148
                    currentSet.add(structure);
2144
                }
2149
                }
2145
                data->variants.append(PutByIdVariant::replace(currentSet, currentOffset));
2150
                data->variants.append(
2151
                    PutByIdVariant::replace(currentSet, currentOffset, InferredType::Top));
2146
            }
2152
            }
2147
2153
2148
            return m_graph.addNode(
2154
            return m_graph.addNode(
- Source/JavaScriptCore/dfg/DFGPropertyTypeKey.h +129 lines
Line 0 Source/JavaScriptCore/dfg/DFGPropertyTypeKey.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef DFGPropertyTypeKey_h
27
#define DFGPropertyTypeKey_h
28
29
#if ENABLE(DFG_JIT)
30
31
#include "Structure.h"
32
#include <wtf/HashMap.h>
33
34
namespace JSC { namespace DFG {
35
36
// This object is a key for finding a property's type. It's a tuple of Structure* and UniquedStringImpl*.
37
38
class PropertyTypeKey {
39
public:
40
    PropertyTypeKey()
41
        : m_structure(nullptr)
42
        , m_uid(nullptr)
43
    {
44
    }
45
46
    PropertyTypeKey(Structure* structure, UniquedStringImpl* uid)
47
        : m_structure(structure)
48
        , m_uid(uid)
49
    {
50
    }
51
52
    PropertyTypeKey(WTF::HashTableDeletedValueType)
53
        : m_structure(nullptr)
54
        , m_uid(deletedUID())
55
    {
56
    }
57
58
    explicit operator bool() const { return m_structure && m_uid; }
59
60
    Structure* structure() const { return m_structure; }
61
    UniquedStringImpl* uid() const { return m_uid; }
62
63
    bool operator==(const PropertyTypeKey& other) const
64
    {
65
        return m_structure == other.m_structure
66
            && m_uid == other.m_uid;
67
    }
68
69
    bool operator!=(const PropertyTypeKey& other) const
70
    {
71
        return !(*this == other);
72
    }
73
74
    unsigned hash() const
75
    {
76
        return WTF::PtrHash<Structure*>::hash(m_structure) + WTF::PtrHash<UniquedStringImpl*>::hash(m_uid);
77
    }
78
79
    bool isHashTableDeletedValue() const
80
    {
81
        return !m_structure && m_uid == deletedUID();
82
    }
83
84
    void dumpInContext(PrintStream& out, DumpContext* context) const
85
    {
86
        out.print(pointerDumpInContext(m_structure, context), "+", m_uid);
87
    }
88
89
    void dump(PrintStream& out) const
90
    {
91
        dumpInContext(out, nullptr);
92
    }
93
94
private:
95
    static UniquedStringImpl* deletedUID()
96
    {
97
        return bitwise_cast<UniquedStringImpl*>(static_cast<intptr_t>(1));
98
    }
99
    
100
    Structure* m_structure;
101
    UniquedStringImpl* m_uid;
102
};
103
104
struct PropertyTypeKeyHash {
105
    static unsigned hash(const PropertyTypeKey& key) { return key.hash(); }
106
    static bool equal(const PropertyTypeKey& a, const PropertyTypeKey& b) { return a == b; }
107
    static const bool safeToCompareToEmptyOrDeleted = true;
108
};
109
110
} } // namespace JSC::DFG
111
112
namespace WTF {
113
114
template<typename T> struct DefaultHash;
115
template<> struct DefaultHash<JSC::DFG::PropertyTypeKey> {
116
    typedef JSC::DFG::PropertyTypeKeyHash Hash;
117
};
118
119
template<typename T> struct HashTraits;
120
template<> struct HashTraits<JSC::DFG::PropertyTypeKey> : SimpleClassHashTraits<JSC::DFG::PropertyTypeKey> {
121
    static const bool emptyValueIsZero = false;
122
};
123
124
} // namespace WTF
125
126
#endif // ENABLE(DFG_JIT)
127
128
#endif // DFGPropertyTypeKey_h
129
- Source/JavaScriptCore/dfg/DFGSafeToExecute.h +4 lines
Lines 53-58 public: Source/JavaScriptCore/dfg/DFGSafeToExecute.h_sec1
53
        case RealNumberUse:
53
        case RealNumberUse:
54
        case BooleanUse:
54
        case BooleanUse:
55
        case CellUse:
55
        case CellUse:
56
        case CellOrOtherUse:
56
        case ObjectUse:
57
        case ObjectUse:
57
        case FunctionUse:
58
        case FunctionUse:
58
        case FinalObjectUse:
59
        case FinalObjectUse:
Lines 127-132 bool safeToExecute(AbstractStateType& st Source/JavaScriptCore/dfg/DFGSafeToExecute.h_sec2
127
    if (!safeToExecuteEdge.result())
128
    if (!safeToExecuteEdge.result())
128
        return false;
129
        return false;
129
130
131
    // NOTE: This tends to lie when it comes to effectful nodes, because it knows that they aren't going to
132
    // get hoisted anyway.
133
130
    switch (node->op()) {
134
    switch (node->op()) {
131
    case JSConstant:
135
    case JSConstant:
132
    case DoubleConstant:
136
    case DoubleConstant:
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp -30 / +1 lines
Lines 3901-3936 void SpeculativeJIT::compile(Node* node) Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp_sec1
3901
    }
3901
    }
3902
        
3902
        
3903
    case CheckStructure: {
3903
    case CheckStructure: {
3904
        SpeculateCellOperand base(this, node->child1());
3904
        compileCheckStructure(node);
3905
        
3906
        ASSERT(node->structureSet().size());
3907
        
3908
        if (node->structureSet().size() == 1) {
3909
            speculationCheck(
3910
                BadCache, JSValueSource::unboxedCell(base.gpr()), 0,
3911
                m_jit.branchWeakPtr(
3912
                    JITCompiler::NotEqual,
3913
                    JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()),
3914
                    node->structureSet()[0]));
3915
        } else {
3916
            GPRTemporary structure(this);
3917
            
3918
            m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()), structure.gpr());
3919
            
3920
            JITCompiler::JumpList done;
3921
            
3922
            for (size_t i = 0; i < node->structureSet().size() - 1; ++i)
3923
                done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node->structureSet()[i]));
3924
            
3925
            speculationCheck(
3926
                BadCache, JSValueSource::unboxedCell(base.gpr()), 0,
3927
                m_jit.branchWeakPtr(
3928
                    JITCompiler::NotEqual, structure.gpr(), node->structureSet().last()));
3929
            
3930
            done.link(&m_jit);
3931
        }
3932
        
3933
        noResult(node);
3934
        break;
3905
        break;
3935
    }
3906
    }
3936
        
3907
        
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp -32 / +1 lines
Lines 3916-3953 void SpeculativeJIT::compile(Node* node) Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp_sec1
3916
    }
3916
    }
3917
        
3917
        
3918
    case CheckStructure: {
3918
    case CheckStructure: {
3919
        SpeculateCellOperand base(this, node->child1());
3919
        compileCheckStructure(node);
3920
        
3921
        ASSERT(node->structureSet().size());
3922
        
3923
        ExitKind exitKind;
3924
        if (node->child1()->hasConstant())
3925
            exitKind = BadConstantCache;
3926
        else
3927
            exitKind = BadCache;
3928
        
3929
        if (node->structureSet().size() == 1) {
3930
            speculationCheck(
3931
                exitKind, JSValueSource::unboxedCell(base.gpr()), 0,
3932
                m_jit.branchWeakStructure(
3933
                    JITCompiler::NotEqual,
3934
                    JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()),
3935
                    node->structureSet()[0]));
3936
        } else {
3937
            JITCompiler::JumpList done;
3938
            
3939
            for (size_t i = 0; i < node->structureSet().size() - 1; ++i)
3940
                done.append(m_jit.branchWeakStructure(JITCompiler::Equal, MacroAssembler::Address(base.gpr(), JSCell::structureIDOffset()), node->structureSet()[i]));
3941
            
3942
            speculationCheck(
3943
                exitKind, JSValueSource::unboxedCell(base.gpr()), 0,
3944
                m_jit.branchWeakStructure(
3945
                    JITCompiler::NotEqual, MacroAssembler::Address(base.gpr(), JSCell::structureIDOffset()), node->structureSet().last()));
3946
            
3947
            done.link(&m_jit);
3948
        }
3949
        
3950
        noResult(node);
3951
        break;
3920
        break;
3952
    }
3921
    }
3953
        
3922
        
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +94 lines
Lines 5232-5237 void SpeculativeJIT::compileTypeOf(Node* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec1
5232
    cellResult(resultGPR, node);
5232
    cellResult(resultGPR, node);
5233
}
5233
}
5234
5234
5235
void SpeculativeJIT::compileCheckStructure(Node* node, GPRReg cellGPR, GPRReg tempGPR)
5236
{
5237
    ASSERT(node->structureSet().size());
5238
    
5239
    if (node->structureSet().size() == 1) {
5240
        speculationCheck(
5241
            BadCache, JSValueSource::unboxedCell(cellGPR), 0,
5242
            m_jit.branchWeakStructure(
5243
                JITCompiler::NotEqual,
5244
                JITCompiler::Address(cellGPR, JSCell::structureIDOffset()),
5245
                node->structureSet()[0]));
5246
    } else {
5247
        std::unique_ptr<GPRTemporary> structure;
5248
        GPRReg structureGPR;
5249
        
5250
        if (tempGPR == InvalidGPRReg) {
5251
            structure = std::make_unique<GPRTemporary>(this);
5252
            structureGPR = structure->gpr();
5253
        } else
5254
            structureGPR = tempGPR;
5255
        
5256
        m_jit.load32(JITCompiler::Address(cellGPR, JSCell::structureIDOffset()), structureGPR);
5257
        
5258
        JITCompiler::JumpList done;
5259
        
5260
        for (size_t i = 0; i < node->structureSet().size() - 1; ++i) {
5261
            done.append(
5262
                m_jit.branchWeakStructure(JITCompiler::Equal, structureGPR, node->structureSet()[i]));
5263
        }
5264
        
5265
        speculationCheck(
5266
            BadCache, JSValueSource::unboxedCell(cellGPR), 0,
5267
            m_jit.branchWeakStructure(
5268
                JITCompiler::NotEqual, structureGPR, node->structureSet().last()));
5269
        
5270
        done.link(&m_jit);
5271
    }
5272
}
5273
5274
void SpeculativeJIT::compileCheckStructure(Node* node)
5275
{
5276
    switch (node->child1().useKind()) {
5277
    case CellUse:
5278
    case KnownCellUse: {
5279
        SpeculateCellOperand cell(this, node->child1());
5280
        compileCheckStructure(node, cell.gpr(), InvalidGPRReg);
5281
        noResult(node);
5282
        return;
5283
    }
5284
5285
    case CellOrOtherUse: {
5286
        JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
5287
        GPRTemporary temp(this);
5288
5289
        JSValueRegs valueRegs = value.jsValueRegs();
5290
        GPRReg tempGPR = temp.gpr();
5291
5292
        JITCompiler::Jump cell = m_jit.branchIfCell(valueRegs);
5293
        DFG_TYPE_CHECK(
5294
            valueRegs, node->child1(), SpecCell | SpecOther,
5295
            m_jit.branchIfNotOther(valueRegs, tempGPR));
5296
        JITCompiler::Jump done = m_jit.jump();
5297
        cell.link(&m_jit);
5298
        compileCheckStructure(node, valueRegs.payloadGPR(), tempGPR);
5299
        done.link(&m_jit);
5300
        noResult(node);
5301
        return;
5302
    }
5303
5304
    default:
5305
        DFG_CRASH(m_jit.graph(), node, "Bad use kind");
5306
        return;
5307
    }
5308
}
5309
5235
void SpeculativeJIT::compileAllocatePropertyStorage(Node* node)
5310
void SpeculativeJIT::compileAllocatePropertyStorage(Node* node)
5236
{
5311
{
5237
    if (node->transition()->previous->couldHaveIndexingHeader()) {
5312
    if (node->transition()->previous->couldHaveIndexingHeader()) {
Lines 5636-5641 void SpeculativeJIT::speculateCell(Edge Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec2
5636
    (SpeculateCellOperand(this, edge)).gpr();
5711
    (SpeculateCellOperand(this, edge)).gpr();
5637
}
5712
}
5638
5713
5714
void SpeculativeJIT::speculateCellOrOther(Edge edge)
5715
{
5716
    if (!needsTypeCheck(edge, SpecCell | SpecOther))
5717
        return;
5718
    
5719
    JSValueOperand operand(this, edge, ManualOperandSpeculation);
5720
    GPRTemporary temp(this);
5721
    GPRReg tempGPR = temp.gpr();
5722
5723
    MacroAssembler::Jump ok = m_jit.branchIfCell(operand.jsValueRegs());
5724
    DFG_TYPE_CHECK(
5725
        operand.jsValueRegs(), edge, SpecCell | SpecOther,
5726
        m_jit.branchIfNotOther(operand.jsValueRegs(), tempGPR));
5727
    ok.link(&m_jit);
5728
}
5729
5639
void SpeculativeJIT::speculateObject(Edge edge)
5730
void SpeculativeJIT::speculateObject(Edge edge)
5640
{
5731
{
5641
    if (!needsTypeCheck(edge, SpecObject))
5732
    if (!needsTypeCheck(edge, SpecObject))
Lines 5916-5921 void SpeculativeJIT::speculate(Node*, Ed Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec3
5916
    case CellUse:
6007
    case CellUse:
5917
        speculateCell(edge);
6008
        speculateCell(edge);
5918
        break;
6009
        break;
6010
    case CellOrOtherUse:
6011
        speculateCellOrOther(edge);
6012
        break;
5919
    case ObjectUse:
6013
    case ObjectUse:
5920
        speculateObject(edge);
6014
        speculateObject(edge);
5921
        break;
6015
        break;
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +3 lines
Lines 2215-2220 public: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec1
2215
    void compileIsObjectOrNull(Node*);
2215
    void compileIsObjectOrNull(Node*);
2216
    void compileIsFunction(Node*);
2216
    void compileIsFunction(Node*);
2217
    void compileTypeOf(Node*);
2217
    void compileTypeOf(Node*);
2218
    void compileCheckStructure(Node*, GPRReg cellGPR, GPRReg tempGPR);
2219
    void compileCheckStructure(Node*);
2218
    
2220
    
2219
    void moveTrueTo(GPRReg);
2221
    void moveTrueTo(GPRReg);
2220
    void moveFalseTo(GPRReg);
2222
    void moveFalseTo(GPRReg);
Lines 2374-2379 public: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec2
2374
    void speculateDoubleRepReal(Edge);
2376
    void speculateDoubleRepReal(Edge);
2375
    void speculateBoolean(Edge);
2377
    void speculateBoolean(Edge);
2376
    void speculateCell(Edge);
2378
    void speculateCell(Edge);
2379
    void speculateCellOrOther(Edge);
2377
    void speculateObject(Edge);
2380
    void speculateObject(Edge);
2378
    void speculateFunction(Edge);
2381
    void speculateFunction(Edge);
2379
    void speculateFinalObject(Edge);
2382
    void speculateFinalObject(Edge);
- Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp -6 / +1 lines
Lines 314-320 private: Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp_sec1
314
            case AllocatePropertyStorage:
314
            case AllocatePropertyStorage:
315
            case ReallocatePropertyStorage:
315
            case ReallocatePropertyStorage:
316
                // These allocate but then run their own barrier.
316
                // These allocate but then run their own barrier.
317
                insertBarrierWithInvalidExit(m_nodeIndex + 1, Edge(m_node->child1().node(), KnownCellUse));
317
                insertBarrier(m_nodeIndex + 1, Edge(m_node->child1().node(), KnownCellUse));
318
                m_node->setEpoch(Epoch());
318
                m_node->setEpoch(Epoch());
319
                break;
319
                break;
320
                
320
                
Lines 481-491 private: Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp_sec2
481
        insertBarrier(m_nodeIndex, base);
481
        insertBarrier(m_nodeIndex, base);
482
    }
482
    }
483
483
484
    void insertBarrierWithInvalidExit(unsigned nodeIndex, Edge base)
485
    {
486
        insertBarrier(nodeIndex, base, false);
487
    }
488
489
    void insertBarrier(unsigned nodeIndex, Edge base, bool exitOK = true)
484
    void insertBarrier(unsigned nodeIndex, Edge base, bool exitOK = true)
490
    {
485
    {
491
        // If we're in global mode, we should only insert the barriers once we have converged.
486
        // If we're in global mode, we should only insert the barriers once we have converged.
- Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h -1 / +8 lines
Lines 192-198 public: Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h_sec1
192
    }
192
    }
193
    
193
    
194
    Structure* operator[](size_t i) const { return at(i); }
194
    Structure* operator[](size_t i) const { return at(i); }
195
    
195
196
    // In most cases, what you really want to do is verify whether the set is top or clobbered, and
196
    // In most cases, what you really want to do is verify whether the set is top or clobbered, and
197
    // if not, enumerate the set of structures. Use this only in cases where the singleton case is
197
    // if not, enumerate the set of structures. Use this only in cases where the singleton case is
198
    // meaningfully special, like for transitions.
198
    // meaningfully special, like for transitions.
Lines 202-207 public: Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h_sec2
202
            return nullptr;
202
            return nullptr;
203
        return m_set.onlyStructure();
203
        return m_set.onlyStructure();
204
    }
204
    }
205
206
    template<typename Functor>
207
    void forEach(const Functor& functor) const
208
    {
209
        ASSERT(!isTop());
210
        m_set.forEach(functor);
211
    }
205
    
212
    
206
    void dumpInContext(PrintStream&, DumpContext*) const;
213
    void dumpInContext(PrintStream&, DumpContext*) const;
207
    void dump(PrintStream&) const;
214
    void dump(PrintStream&) const;
- Source/JavaScriptCore/dfg/DFGUseKind.cpp +3 lines
Lines 79-84 void printInternal(PrintStream& out, Use Source/JavaScriptCore/dfg/DFGUseKind.cpp_sec1
79
    case KnownCellUse:
79
    case KnownCellUse:
80
        out.print("KnownCell");
80
        out.print("KnownCell");
81
        return;
81
        return;
82
    case CellOrOtherUse:
83
        out.print("CellOrOther");
84
        return;
82
    case ObjectUse:
85
    case ObjectUse:
83
        out.print("Object");
86
        out.print("Object");
84
        return;
87
        return;
- Source/JavaScriptCore/dfg/DFGUseKind.h +3 lines
Lines 51-56 enum UseKind { Source/JavaScriptCore/dfg/DFGUseKind.h_sec1
51
    KnownBooleanUse,
51
    KnownBooleanUse,
52
    CellUse,
52
    CellUse,
53
    KnownCellUse,
53
    KnownCellUse,
54
    CellOrOtherUse,
54
    ObjectUse,
55
    ObjectUse,
55
    FunctionUse,
56
    FunctionUse,
56
    FinalObjectUse,
57
    FinalObjectUse,
Lines 108-113 inline SpeculatedType typeFilterFor(UseK Source/JavaScriptCore/dfg/DFGUseKind.h_sec2
108
    case CellUse:
109
    case CellUse:
109
    case KnownCellUse:
110
    case KnownCellUse:
110
        return SpecCell;
111
        return SpecCell;
112
    case CellOrOtherUse:
113
        return SpecCell | SpecOther;
111
    case ObjectUse:
114
    case ObjectUse:
112
        return SpecObject;
115
        return SpecObject;
113
    case FunctionUse:
116
    case FunctionUse:
- Source/JavaScriptCore/dfg/DFGValidate.cpp +3 lines
Lines 263-268 public: Source/JavaScriptCore/dfg/DFGValidate.cpp_sec1
263
                    VALIDATE((node), !!node->child1());
263
                    VALIDATE((node), !!node->child1());
264
                    VALIDATE((node), !!node->child2());
264
                    VALIDATE((node), !!node->child2());
265
                    break;
265
                    break;
266
                case CheckStructure:
267
                    VALIDATE((node), !!node->child1());
268
                    break;
266
                case PutStructure:
269
                case PutStructure:
267
                    VALIDATE((node), !node->transition()->previous->dfgShouldWatch());
270
                    VALIDATE((node), !node->transition()->previous->dfgShouldWatch());
268
                    break;
271
                    break;
- Source/JavaScriptCore/ftl/FTLCapabilities.cpp +1 lines
Lines 418-423 CapabilityLevel canCompile(Graph& graph) Source/JavaScriptCore/ftl/FTLCapabilities.cpp_sec1
418
                case KnownBooleanUse:
418
                case KnownBooleanUse:
419
                case CellUse:
419
                case CellUse:
420
                case KnownCellUse:
420
                case KnownCellUse:
421
                case CellOrOtherUse:
421
                case ObjectUse:
422
                case ObjectUse:
422
                case FunctionUse:
423
                case FunctionUse:
423
                case ObjectOrOtherUse:
424
                case ObjectOrOtherUse:
- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp -11 / +205 lines
Lines 2026-2046 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
2026
    
2026
    
2027
    void compileCheckStructure()
2027
    void compileCheckStructure()
2028
    {
2028
    {
2029
        LValue cell = lowCell(m_node->child1());
2030
        
2031
        ExitKind exitKind;
2029
        ExitKind exitKind;
2032
        if (m_node->child1()->hasConstant())
2030
        if (m_node->child1()->hasConstant())
2033
            exitKind = BadConstantCache;
2031
            exitKind = BadConstantCache;
2034
        else
2032
        else
2035
            exitKind = BadCache;
2033
            exitKind = BadCache;
2036
        
2034
2037
        LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
2035
        switch (m_node->child1().useKind()) {
2038
        
2036
        case CellUse:
2039
        checkStructure(
2037
        case KnownCellUse: {
2040
            structureID, jsValueValue(cell), exitKind, m_node->structureSet(),
2038
            LValue cell = lowCell(m_node->child1());
2041
            [this] (Structure* structure) {
2039
            
2042
                return weakStructureID(structure);
2040
            checkStructure(
2043
            });
2041
                m_out.load32(cell, m_heaps.JSCell_structureID), jsValueValue(cell),
2042
                exitKind, m_node->structureSet(),
2043
                [&] (Structure* structure) {
2044
                    return weakStructureID(structure);
2045
                });
2046
            return;
2047
        }
2048
2049
        case CellOrOtherUse: {
2050
            LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
2051
2052
            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse cell case"));
2053
            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse not cell case"));
2054
            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse continuation"));
2055
2056
            m_out.branch(
2057
                isCell(value, provenType(m_node->child1())), unsure(cellCase), unsure(notCellCase));
2058
2059
            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
2060
            checkStructure(
2061
                m_out.load32(value, m_heaps.JSCell_structureID), jsValueValue(value),
2062
                exitKind, m_node->structureSet(),
2063
                [&] (Structure* structure) {
2064
                    return weakStructureID(structure);
2065
                });
2066
            m_out.jump(continuation);
2067
2068
            m_out.appendTo(notCellCase, continuation);
2069
            FTL_TYPE_CHECK(jsValueValue(value), m_node->child1(), SpecCell | SpecOther, isNotOther(value));
2070
            m_out.jump(continuation);
2071
2072
            m_out.appendTo(continuation, lastNext);
2073
            return;
2074
        }
2075
2076
        default:
2077
            DFG_CRASH(m_graph, m_node, "Bad use kind");
2078
            return;
2079
        }
2044
    }
2080
    }
2045
    
2081
    
2046
    void compileCheckCell()
2082
    void compileCheckCell()
Lines 4022-4027 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
4022
            m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit);
4058
            m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit);
4023
            
4059
            
4024
            PutByIdVariant variant = data.variants[i];
4060
            PutByIdVariant variant = data.variants[i];
4061
4062
            checkInferredType(m_node->child2(), value, variant.requiredType());
4025
            
4063
            
4026
            LValue storage;
4064
            LValue storage;
4027
            if (variant.kind() == PutByIdVariant::Replace) {
4065
            if (variant.kind() == PutByIdVariant::Replace) {
Lines 5674-5679 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec3
5674
        m_out.appendTo(continuation, lastNext);
5712
        m_out.appendTo(continuation, lastNext);
5675
        return m_out.phi(m_out.int32, results);
5713
        return m_out.phi(m_out.int32, results);
5676
    }
5714
    }
5715
5716
    void checkInferredType(Edge edge, LValue value, const InferredType::Descriptor& type)
5717
    {
5718
        // This cannot use FTL_TYPE_CHECK or typeCheck() because it is called partially, as in a node like:
5719
        //
5720
        //     MultiPutByOffset(...)
5721
        //
5722
        // may be lowered to:
5723
        //
5724
        //     switch (object->structure) {
5725
        //     case 42:
5726
        //         checkInferredType(..., type1);
5727
        //         ...
5728
        //         break;
5729
        //     case 43:
5730
        //         checkInferredType(..., type2);
5731
        //         ...
5732
        //         break;
5733
        //     }
5734
        //
5735
        // where type1 and type2 are different. Using typeCheck() would mean that the edge would be
5736
        // filtered by type1 & type2, instead of type1 | type2.
5737
        
5738
        switch (type.kind()) {
5739
        case InferredType::Bottom:
5740
            speculate(BadType, jsValueValue(value), edge.node(), m_out.booleanTrue);
5741
            return;
5742
5743
        case InferredType::Boolean:
5744
            speculate(BadType, jsValueValue(value), edge.node(), isNotBoolean(value, provenType(edge)));
5745
            return;
5746
5747
        case InferredType::Other:
5748
            speculate(BadType, jsValueValue(value), edge.node(), isNotOther(value, provenType(edge)));
5749
            return;
5750
5751
        case InferredType::Int32:
5752
            speculate(BadType, jsValueValue(value), edge.node(), isNotInt32(value, provenType(edge)));
5753
            return;
5754
5755
        case InferredType::Number:
5756
            speculate(BadType, jsValueValue(value), edge.node(), isNotNumber(value, provenType(edge)));
5757
            return;
5758
5759
        case InferredType::String:
5760
            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
5761
            speculate(BadType, jsValueValue(value), edge.node(), isNotString(value, provenType(edge)));
5762
            return;
5763
5764
        case InferredType::ObjectWithStructure:
5765
            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
5766
            if (!abstractValue(edge).m_structure.isSubsetOf(StructureSet(type.structure()))) {
5767
                speculate(
5768
                    BadType, jsValueValue(value), edge.node(),
5769
                    m_out.notEqual(
5770
                        m_out.load32(value, m_heaps.JSCell_structureID),
5771
                        weakStructureID(type.structure())));
5772
            }
5773
            return;
5774
5775
        case InferredType::ObjectWithStructureOrOther: {
5776
            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectWithStructureOrOther cell case"));
5777
            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectWithStructureOrOther not cell case"));
5778
            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectWithStructureOrOther continuation"));
5779
5780
            m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
5781
5782
            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
5783
5784
            if (!abstractValue(edge).m_structure.isSubsetOf(StructureSet(type.structure()))) {
5785
                speculate(
5786
                    BadType, jsValueValue(value), edge.node(),
5787
                    m_out.notEqual(
5788
                        m_out.load32(value, m_heaps.JSCell_structureID),
5789
                        weakStructureID(type.structure())));
5790
            }
5791
5792
            m_out.jump(continuation);
5793
5794
            m_out.appendTo(notCellCase, continuation);
5795
5796
            speculate(
5797
                BadType, jsValueValue(value), edge.node(),
5798
                isNotOther(value, provenType(edge) & ~SpecCell));
5799
5800
            m_out.jump(continuation);
5801
5802
            m_out.appendTo(continuation, lastNext);
5803
            return;
5804
        }
5805
5806
        case InferredType::Object:
5807
            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
5808
            speculate(BadType, jsValueValue(value), edge.node(), isNotObject(value, provenType(edge)));
5809
            return;
5810
5811
        case InferredType::ObjectOrOther: {
5812
            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectOrOther cell case"));
5813
            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectOrOther not cell case"));
5814
            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectOrOther continuation"));
5815
5816
            m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
5817
5818
            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
5819
5820
            speculate(
5821
                BadType, jsValueValue(value), edge.node(),
5822
                isNotObject(value, provenType(edge) & SpecCell));
5823
5824
            m_out.jump(continuation);
5825
5826
            m_out.appendTo(notCellCase, continuation);
5827
5828
            speculate(
5829
                BadType, jsValueValue(value), edge.node(),
5830
                isNotOther(value, provenType(edge) & ~SpecCell));
5831
5832
            m_out.jump(continuation);
5833
5834
            m_out.appendTo(continuation, lastNext);
5835
            return;
5836
        }
5837
5838
        case InferredType::Top:
5839
            return;
5840
        }
5841
5842
        DFG_CRASH(m_graph, m_node, "Bad inferred type");
5843
    }
5677
    
5844
    
5678
    LValue loadProperty(LValue storage, unsigned identifierNumber, PropertyOffset offset)
5845
    LValue loadProperty(LValue storage, unsigned identifierNumber, PropertyOffset offset)
5679
    {
5846
    {
Lines 7514-7519 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec4
7514
        case CellUse:
7681
        case CellUse:
7515
            speculateCell(edge);
7682
            speculateCell(edge);
7516
            break;
7683
            break;
7684
        case CellOrOtherUse:
7685
            speculateCellOrOther(edge);
7686
            break;
7517
        case KnownCellUse:
7687
        case KnownCellUse:
7518
            ASSERT(!m_interpreter.needsTypeCheck(edge));
7688
            ASSERT(!m_interpreter.needsTypeCheck(edge));
7519
            break;
7689
            break;
Lines 7594-7599 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec5
7594
        lowCell(edge);
7764
        lowCell(edge);
7595
    }
7765
    }
7596
    
7766
    
7767
    void speculateCellOrOther(Edge edge)
7768
    {
7769
        LValue value = lowJSValue(edge, ManualOperandSpeculation);
7770
7771
        LBasicBlock isNotCell = FTL_NEW_BLOCK(m_out, ("Speculate CellOrOther not cell"));
7772
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Speculate CellOrOther continuation"));
7773
7774
        m_out.branch(isCell(value, provenType(edge)), unsure(continuation), unsure(isNotCell));
7775
7776
        LBasicBlock lastNext = m_out.appendTo(isNotCell, continuation);
7777
        FTL_TYPE_CHECK(jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
7778
        m_out.jump(continuation);
7779
7780
        m_out.appendTo(continuation, lastNext);
7781
    }
7782
    
7597
    void speculateMachineInt(Edge edge)
7783
    void speculateMachineInt(Edge edge)
7598
    {
7784
    {
7599
        if (!m_interpreter.needsTypeCheck(edge))
7785
        if (!m_interpreter.needsTypeCheck(edge))
Lines 8127-8132 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec6
8127
            }
8313
            }
8128
        }
8314
        }
8129
8315
8316
        if (failCondition == m_out.booleanFalse)
8317
            return;
8318
8130
        ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.finalizer->osrExit.size());
8319
        ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.finalizer->osrExit.size());
8131
        
8320
        
8132
        m_ftlState.jitCode->osrExit.append(OSRExit(
8321
        m_ftlState.jitCode->osrExit.append(OSRExit(
Lines 8135-8143 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec7
8135
            availabilityMap().m_locals.numberOfArguments(),
8324
            availabilityMap().m_locals.numberOfArguments(),
8136
            availabilityMap().m_locals.numberOfLocals()));
8325
            availabilityMap().m_locals.numberOfLocals()));
8137
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
8326
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
8138
        
8327
8139
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
8328
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
8140
8329
8330
        if (failCondition == m_out.booleanTrue) {
8331
            emitOSRExitCall(exit, lowValue);
8332
            return;
8333
        }
8334
8141
        LBasicBlock lastNext = nullptr;
8335
        LBasicBlock lastNext = nullptr;
8142
        LBasicBlock continuation = nullptr;
8336
        LBasicBlock continuation = nullptr;
8143
        
8337
        
- Source/JavaScriptCore/jit/AssemblyHelpers.cpp +72 lines
Lines 55-60 Vector<BytecodeAndMachineOffset>& Assemb Source/JavaScriptCore/jit/AssemblyHelpers.cpp_sec1
55
    return result.iterator->value;
55
    return result.iterator->value;
56
}
56
}
57
57
58
AssemblyHelpers::JumpList AssemblyHelpers::branchIfNotType(
59
    JSValueRegs regs, GPRReg tempGPR, const InferredType::Descriptor& descriptor, TagRegistersMode mode)
60
{
61
    AssemblyHelpers::JumpList result;
62
63
    switch (descriptor.kind()) {
64
    case InferredType::Bottom:
65
        result.append(jump());
66
        break;
67
68
    case InferredType::Boolean:
69
        result.append(branchIfNotBoolean(regs, tempGPR));
70
        break;
71
72
    case InferredType::Other:
73
        result.append(branchIfNotOther(regs, tempGPR));
74
        break;
75
76
    case InferredType::Int32:
77
        result.append(branchIfNotInt32(regs, mode));
78
        break;
79
80
    case InferredType::Number:
81
        result.append(branchIfNotNumber(regs, tempGPR, mode));
82
        break;
83
84
    case InferredType::String:
85
        result.append(branchIfNotCell(regs, mode));
86
        result.append(branchIfNotString(regs.payloadGPR()));
87
        break;
88
89
    case InferredType::ObjectWithStructure:
90
        result.append(branchIfNotCell(regs, mode));
91
        result.append(
92
            branchStructure(
93
                NotEqual,
94
                Address(regs.payloadGPR(), JSCell::structureIDOffset()),
95
                descriptor.structure()));
96
        break;
97
98
    case InferredType::ObjectWithStructureOrOther: {
99
        Jump ok = branchIfOther(regs, tempGPR);
100
        result.append(branchIfNotCell(regs, mode));
101
        result.append(
102
            branchStructure(
103
                NotEqual,
104
                Address(regs.payloadGPR(), JSCell::structureIDOffset()),
105
                descriptor.structure()));
106
        ok.link(this);
107
        break;
108
    }
109
110
    case InferredType::Object:
111
        result.append(branchIfNotCell(regs, mode));
112
        result.append(branchIfNotObject(regs.payloadGPR()));
113
        break;
114
115
    case InferredType::ObjectOrOther: {
116
        Jump ok = branchIfOther(regs, tempGPR);
117
        result.append(branchIfNotCell(regs, mode));
118
        result.append(branchIfNotObject(regs.payloadGPR()));
119
        ok.link(this);
120
        break;
121
    }
122
123
    case InferredType::Top:
124
        break;
125
    }
126
127
    return result;
128
}
129
58
void AssemblyHelpers::purifyNaN(FPRReg fpr)
130
void AssemblyHelpers::purifyNaN(FPRReg fpr)
59
{
131
{
60
    MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
132
    MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
- Source/JavaScriptCore/jit/AssemblyHelpers.h -18 / +44 lines
Lines 555-591 public: Source/JavaScriptCore/jit/AssemblyHelpers.h_sec1
555
#endif
555
#endif
556
    }
556
    }
557
557
558
    Jump branchIfNotCell(GPRReg reg)
558
    enum TagRegistersMode {
559
        DoNotHaveTagRegisters,
560
        HaveTagRegisters
561
    };
562
563
    Jump branchIfNotCell(GPRReg reg, TagRegistersMode mode = HaveTagRegisters)
559
    {
564
    {
560
#if USE(JSVALUE64)
565
#if USE(JSVALUE64)
561
        return branchTest64(MacroAssembler::NonZero, reg, GPRInfo::tagMaskRegister);
566
        if (mode == HaveTagRegisters)
567
            return branchTest64(NonZero, reg, GPRInfo::tagMaskRegister);
568
        return branchTest64(NonZero, reg, TrustedImm64(TagMask));
562
#else
569
#else
570
        UNUSED_PARAM(mode);
563
        return branch32(MacroAssembler::NotEqual, reg, TrustedImm32(JSValue::CellTag));
571
        return branch32(MacroAssembler::NotEqual, reg, TrustedImm32(JSValue::CellTag));
564
#endif
572
#endif
565
    }
573
    }
566
    Jump branchIfNotCell(JSValueRegs regs)
574
    Jump branchIfNotCell(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
567
    {
575
    {
568
#if USE(JSVALUE64)
576
#if USE(JSVALUE64)
569
        return branchIfNotCell(regs.gpr());
577
        return branchIfNotCell(regs.gpr(), mode);
570
#else
578
#else
571
        return branchIfNotCell(regs.tagGPR());
579
        return branchIfNotCell(regs.tagGPR(), mode);
572
#endif
580
#endif
573
    }
581
    }
574
    
582
    
575
    Jump branchIfCell(GPRReg reg)
583
    Jump branchIfCell(GPRReg reg, TagRegistersMode mode = HaveTagRegisters)
576
    {
584
    {
577
#if USE(JSVALUE64)
585
#if USE(JSVALUE64)
578
        return branchTest64(MacroAssembler::Zero, reg, GPRInfo::tagMaskRegister);
586
        if (mode == HaveTagRegisters)
587
            return branchTest64(Zero, reg, GPRInfo::tagMaskRegister);
588
        return branchTest64(Zero, reg, TrustedImm64(TagMask));
579
#else
589
#else
590
        UNUSED_PARAM(mode);
580
        return branch32(MacroAssembler::Equal, reg, TrustedImm32(JSValue::CellTag));
591
        return branch32(MacroAssembler::Equal, reg, TrustedImm32(JSValue::CellTag));
581
#endif
592
#endif
582
    }
593
    }
583
    Jump branchIfCell(JSValueRegs regs)
594
    Jump branchIfCell(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
584
    {
595
    {
585
#if USE(JSVALUE64)
596
#if USE(JSVALUE64)
586
        return branchIfCell(regs.gpr());
597
        return branchIfCell(regs.gpr(), mode);
587
#else
598
#else
588
        return branchIfCell(regs.tagGPR());
599
        return branchIfCell(regs.tagGPR(), mode);
589
#endif
600
#endif
590
    }
601
    }
591
    
602
    
Lines 613-655 public: Source/JavaScriptCore/jit/AssemblyHelpers.h_sec2
613
#endif
624
#endif
614
    }
625
    }
615
    
626
    
616
    Jump branchIfInt32(JSValueRegs regs)
627
    Jump branchIfInt32(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
617
    {
628
    {
618
#if USE(JSVALUE64)
629
#if USE(JSVALUE64)
619
        return branch64(AboveOrEqual, regs.gpr(), GPRInfo::tagTypeNumberRegister);
630
        if (mode == HaveTagRegisters)
631
            return branch64(AboveOrEqual, regs.gpr(), GPRInfo::tagTypeNumberRegister);
632
        return branch64(AboveOrEqual, regs.gpr(), TrustedImm64(TagTypeNumber));
620
#else
633
#else
634
        UNUSED_PARAM(mode);
621
        return branch32(Equal, regs.tagGPR(), TrustedImm32(JSValue::Int32Tag));
635
        return branch32(Equal, regs.tagGPR(), TrustedImm32(JSValue::Int32Tag));
622
#endif
636
#endif
623
    }
637
    }
624
    
638
    
625
    Jump branchIfNotInt32(JSValueRegs regs)
639
    Jump branchIfNotInt32(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
626
    {
640
    {
627
#if USE(JSVALUE64)
641
#if USE(JSVALUE64)
628
        return branch64(Below, regs.gpr(), GPRInfo::tagTypeNumberRegister);
642
        if (mode == HaveTagRegisters)
643
            return branch64(Below, regs.gpr(), GPRInfo::tagTypeNumberRegister);
644
        return branch64(Below, regs.gpr(), TrustedImm64(TagTypeNumber));
629
#else
645
#else
646
        UNUSED_PARAM(mode);
630
        return branch32(NotEqual, regs.tagGPR(), TrustedImm32(JSValue::Int32Tag));
647
        return branch32(NotEqual, regs.tagGPR(), TrustedImm32(JSValue::Int32Tag));
631
#endif
648
#endif
632
    }
649
    }
633
650
634
    // Note that the tempGPR is not used in 64-bit mode.
651
    // Note that the tempGPR is not used in 64-bit mode.
635
    Jump branchIfNumber(JSValueRegs regs, GPRReg tempGPR)
652
    Jump branchIfNumber(JSValueRegs regs, GPRReg tempGPR, TagRegistersMode mode = HaveTagRegisters)
636
    {
653
    {
637
#if USE(JSVALUE64)
654
#if USE(JSVALUE64)
638
        UNUSED_PARAM(tempGPR);
655
        UNUSED_PARAM(tempGPR);
639
        return branchTest64(NonZero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
656
        if (mode == HaveTagRegisters)
657
            return branchTest64(NonZero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
658
        return branchTest64(NonZero, regs.gpr(), TrustedImm64(TagTypeNumber));
640
#else
659
#else
660
        UNUSED_PARAM(mode);
641
        add32(TrustedImm32(1), regs.tagGPR(), tempGPR);
661
        add32(TrustedImm32(1), regs.tagGPR(), tempGPR);
642
        return branch32(Below, tempGPR, TrustedImm32(JSValue::LowestTag + 1));
662
        return branch32(Below, tempGPR, TrustedImm32(JSValue::LowestTag + 1));
643
#endif
663
#endif
644
    }
664
    }
645
    
665
    
646
    // Note that the tempGPR is not used in 64-bit mode.
666
    // Note that the tempGPR is not used in 64-bit mode.
647
    Jump branchIfNotNumber(JSValueRegs regs, GPRReg tempGPR)
667
    Jump branchIfNotNumber(JSValueRegs regs, GPRReg tempGPR, TagRegistersMode mode = HaveTagRegisters)
648
    {
668
    {
649
#if USE(JSVALUE64)
669
#if USE(JSVALUE64)
650
        UNUSED_PARAM(tempGPR);
670
        UNUSED_PARAM(tempGPR);
651
        return branchTest64(Zero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
671
        if (mode == HaveTagRegisters)
672
            return branchTest64(Zero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
673
        return branchTest64(Zero, regs.gpr(), TrustedImm64(TagTypeNumber));
652
#else
674
#else
675
        UNUSED_PARAM(mode);
653
        add32(TrustedImm32(1), regs.tagGPR(), tempGPR);
676
        add32(TrustedImm32(1), regs.tagGPR(), tempGPR);
654
        return branch32(AboveOrEqual, tempGPR, TrustedImm32(JSValue::LowestTag + 1));
677
        return branch32(AboveOrEqual, tempGPR, TrustedImm32(JSValue::LowestTag + 1));
655
#endif
678
#endif
Lines 719-724 public: Source/JavaScriptCore/jit/AssemblyHelpers.h_sec3
719
#endif
742
#endif
720
    }
743
    }
721
744
745
    JumpList branchIfNotType(
746
        JSValueRegs, GPRReg tempGPR, const InferredType::Descriptor&, TagRegistersMode);
747
722
    template<typename T>
748
    template<typename T>
723
    Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
749
    Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
724
    {
750
    {
- Source/JavaScriptCore/jit/Repatch.cpp -1 / +2 lines
Lines 378-384 static InlineCacheAction tryCachePutByID Source/JavaScriptCore/jit/Repatch.cpp_sec1
378
            ptrdiff_t offsetToPatchedStorage = offsetRelativeToPatchedStorage(slot.cachedOffset());
378
            ptrdiff_t offsetToPatchedStorage = offsetRelativeToPatchedStorage(slot.cachedOffset());
379
            if (stubInfo.cacheType == CacheType::Unset
379
            if (stubInfo.cacheType == CacheType::Unset
380
                && MacroAssembler::isPtrAlignedAddressOffset(offsetToPatchedStorage)
380
                && MacroAssembler::isPtrAlignedAddressOffset(offsetToPatchedStorage)
381
                && !structure->needImpurePropertyWatchpoint()) {
381
                && !structure->needImpurePropertyWatchpoint()
382
                && !structure->inferredTypeFor(ident.impl())) {
382
383
383
                repatchByIdSelfAccess(
384
                repatchByIdSelfAccess(
384
                    codeBlock, stubInfo, structure, slot.cachedOffset(),
385
                    codeBlock, stubInfo, structure, slot.cachedOffset(),
- Source/JavaScriptCore/llint/LLIntSlowPaths.cpp +8 lines
Lines 631-636 LLINT_SLOW_PATH_DECL(slow_path_put_by_id Source/JavaScriptCore/llint/LLIntSlowPaths.cpp_sec1
631
        pc[5].u.pointer = nullptr; // offset
631
        pc[5].u.pointer = nullptr; // offset
632
        pc[6].u.pointer = nullptr; // new structure
632
        pc[6].u.pointer = nullptr; // new structure
633
        pc[7].u.pointer = nullptr; // structure chain
633
        pc[7].u.pointer = nullptr; // structure chain
634
        pc[8].u.putByIdFlags =
635
            static_cast<PutByIdFlags>(pc[8].u.putByIdFlags & PutByIdPersistentFlagsMask);
634
        
636
        
635
        JSCell* baseCell = baseValue.asCell();
637
        JSCell* baseCell = baseValue.asCell();
636
        Structure* structure = baseCell->structure();
638
        Structure* structure = baseCell->structure();
Lines 658-669 LLINT_SLOW_PATH_DECL(slow_path_put_by_id Source/JavaScriptCore/llint/LLIntSlowPaths.cpp_sec2
658
                            pc[7].u.structureChain.set(
660
                            pc[7].u.structureChain.set(
659
                                vm, codeBlock->ownerExecutable(), chain);
661
                                vm, codeBlock->ownerExecutable(), chain);
660
                        }
662
                        }
663
                        pc[8].u.putByIdFlags = static_cast<PutByIdFlags>(
664
                            pc[8].u.putByIdFlags |
665
                            structure->inferredTypeDescriptorFor(ident.impl()).putByIdFlags());
661
                    }
666
                    }
662
                }
667
                }
663
            } else {
668
            } else {
664
                structure->didCachePropertyReplacement(vm, slot.cachedOffset());
669
                structure->didCachePropertyReplacement(vm, slot.cachedOffset());
665
                pc[4].u.structureID = structure->id();
670
                pc[4].u.structureID = structure->id();
666
                pc[5].u.operand = slot.cachedOffset();
671
                pc[5].u.operand = slot.cachedOffset();
672
                pc[8].u.putByIdFlags = static_cast<PutByIdFlags>(
673
                    pc[8].u.putByIdFlags |
674
                    structure->inferredTypeDescriptorFor(ident.impl()).putByIdFlags());
667
            }
675
            }
668
        }
676
        }
669
    }
677
    }
- Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm -3 / +77 lines
Lines 1391-1407 _llint_op_put_by_id: Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm_sec1
1391
    # At this point, we have:
1391
    # At this point, we have:
1392
    # t2 -> currentStructureID
1392
    # t2 -> currentStructureID
1393
    # t0 -> object base
1393
    # t0 -> object base
1394
    # We will lose currentStructureID in the shenanigans below.
1394
1395
1396
    loadi 12[PC], t1
1397
    loadConstantOrVariable(t1, t2, t3)
1398
    loadi 32[PC], t1
1399
1400
    # At this point, we have:
1401
    # t0 -> object base
1402
    # t1 -> put by id flags
1403
    # t2 -> value tag
1404
    # t3 -> value payload
1405
1406
    btinz t1, PutByIdPrimaryTypeMask, .opPutByIdTypeCheckObjectWithStructureOrOther
1407
1408
    # We have one of the non-structure type checks. Find out which one.
1409
    andi PutByIdSecondaryTypeMask, t1
1410
    bilt t1, PutByIdSecondaryTypeString, .opPutByIdTypeCheckLessThanString
1411
1412
    # We are one of the following: String, Object, ObjectOrOther, Top
1413
    bilt t1, PutByIdSecondaryTypeObjectOrOther, .opPutByIdTypeCheckLessThanObjectOrOther
1414
1415
    # We are either ObjectOrOther or Top.
1416
    bieq t1, PutByIdSecondaryTypeTop, .opPutByIdDoneCheckingTypes
1417
1418
    # Check if we are ObjectOrOther.
1419
    bieq t2, CellTag, .opPutByIdTypeCheckObject
1420
.opPutByIdTypeCheckOther:
1421
    bieq t2, NullTag, .opPutByIdDoneCheckingTypes
1422
    bieq t2, UndefinedTag, .opPutByIdDoneCheckingTypes
1423
    jmp .opPutByIdSlow
1424
1425
.opPutByIdTypeCheckLessThanObjectOrOther:
1426
    # We are either String or Object.
1427
    bineq t2, CellTag, .opPutByIdSlow
1428
    bieq t1, PutByIdSecondaryTypeObject, .opPutByIdTypeCheckObject
1429
    bbeq JSCell::m_type[t3], StringType, .opPutByIdDoneCheckingTypes
1430
    jmp .opPutByIdSlow
1431
.opPutByIdTypeCheckObject:
1432
    bbaeq JSCell::m_type[t3], ObjectType, .opPutByIdDoneCheckingTypes
1433
    jmp .opPutByIdSlow
1434
1435
.opPutByIdTypeCheckLessThanString:
1436
    # We are one of the following: Bottom, Boolean, Other, Int32, Number.
1437
    bilt t1, PutByIdSecondaryTypeInt32, .opPutByIdTypeCheckLessThanInt32
1438
1439
    # We are either Int32 or Number.
1440
    bieq t1, PutByIdSecondaryTypeNumber, .opPutByIdTypeCheckNumber
1441
1442
    bieq t2, Int32Tag, .opPutByIdDoneCheckingTypes
1443
    jmp .opPutByIdSlow
1444
1445
.opPutByIdTypeCheckNumber:
1446
    bib t2, LowestTag + 1, .opPutByIdDoneCheckingTypes
1447
    jmp .opPutByIdSlow
1448
1449
.opPutByIdTypeCheckLessThanInt32:
1450
    # We are one of the following: Bottom, Boolean, Other
1451
    bineq t1, PutByIdSecondaryTypeBoolean, .opPutByIdTypeCheckBottomOrOther
1452
    bieq t2, BooleanTag, .opPutByIdDoneCheckingTypes
1453
    jmp .opPutByIdSlow
1454
1455
.opPutByIdTypeCheckBottomOrOther:
1456
    bieq t1, PutByIdSecondaryTypeOther, .opPutByIdTypeCheckOther
1457
    jmp .opPutByIdSlow
1458
1459
.opPutByIdTypeCheckObjectWithStructureOrOther:
1460
    bieq t2, CellTag, .opPutByIdTypeCheckObjectWithStructure
1461
    btinz t1, PutByIdPrimaryTypeObjectWithStructureOrOther, .opPutByIdTypeCheckOther
1462
    jmp .opPutByIdSlow
1463
1464
.opPutByIdTypeCheckObjectWithStructure:
1465
    andi PutByIdSecondaryTypeMask, t1
1466
    bineq t1, JSCell::m_structureID[t3], .opPutByIdSlow
1467
1468
.opPutByIdDoneCheckingTypes:
1395
    loadi 24[PC], t1
1469
    loadi 24[PC], t1
1396
1470
1397
    btiz t1, .opPutByIdNotTransition
1471
    btiz t1, .opPutByIdNotTransition
1398
1472
1399
    # This is the transition case. t1 holds the new Structure*. t2 holds the old Structure*.
1473
    # This is the transition case. t1 holds the new Structure*. If we have a chain, we need to
1400
    # If we have a chain, we need to check it. t0 is the base. We may clobber t1 to use it as
1474
    # check it. t0 is the base. We may clobber t1 to use it as scratch.
1401
    # scratch.
1402
    loadp 28[PC], t3
1475
    loadp 28[PC], t3
1403
    btpz t3, .opPutByIdTransitionDirect
1476
    btpz t3, .opPutByIdTransitionDirect
1404
1477
1478
    loadi 16[PC], t2 # Need old structure again.
1405
    loadp StructureChain::m_vector[t3], t3
1479
    loadp StructureChain::m_vector[t3], t3
1406
    assert(macro (ok) btpnz t3, ok end)
1480
    assert(macro (ok) btpnz t3, ok end)
1407
1481
- Source/JavaScriptCore/llint/LowLevelInterpreter64.asm -4 / +78 lines
Lines 1266-1279 _llint_op_put_by_id: Source/JavaScriptCore/llint/LowLevelInterpreter64.asm_sec1
1266
    writeBarrierOnOperands(1, 3)
1266
    writeBarrierOnOperands(1, 3)
1267
    loadisFromInstruction(1, t3)
1267
    loadisFromInstruction(1, t3)
1268
    loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1268
    loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1269
    loadi JSCell::m_structureID[t0], t2
1269
    loadisFromInstruction(4, t2)
1270
    loadisFromInstruction(4, t1)
1270
    bineq t2, JSCell::m_structureID[t0], .opPutByIdSlow
1271
    bineq t2, t1, .opPutByIdSlow
1272
1271
1273
    # At this point, we have:
1272
    # At this point, we have:
1274
    # t1, t2 -> current structure ID
1273
    # t2 -> current structure ID
1275
    # t0 -> object base
1274
    # t0 -> object base
1276
1275
1276
    loadisFromInstruction(3, t1)
1277
    loadConstantOrVariable(t1, t3)
1278
1279
    loadpFromInstruction(8, t1)
1280
1281
    # At this point, we have:
1282
    # t0 -> object base
1283
    # t1 -> put by id flags
1284
    # t2 -> current structure ID
1285
    # t3 -> value to put
1286
1287
    btpnz t1, PutByIdPrimaryTypeMask, .opPutByIdTypeCheckObjectWithStructureOrOther
1288
1289
    # We have one of the non-structure type checks. Find out which one.
1290
    andp PutByIdSecondaryTypeMask, t1
1291
    bplt t1, PutByIdSecondaryTypeString, .opPutByIdTypeCheckLessThanString
1292
1293
    # We are one of the following: String, Object, ObjectOrOther, Top
1294
    bplt t1, PutByIdSecondaryTypeObjectOrOther, .opPutByIdTypeCheckLessThanObjectOrOther
1295
1296
    # We are either ObjectOrOther or Top.
1297
    bpeq t1, PutByIdSecondaryTypeTop, .opPutByIdDoneCheckingTypes
1298
1299
    # Check if we are ObjectOrOther.
1300
    btqz t3, tagMask, .opPutByIdTypeCheckObject
1301
.opPutByIdTypeCheckOther:
1302
    andq ~TagBitUndefined, t3
1303
    bqeq t3, ValueNull, .opPutByIdDoneCheckingTypes
1304
    jmp .opPutByIdSlow
1305
1306
.opPutByIdTypeCheckLessThanObjectOrOther:
1307
    # We are either String or Object.
1308
    btqnz t3, tagMask, .opPutByIdSlow
1309
    bpeq t1, PutByIdSecondaryTypeObject, .opPutByIdTypeCheckObject
1310
    bbeq JSCell::m_type[t3], StringType, .opPutByIdDoneCheckingTypes
1311
    jmp .opPutByIdSlow
1312
.opPutByIdTypeCheckObject:
1313
    bbaeq JSCell::m_type[t3], ObjectType, .opPutByIdDoneCheckingTypes
1314
    jmp .opPutByIdSlow
1315
1316
.opPutByIdTypeCheckLessThanString:
1317
    # We are one of the following: Bottom, Boolean, Other, Int32, Number
1318
    bplt t1, PutByIdSecondaryTypeInt32, .opPutByIdTypeCheckLessThanInt32
1319
1320
    # We are either Int32 or Number.
1321
    bpeq t1, PutByIdSecondaryTypeNumber, .opPutByIdTypeCheckNumber
1322
1323
    bqaeq t3, tagTypeNumber, .opPutByIdDoneCheckingTypes
1324
    jmp .opPutByIdSlow
1325
1326
.opPutByIdTypeCheckNumber:
1327
    btqnz t3, tagTypeNumber, .opPutByIdDoneCheckingTypes
1328
    jmp .opPutByIdSlow
1329
1330
.opPutByIdTypeCheckLessThanInt32:
1331
    # We are one of the following: Bottom, Boolean, Other.
1332
    bpneq t1, PutByIdSecondaryTypeBoolean, .opPutByIdTypeCheckBottomOrOther
1333
    xorq ValueFalse, t3
1334
    btqz t3, ~1, .opPutByIdDoneCheckingTypes
1335
    jmp .opPutByIdSlow
1336
1337
.opPutByIdTypeCheckBottomOrOther:
1338
    bpeq t1, PutByIdSecondaryTypeOther, .opPutByIdTypeCheckOther
1339
    jmp .opPutByIdSlow
1340
1341
.opPutByIdTypeCheckObjectWithStructureOrOther:
1342
    btqz t3, tagMask, .opPutByIdTypeCheckObjectWithStructure
1343
    btpnz t1, PutByIdPrimaryTypeObjectWithStructureOrOther, .opPutByIdTypeCheckOther
1344
    jmp .opPutByIdSlow
1345
1346
.opPutByIdTypeCheckObjectWithStructure:
1347
    urshiftp 3, t1
1348
    bineq t1, JSCell::m_structureID[t3], .opPutByIdSlow
1349
1350
.opPutByIdDoneCheckingTypes:
1277
    loadisFromInstruction(6, t1)
1351
    loadisFromInstruction(6, t1)
1278
    
1352
    
1279
    btiz t1, .opPutByIdNotTransition
1353
    btiz t1, .opPutByIdNotTransition
- Source/JavaScriptCore/llint/LowLevelInterpreter.asm +16 lines
Lines 204-209 else Source/JavaScriptCore/llint/LowLevelInterpreter.asm_sec1
204
    const LowestTag = DeletedValueTag
204
    const LowestTag = DeletedValueTag
205
end
205
end
206
206
207
# NOTE: The values below must be in sync with what is in PutByIdFlags.h.
208
const PutByIdPrimaryTypeMask = 0x6
209
const PutByIdPrimaryTypeSecondary = 0x0
210
const PutByIdPrimaryTypeObjectWithStructure = 0x2
211
const PutByIdPrimaryTypeObjectWithStructureOrOther = 0x4
212
const PutByIdSecondaryTypeMask = -0x8
213
const PutByIdSecondaryTypeBottom = 0x0
214
const PutByIdSecondaryTypeBoolean = 0x8
215
const PutByIdSecondaryTypeOther = 0x10
216
const PutByIdSecondaryTypeInt32 = 0x18
217
const PutByIdSecondaryTypeNumber = 0x20
218
const PutByIdSecondaryTypeString = 0x28
219
const PutByIdSecondaryTypeObject = 0x30
220
const PutByIdSecondaryTypeObjectOrOther = 0x38
221
const PutByIdSecondaryTypeTop = 0x40
222
207
const CallOpCodeSize = 9
223
const CallOpCodeSize = 9
208
224
209
if X86_64 or ARM64 or C_LOOP
225
if X86_64 or ARM64 or C_LOOP
- Source/JavaScriptCore/runtime/Executable.h -1 lines
Lines 31-37 Source/JavaScriptCore/runtime/Executable.h_sec1
31
#include "CodeBlockHash.h"
31
#include "CodeBlockHash.h"
32
#include "CodeSpecializationKind.h"
32
#include "CodeSpecializationKind.h"
33
#include "CompilationResult.h"
33
#include "CompilationResult.h"
34
#include "DFGPlan.h"
35
#include "ExecutableInfo.h"
34
#include "ExecutableInfo.h"
36
#include "HandlerInfo.h"
35
#include "HandlerInfo.h"
37
#include "InferredValue.h"
36
#include "InferredValue.h"
- Source/JavaScriptCore/runtime/InferredType.cpp +565 lines
Line 0 Source/JavaScriptCore/runtime/InferredType.cpp_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#include "config.h"
27
#include "InferredType.h"
28
29
#include "JSCInlines.h"
30
31
namespace JSC {
32
33
namespace {
34
35
class InferredTypeFireDetail : public FireDetail {
36
public:
37
    InferredTypeFireDetail(
38
        InferredType* inferredType, UniquedStringImpl* uid,
39
        const InferredType::Descriptor& oldDescriptor, const InferredType::Descriptor& newDescriptor,
40
        JSValue offendingValue)
41
        : m_inferredType(inferredType)
42
        , m_uid(uid)
43
        , m_oldDescriptor(oldDescriptor)
44
        , m_newDescriptor(newDescriptor)
45
        , m_offendingValue(offendingValue)
46
    {
47
    }
48
49
protected:
50
    void dump(PrintStream& out) const override
51
    {
52
        out.print(
53
            "Inferred type changed on ", RawPointer(m_inferredType), " for property ", m_uid, ": "
54
            "old type was ", m_oldDescriptor, " while desired type is ", m_newDescriptor);
55
        if (m_offendingValue)
56
            out.print(" due to ", m_offendingValue);
57
    }
58
59
private:
60
    InferredType* m_inferredType;
61
    RefPtr<UniquedStringImpl> m_uid;
62
    InferredType::Descriptor m_oldDescriptor;
63
    InferredType::Descriptor m_newDescriptor;
64
    JSValue m_offendingValue;
65
};
66
67
} // anonymous namespace
68
69
const ClassInfo InferredType::s_info = { "InferredType", 0, 0, CREATE_METHOD_TABLE(InferredType) };
70
71
InferredType* InferredType::create(VM& vm)
72
{
73
    InferredType* result = new (NotNull, allocateCell<InferredType>(vm.heap)) InferredType(vm);
74
    result->finishCreation(vm);
75
    return result;
76
}
77
78
void InferredType::destroy(JSCell* cell)
79
{
80
    InferredType* inferredType = static_cast<InferredType*>(cell);
81
    inferredType->InferredType::~InferredType();
82
}
83
84
Structure* InferredType::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
85
{
86
    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
87
}
88
89
void InferredType::visitChildren(JSCell* cell, SlotVisitor& visitor)
90
{
91
    InferredType* inferredType = jsCast<InferredType*>(cell);
92
93
    if (inferredType->m_structure)
94
        visitor.addUnconditionalFinalizer(&inferredType->m_structure->m_finalizer);
95
}
96
97
InferredType::Kind InferredType::kindForFlags(PutByIdFlags flags)
98
{
99
    switch (flags & PutByIdPrimaryTypeMask) {
100
    case PutByIdPrimaryTypeSecondary:
101
        switch (flags & PutByIdSecondaryTypeMask) {
102
        case PutByIdSecondaryTypeBottom:
103
            return Bottom;
104
        case PutByIdSecondaryTypeBoolean:
105
            return Boolean;
106
        case PutByIdSecondaryTypeOther:
107
            return Other;
108
        case PutByIdSecondaryTypeInt32:
109
            return Int32;
110
        case PutByIdSecondaryTypeNumber:
111
            return Number;
112
        case PutByIdSecondaryTypeString:
113
            return String;
114
        case PutByIdSecondaryTypeObject:
115
            return Object;
116
        case PutByIdSecondaryTypeObjectOrOther:
117
            return ObjectOrOther;
118
        case PutByIdSecondaryTypeTop:
119
            return Top;
120
        default:
121
            RELEASE_ASSERT_NOT_REACHED();
122
            return Bottom;
123
        }
124
    case PutByIdPrimaryTypeObjectWithStructure:
125
        return ObjectWithStructure;
126
    case PutByIdPrimaryTypeObjectWithStructureOrOther:
127
        return ObjectWithStructureOrOther;
128
    default:
129
        RELEASE_ASSERT_NOT_REACHED();
130
        return Bottom;
131
    }
132
}
133
134
InferredType::Descriptor InferredType::Descriptor::forValue(JSValue value)
135
{
136
    if (value.isBoolean())
137
        return Boolean;
138
    if (value.isUndefinedOrNull())
139
        return Other;
140
    if (value.isInt32())
141
        return Int32;
142
    if (value.isNumber())
143
        return Number;
144
    if (value.isCell()) {
145
        JSCell* cell = value.asCell();
146
        if (cell->isString())
147
            return String;
148
        if (cell->isObject()) {
149
            if (cell->structure()->transitionWatchpointSetIsStillValid())
150
                return Descriptor(ObjectWithStructure, cell->structure());
151
            return Object;
152
        }
153
    }
154
    return Top;
155
}
156
157
InferredType::Descriptor InferredType::Descriptor::forFlags(VM& vm, PutByIdFlags flags)
158
{
159
    Kind kind = kindForFlags(flags);
160
    Structure* structure;
161
    if (hasStructure(kind))
162
        structure = vm.heap.structureIDTable().get(decodeStructureID(flags));
163
    else
164
        structure = nullptr;
165
    return Descriptor(kind, structure);
166
}
167
168
PutByIdFlags InferredType::Descriptor::putByIdFlags() const
169
{
170
    switch (m_kind) {
171
    case Bottom:
172
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeBottom);
173
    case Boolean:
174
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeBoolean);
175
    case Other:
176
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeOther);
177
    case Int32:
178
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeInt32);
179
    case Number:
180
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeNumber);
181
    case String:
182
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeString);
183
    case Object:
184
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeObject);
185
    case ObjectOrOther:
186
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeObjectOrOther);
187
    case Top:
188
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeTop);
189
    case ObjectWithStructure:
190
        return static_cast<PutByIdFlags>(
191
            PutByIdPrimaryTypeObjectWithStructure | encodeStructureID(m_structure->id()));
192
    case ObjectWithStructureOrOther:
193
        return static_cast<PutByIdFlags>(
194
            PutByIdPrimaryTypeObjectWithStructureOrOther | encodeStructureID(m_structure->id()));
195
    }
196
    RELEASE_ASSERT_NOT_REACHED();
197
    return PutByIdNone;
198
}
199
200
void InferredType::Descriptor::merge(const Descriptor& other)
201
{
202
    // Filter out common things to simplify the switch statement below.
203
    if (*this == other)
204
        return;
205
    if (other.m_kind == Bottom)
206
        return;
207
208
    switch (m_kind) {
209
    case Bottom:
210
        *this = other;
211
        return;
212
    case Boolean:
213
    case String:
214
        *this = Top;
215
        return;
216
    case Other:
217
        switch (other.m_kind) {
218
        case ObjectWithStructure:
219
        case ObjectWithStructureOrOther:
220
            *this = Descriptor(ObjectWithStructureOrOther, other.structure());
221
            return;
222
        case Object:
223
        case ObjectOrOther:
224
            *this = ObjectOrOther;
225
            return;
226
        default:
227
            *this = Top;
228
            return;
229
        }
230
    case Int32:
231
        switch (other.m_kind) {
232
        case Number:
233
            *this = Number;
234
            return;
235
        default:
236
            *this = Top;
237
            return;
238
        }
239
    case Number:
240
        switch (other.m_kind) {
241
        case Int32:
242
            return;
243
        default:
244
            *this = Top;
245
            return;
246
        }
247
    case ObjectWithStructure:
248
        switch (other.m_kind) {
249
        case ObjectWithStructure: // If we see this here, then we know that the structures didn't match.
250
        case Object:
251
            *this = Object;
252
            return;
253
        case ObjectWithStructureOrOther:
254
            if (m_structure == other.m_structure) {
255
                *this = other;
256
                return;
257
            }
258
            *this = ObjectOrOther;
259
            return;
260
        case ObjectOrOther:
261
            *this = ObjectOrOther;
262
            return;
263
        case Other:
264
            m_kind = ObjectWithStructureOrOther;
265
            return;
266
        default:
267
            *this = Top;
268
            return;
269
        }
270
    case ObjectWithStructureOrOther:
271
        switch (other.m_kind) {
272
        case ObjectWithStructure:
273
            if (m_structure == other.m_structure)
274
                return;
275
            *this = ObjectOrOther;
276
            return;
277
        case Object:
278
        case ObjectWithStructureOrOther: // If we see this here, then we know that the structures didn't match.
279
        case ObjectOrOther:
280
            *this = ObjectOrOther;
281
            return;
282
        case Other:
283
            return;
284
        default:
285
            *this = Top;
286
            return;
287
        }
288
    case Object:
289
        switch (other.m_kind) {
290
        case ObjectWithStructure:
291
            return;
292
        case ObjectWithStructureOrOther:
293
        case ObjectOrOther:
294
        case Other:
295
            *this = ObjectOrOther;
296
            return;
297
        default:
298
            *this = Top;
299
            return;
300
        }
301
    case ObjectOrOther:
302
        switch (other.m_kind) {
303
        case ObjectWithStructure:
304
        case ObjectWithStructureOrOther:
305
        case Object:
306
        case Other:
307
            return;
308
        default:
309
            *this = Top;
310
            return;
311
        }
312
    case Top:
313
        return;
314
    }
315
316
    RELEASE_ASSERT_NOT_REACHED();
317
}
318
319
void InferredType::Descriptor::removeStructure()
320
{
321
    switch (m_kind) {
322
    case ObjectWithStructure:
323
        *this = Object;
324
        return;
325
    case ObjectWithStructureOrOther:
326
        *this = ObjectOrOther;
327
        return;
328
    default:
329
        return;
330
    }
331
}
332
333
bool InferredType::Descriptor::subsumes(const Descriptor& other) const
334
{
335
    Descriptor merged = *this;
336
    merged.merge(other);
337
    return *this == merged;
338
}
339
340
void InferredType::Descriptor::dumpInContext(PrintStream& out, DumpContext* context) const
341
{
342
    out.print(m_kind);
343
    if (m_structure)
344
        out.print(":", inContext(*m_structure, context));
345
}
346
347
void InferredType::Descriptor::dump(PrintStream& out) const
348
{
349
    dumpInContext(out, nullptr);
350
}
351
352
InferredType::InferredType(VM& vm)
353
    : Base(vm, vm.inferredTypeStructure.get())
354
    , m_watchpointSet(ClearWatchpoint)
355
{
356
}
357
358
InferredType::~InferredType()
359
{
360
}
361
362
bool InferredType::canWatch(const ConcurrentJITLocker& locker, const Descriptor& expected)
363
{
364
    if (expected.kind() == Top)
365
        return false;
366
    
367
    return descriptor(locker) == expected;
368
}
369
370
bool InferredType::canWatch(const Descriptor& expected)
371
{
372
    ConcurrentJITLocker locker(m_lock);
373
    return canWatch(locker, expected);
374
}
375
376
void InferredType::addWatchpoint(const ConcurrentJITLocker& locker, Watchpoint* watchpoint)
377
{
378
    RELEASE_ASSERT(descriptor(locker).kind() != Top);
379
380
    m_watchpointSet.add(watchpoint);
381
}
382
383
void InferredType::addWatchpoint(Watchpoint* watchpoint)
384
{
385
    ConcurrentJITLocker locker(m_lock);
386
    addWatchpoint(locker, watchpoint);
387
}
388
389
void InferredType::dump(PrintStream& out) const
390
{
391
    out.print(RawPointer(this), ":", descriptor());
392
}
393
394
bool InferredType::willStoreValueSlow(VM& vm, PropertyName propertyName, JSValue value)
395
{
396
    ConcurrentJITLocker locker(m_lock);
397
    Descriptor myType = descriptor(locker);
398
    Descriptor otherType = Descriptor::forValue(value);
399
400
    myType.merge(otherType);
401
402
    ASSERT(descriptor(locker) != myType); // The type must have changed if we're on the slow path.
403
404
    set(locker, vm, propertyName, value, myType);
405
406
    return kind(locker) != Top;
407
}
408
409
void InferredType::makeTopSlow(VM& vm, PropertyName propertyName)
410
{
411
    ConcurrentJITLocker locker(m_lock);
412
    set(locker, vm, propertyName, JSValue(), Top);
413
}
414
415
void InferredType::set(
416
    const ConcurrentJITLocker& locker, VM& vm, PropertyName propertyName, JSValue offendingValue,
417
    Descriptor newDescriptor)
418
{
419
    // We will trigger write barriers while holding our lock. Currently, write barriers don't GC, but that
420
    // could change. If it does, we don't want to deadlock. Note that we could have used
421
    // GCSafeConcurrentJITLocker in the caller, but the caller is on a fast path so maybe that wouldn't be
422
    // a good idea.
423
    DeferGCForAWhile deferGC(vm.heap);
424
    
425
    // Be defensive: if we're not really changing the type, then we don't have to do anything.
426
    if (descriptor(locker) == newDescriptor)
427
        return;
428
429
    // The new descriptor must be more general than the previous one.
430
    ASSERT(newDescriptor.subsumes(descriptor(locker)));
431
432
    // If the new descriptors have different structures, then it can only be because one is null.
433
    if (descriptor(locker).structure() != newDescriptor.structure())
434
        ASSERT(!descriptor(locker).structure() || !newDescriptor.structure());
435
436
    // We are changing the type, so make sure that if anyone was watching, they find out about it now. If
437
    // anyone is watching, we make sure to go to Top so that we don't do this sort of thing again.
438
    if (m_watchpointSet.state() != ClearWatchpoint) {
439
        // We cannot have been invalidated, since if we were, then we'd already be at Top.
440
        ASSERT(m_watchpointSet.state() != IsInvalidated);
441
442
        InferredTypeFireDetail detail(
443
            this, propertyName.uid(), descriptor(locker), newDescriptor, offendingValue);
444
        
445
        // We're about to do expensive things because some compiler thread decided to watch this type and
446
        // then the type changed. Assume that this property is crazy, and don't ever do any more things for
447
        // it.
448
        newDescriptor = Top;
449
450
        m_watchpointSet.fireAll(detail);
451
    }
452
453
    // Remove the old InferredStructure object if we no longer need it.
454
    if (!newDescriptor.structure())
455
        m_structure = nullptr;
456
457
    // Add a new InferredStructure object if we need one now.
458
    if (newDescriptor.structure()) {
459
        if (m_structure) {
460
            // We should agree on the structures if we get here.
461
            ASSERT(newDescriptor.structure() == m_structure->structure());
462
        } else {
463
            m_structure = std::make_unique<InferredStructure>(vm, this, newDescriptor.structure());
464
            newDescriptor.structure()->addTransitionWatchpoint(&m_structure->m_watchpoint);
465
        }
466
    }
467
468
    // Finally, set the descriptor kind.
469
    m_kind = newDescriptor.kind();
470
471
    // Assert that we did things.
472
    ASSERT(descriptor(locker) == newDescriptor);
473
}
474
475
void InferredType::removeStructure()
476
{
477
    // FIXME: Find an elegant and cheap way to thread information about why we got here into the fire
478
    // detail in set().
479
    
480
    VM& vm = *Heap::heap(this)->vm();
481
482
    ConcurrentJITLocker locker(m_lock);
483
    
484
    Descriptor newDescriptor = descriptor(locker);
485
    newDescriptor.removeStructure();
486
    
487
    set(locker, vm, PropertyName(nullptr), JSValue(), newDescriptor);
488
}
489
490
void InferredType::InferredStructureWatchpoint::fireInternal(const FireDetail&)
491
{
492
    InferredStructure* inferredStructure =
493
        bitwise_cast<InferredStructure*>(
494
            bitwise_cast<char*>(this) - OBJECT_OFFSETOF(InferredStructure, m_watchpoint));
495
496
    inferredStructure->m_parent->removeStructure();
497
}
498
499
void InferredType::InferredStructureFinalizer::finalizeUnconditionally()
500
{
501
    InferredStructure* inferredStructure =
502
        bitwise_cast<InferredStructure*>(
503
            bitwise_cast<char*>(this) - OBJECT_OFFSETOF(InferredStructure, m_finalizer));
504
505
    ASSERT(Heap::isMarked(inferredStructure->m_parent));
506
    
507
    if (!Heap::isMarked(inferredStructure->m_structure.get()))
508
        inferredStructure->m_parent->removeStructure();
509
}
510
511
InferredType::InferredStructure::InferredStructure(VM& vm, InferredType* parent, Structure* structure)
512
    : m_parent(parent)
513
    , m_structure(vm, parent, structure)
514
{
515
}
516
517
} // namespace JSC
518
519
namespace WTF {
520
521
using namespace JSC;
522
523
void printInternal(PrintStream& out, InferredType::Kind kind)
524
{
525
    switch (kind) {
526
    case InferredType::Bottom:
527
        out.print("Bottom");
528
        return;
529
    case InferredType::Boolean:
530
        out.print("Boolean");
531
        return;
532
    case InferredType::Other:
533
        out.print("Other");
534
        return;
535
    case InferredType::Int32:
536
        out.print("Int32");
537
        return;
538
    case InferredType::Number:
539
        out.print("Number");
540
        return;
541
    case InferredType::String:
542
        out.print("String");
543
        return;
544
    case InferredType::ObjectWithStructure:
545
        out.print("ObjectWithStructure");
546
        return;
547
    case InferredType::ObjectWithStructureOrOther:
548
        out.print("ObjectWithStructureOrOther");
549
        return;
550
    case InferredType::Object:
551
        out.print("Object");
552
        return;
553
    case InferredType::ObjectOrOther:
554
        out.print("ObjectOrOther");
555
        return;
556
    case InferredType::Top:
557
        out.print("Top");
558
        return;
559
    }
560
561
    RELEASE_ASSERT_NOT_REACHED();
562
}
563
564
} // namespace WTF
565
- Source/JavaScriptCore/runtime/InferredType.h +286 lines
Line 0 Source/JavaScriptCore/runtime/InferredType.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef InferredType_h
27
#define InferredType_h
28
29
#include "ConcurrentJITLock.h"
30
#include "JSCell.h"
31
#include "PropertyName.h"
32
#include "PutByIdFlags.h"
33
#include "Watchpoint.h"
34
35
namespace JSC {
36
37
// This is an object used for the inference of the types of object properties.
38
39
class InferredType final : public JSCell {
40
public:
41
    typedef JSCell Base;
42
43
    static InferredType* create(VM&);
44
45
    static const bool needsDestruction = true;
46
    static void destroy(JSCell*);
47
48
    static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;
49
    
50
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
51
52
    static void visitChildren(JSCell*, SlotVisitor&);
53
54
    DECLARE_INFO;
55
56
    enum Kind : uint8_t {
57
        Bottom,
58
        Boolean,
59
        Other,
60
        Int32,
61
        Number,
62
        String,
63
        ObjectWithStructure,
64
        ObjectWithStructureOrOther,
65
        Object,
66
        ObjectOrOther,
67
        Top
68
    };
69
70
    static Kind kindForFlags(PutByIdFlags);
71
    
72
    static bool hasStructure(Kind kind)
73
    {
74
        switch (kind) {
75
        case ObjectWithStructure:
76
        case ObjectWithStructureOrOther:
77
            return true;
78
        default:
79
            return false;
80
        }
81
    }
82
83
    class Descriptor {
84
    public:
85
        Descriptor()
86
            : m_kind(Bottom)
87
            , m_structure(nullptr)
88
        {
89
        }
90
91
        Descriptor(Kind kind, Structure* structure = nullptr)
92
            : m_kind(kind)
93
            , m_structure(structure)
94
        {
95
            if (hasStructure(kind))
96
                ASSERT(structure);
97
        }
98
99
        static Descriptor forValue(JSValue);
100
101
        static Descriptor forFlags(VM&, PutByIdFlags);
102
103
        explicit operator bool() const
104
        {
105
            return m_kind != Bottom || m_structure;
106
        }
107
108
        Kind kind() const { return m_kind; }
109
        Structure* structure() const { return m_structure; }
110
111
        PutByIdFlags putByIdFlags() const;
112
113
        ALWAYS_INLINE bool includesValue(JSValue value)
114
        {
115
            switch (m_kind) {
116
            case Bottom:
117
                return false;
118
            case Boolean:
119
                return value.isBoolean();
120
            case Other:
121
                return value.isUndefinedOrNull();
122
            case Int32:
123
                return value.isInt32();
124
            case Number:
125
                return value.isNumber();
126
            case String:
127
                return value.isString();
128
            case ObjectWithStructure:
129
                return value.isCell() && value.asCell()->structure() == m_structure;
130
            case ObjectWithStructureOrOther:
131
                return value.isUndefinedOrNull()
132
                    || (value.isCell() && value.asCell()->structure() == m_structure);
133
            case Object:
134
                return value.isObject();
135
            case ObjectOrOther:
136
                return value.isUndefinedOrNull() || value.isObject();
137
            case Top:
138
                return true;
139
            }
140
141
            RELEASE_ASSERT_NOT_REACHED();
142
        }
143
144
        bool operator==(const Descriptor& other) const
145
        {
146
            return m_kind == other.m_kind
147
                && m_structure == other.m_structure;
148
        }
149
150
        bool operator!=(const Descriptor& other) const
151
        {
152
            return !(*this == other);
153
        }
154
155
        unsigned hash() const
156
        {
157
            return WTF::PtrHash<Structure*>::hash(m_structure) ^ static_cast<unsigned>(m_kind);
158
        }
159
    
160
        void merge(const Descriptor&);
161
        void removeStructure();
162
163
        // Returns true if this descriptor is more general than the other one.
164
        bool subsumes(const Descriptor&) const;
165
166
        void dumpInContext(PrintStream&, DumpContext*) const;
167
        void dump(PrintStream&) const;
168
169
    private:
170
        Kind m_kind;
171
        Structure* m_structure;
172
    };
173
174
    ConcurrentJITLock& lock() const { return m_lock; }
175
176
    Descriptor descriptorMainThread() const
177
    {
178
        return Descriptor(m_kind, m_structure ? m_structure->structure() : nullptr);
179
    }
180
    
181
    Descriptor descriptor(const ConcurrentJITLocker&) const
182
    {
183
        return descriptorMainThread();
184
    }
185
    Descriptor descriptor() const
186
    {
187
        ConcurrentJITLocker locker(m_lock);
188
        return descriptor(locker);
189
    }
190
    
191
    Kind kind(const ConcurrentJITLocker& locker) const { return descriptor(locker).kind(); }
192
193
    bool isTop() const { return m_kind == Top; }
194
    bool isRelevant() const { return m_kind != Top; }
195
196
    // Returns true if the InferredType is still relevant after the store. It's not relevant if it's Top.
197
    ALWAYS_INLINE bool willStoreValue(VM& vm, PropertyName propertyName, JSValue value)
198
    {
199
        Descriptor currentDescriptor = descriptorMainThread();
200
        if (currentDescriptor.includesValue(value))
201
            return currentDescriptor.kind() != Top;
202
        return willStoreValueSlow(vm, propertyName, value);
203
    }
204
205
    // Immediately makes this type irrelevant.
206
    void makeTop(VM& vm, PropertyName propertyName)
207
    {
208
        if (isTop())
209
            return;
210
        makeTopSlow(vm, propertyName);
211
    }
212
213
    // Returns true if it currently makes sense to watch this InferredType for this descriptor. Note that
214
    // this will always return false for Top.
215
    bool canWatch(const ConcurrentJITLocker& locker, const Descriptor&);
216
    bool canWatch(const Descriptor&);
217
    
218
    void addWatchpoint(const ConcurrentJITLocker& locker, Watchpoint*);
219
    void addWatchpoint(Watchpoint*);
220
221
    void dump(PrintStream&) const;
222
223
private:
224
    InferredType(VM&);
225
    ~InferredType();
226
227
    bool willStoreValueSlow(VM&, PropertyName, JSValue);
228
    void makeTopSlow(VM&, PropertyName);
229
    void set(const ConcurrentJITLocker&, VM&, PropertyName, JSValue, Descriptor);
230
    void removeStructure();
231
232
    mutable ConcurrentJITLock m_lock;
233
    
234
    Kind m_kind { Bottom };
235
236
    class InferredStructureWatchpoint : public Watchpoint {
237
    public:
238
        InferredStructureWatchpoint() { }
239
    protected:
240
        void fireInternal(const FireDetail&) override;
241
    };
242
243
    class InferredStructureFinalizer : public UnconditionalFinalizer {
244
    public:
245
        InferredStructureFinalizer() { }
246
    protected:
247
        void finalizeUnconditionally() override;
248
    };
249
250
    class InferredStructure {
251
        WTF_MAKE_FAST_ALLOCATED;
252
    public:
253
        InferredStructure(VM&, InferredType* parent, Structure*);
254
255
        Structure* structure() const { return m_structure.get(); };
256
257
    private:
258
        friend class InferredType;
259
        friend class InferredStructureWatchpoint;
260
        friend class InferredStructureFinalizer;
261
        
262
        InferredType* m_parent;
263
        WriteBarrier<Structure> m_structure;
264
265
        InferredStructureWatchpoint m_watchpoint;
266
        InferredStructureFinalizer m_finalizer;
267
    };
268
269
    std::unique_ptr<InferredStructure> m_structure;
270
271
    // NOTE: If this is being watched, we transform to Top because that implies that it wouldn't be
272
    // profitable to watch it again. Also, this set is initialized clear, and is never exposed to the DFG
273
    // thread. The DFG will use the InferredType as the thing that it watches.
274
    InlineWatchpointSet m_watchpointSet;
275
};
276
277
} // namespace JSC
278
279
namespace WTF {
280
281
void printInternal(PrintStream&, JSC::InferredType::Kind);
282
283
} // namespace WTF
284
285
#endif // InferredType_h
286
- Source/JavaScriptCore/runtime/InferredTypeTable.cpp +166 lines
Line 0 Source/JavaScriptCore/runtime/InferredTypeTable.cpp_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#include "config.h"
27
#include "InferredTypeTable.h"
28
29
#include "JSCInlines.h"
30
31
namespace JSC {
32
33
const ClassInfo InferredTypeTable::s_info = { "InferredTypeTable", 0, 0, CREATE_METHOD_TABLE(InferredTypeTable) };
34
35
InferredTypeTable* InferredTypeTable::create(VM& vm)
36
{
37
    InferredTypeTable* result = new (NotNull, allocateCell<InferredTypeTable>(vm.heap)) InferredTypeTable(vm);
38
    result->finishCreation(vm);
39
    return result;
40
}
41
42
void InferredTypeTable::destroy(JSCell* cell)
43
{
44
    InferredTypeTable* inferredTypeTable = static_cast<InferredTypeTable*>(cell);
45
    inferredTypeTable->InferredTypeTable::~InferredTypeTable();
46
}
47
48
Structure* InferredTypeTable::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
49
{
50
    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
51
}
52
53
void InferredTypeTable::visitChildren(JSCell* cell, SlotVisitor& visitor)
54
{
55
    InferredTypeTable* inferredTypeTable = jsCast<InferredTypeTable*>(cell);
56
57
    ConcurrentJITLocker locker(inferredTypeTable->m_lock);
58
    
59
    for (auto& entry : inferredTypeTable->m_table) {
60
        if (!entry.value)
61
            continue;
62
        if (entry.value->isRelevant())
63
            visitor.append(&entry.value);
64
        else
65
            entry.value.clear();
66
    }
67
}
68
69
InferredType* InferredTypeTable::get(const ConcurrentJITLocker&, UniquedStringImpl* uid)
70
{
71
    auto iter = m_table.find(uid);
72
    if (iter == m_table.end() || !iter->value)
73
        return nullptr;
74
75
    // Take this opportunity to prune invalidated types.
76
    if (!iter->value->isRelevant()) {
77
        iter->value.clear();
78
        return nullptr;
79
    }
80
81
    return iter->value.get();
82
}
83
84
InferredType* InferredTypeTable::get(UniquedStringImpl* uid)
85
{
86
    ConcurrentJITLocker locker(m_lock);
87
    return get(locker, uid);
88
}
89
90
InferredType* InferredTypeTable::get(PropertyName propertyName)
91
{
92
    return get(propertyName.uid());
93
}
94
95
bool InferredTypeTable::willStoreValue(
96
    VM& vm, PropertyName propertyName, JSValue value, StoredPropertyAge age)
97
{
98
    // The algorithm here relies on the fact that only one thread modifies the hash map.
99
    
100
    if (age == OldProperty) {
101
        TableType::iterator iter = m_table.find(propertyName.uid());
102
        if (iter == m_table.end() || !iter->value)
103
            return false; // Absence on replace => top.
104
        
105
        if (iter->value->willStoreValue(vm, propertyName, value))
106
            return true;
107
        
108
        iter->value.clear();
109
        return false;
110
    }
111
112
    TableType::AddResult result;
113
    {
114
        ConcurrentJITLocker locker(m_lock);
115
        result = m_table.add(propertyName.uid(), WriteBarrier<InferredType>());
116
    }
117
    if (result.isNewEntry) {
118
        InferredType* inferredType = InferredType::create(vm);
119
        WTF::storeStoreFence();
120
        result.iterator->value.set(vm, this, inferredType);
121
    } else if (!result.iterator->value)
122
        return false;
123
    
124
    if (result.iterator->value->willStoreValue(vm, propertyName, value))
125
        return true;
126
    
127
    result.iterator->value.clear();
128
    return false;
129
}
130
131
void InferredTypeTable::makeTop(VM& vm, PropertyName propertyName, StoredPropertyAge age)
132
{
133
    // The algorithm here relies on the fact that only one thread modifies the hash map.
134
    if (age == OldProperty) {
135
        TableType::iterator iter = m_table.find(propertyName.uid());
136
        if (iter == m_table.end() || !iter->value)
137
            return; // Absence on replace => top.
138
139
        iter->value->makeTop(vm, propertyName);
140
        iter->value.clear();
141
        return;
142
    }
143
144
    TableType::AddResult result;
145
    {
146
        ConcurrentJITLocker locker(m_lock);
147
        result = m_table.add(propertyName.uid(), WriteBarrier<InferredType>());
148
    }
149
    if (!result.iterator->value)
150
        return;
151
    
152
    result.iterator->value->makeTop(vm, propertyName);
153
    result.iterator->value.clear();
154
}
155
156
InferredTypeTable::InferredTypeTable(VM& vm)
157
    : Base(vm, vm.inferredTypeTableStructure.get())
158
{
159
}
160
161
InferredTypeTable::~InferredTypeTable()
162
{
163
}
164
165
} // namespace JSC
166
- Source/JavaScriptCore/runtime/InferredTypeTable.h +114 lines
Line 0 Source/JavaScriptCore/runtime/InferredTypeTable.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef InferredTypeTable_h
27
#define InferredTypeTable_h
28
29
#include "Identifier.h"
30
#include "InferredType.h"
31
#include "JSCell.h"
32
33
namespace JSC {
34
35
// A table of inferred types for some structure. This is a JSCell because that simplifies the Structure
36
// destructor and makes lifetime easier to manage. For example, since it's a cell, we know that this thing
37
// cannot be deleted while the DFG is running. This is separate from PropertyTable because most properties
38
// will not have an InferredType, since most properties are in dictionaries (if you think of "a property"
39
// as being "a property in some Structure"). Also, this will happily conflate the types of properties from
40
// different structures even if the structures represent disjoint sets of objects.
41
42
class InferredTypeTable final : public JSCell {
43
public:
44
    typedef JSCell Base;
45
46
    static InferredTypeTable* create(VM&);
47
48
    static const bool needsDestruction = true;
49
    static void destroy(JSCell*);
50
51
    static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;
52
    
53
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
54
55
    static void visitChildren(JSCell*, SlotVisitor&);
56
57
    DECLARE_INFO;
58
59
    ConcurrentJITLock& lock() { return m_lock; }
60
61
    bool isEmpty() const { return m_table.isEmpty(); }
62
63
    // Get the current inferred type. Returns nullptr for both Top and Bottom. Null means Bottom if the
64
    // owning Structure doesn't know about the property.
65
    InferredType* get(const ConcurrentJITLocker&, UniquedStringImpl*);
66
    InferredType* get(UniquedStringImpl*);
67
    InferredType* get(PropertyName);
68
69
    enum StoredPropertyAge {
70
        NewProperty,
71
        OldProperty
72
    };
73
    
74
    // Returns true if the InferredType for this property is still relevant after the store. It's not
75
    // relevant if it's Top. Note that this table will internally prune Top entries.
76
    bool willStoreValue(VM&, PropertyName, JSValue, StoredPropertyAge);
77
78
    // Invalidates the type for the property. Useful if we detect a store in a reflective context.
79
    void makeTop(VM&, PropertyName, StoredPropertyAge);
80
81
private:
82
    InferredTypeTable(VM&);
83
    ~InferredTypeTable();
84
85
    // Bottom: absence from table.
86
    // Top: null value in table, !value->isRelevant(), or absence from table.
87
    //
88
    // We know how to determine if absence from the table is bottom or top depending on whether the
89
    // property is present in the owning structure. Hence, depending on the structure, absence may have
90
    // different meanings. The way that this class determines if the owning structure knows of the property
91
    // is that we differentiate between actions: replace or transition. If we're adding a new property
92
    // (transition), then absence means bottom. If we're storing to an existing property (replace), then
93
    // absence means top. To make this work, we have to watch out for the case where two structures, S1 and
94
    // S2, share the same InferredTypeTable and neither of them initially know about property P. S1 may
95
    // want to add P without a type, while S2 may want to add P with a type. If S1 added P and used absence
96
    // to indicate Top, then S2 would use that absence to mean Bottom and would end up creating a non-Top
97
    // entry in the table. Then S1 would forget that it wanted Top, and would use S2's type. Clearly,
98
    // that's bad. We avoid such confusion by ensuring that a transition always adds an entry. Hence,
99
    // absence-means-bottom only comes into play for properties added before the InferredTypeTable was
100
    // created.
101
    typedef HashMap<RefPtr<UniquedStringImpl>, WriteBarrier<InferredType>, IdentifierRepHash, HashTraits<UniquedStringImpl*>> TableType;
102
    
103
    TableType m_table;
104
105
    // We only grab this lock when we're doing modifications on the main thread, or reads on the compiler
106
    // thread. The compiler thread is not allowed to do modifications.
107
    ConcurrentJITLock m_lock;
108
};
109
110
} // namespace JSC
111
112
#endif // InferredTypeTable_h
113
114
- Source/JavaScriptCore/runtime/JSObject.h -13 / +32 lines
Lines 1189-1194 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec1
1189
1189
1190
    Structure* structure = this->structure(vm);
1190
    Structure* structure = this->structure(vm);
1191
    if (structure->isDictionary()) {
1191
    if (structure->isDictionary()) {
1192
        ASSERT(!structure->hasInferredTypes());
1193
        
1192
        unsigned currentAttributes;
1194
        unsigned currentAttributes;
1193
        PropertyOffset offset = structure->get(vm, propertyName, currentAttributes);
1195
        PropertyOffset offset = structure->get(vm, propertyName, currentAttributes);
1194
        if (offset != invalidOffset) {
1196
        if (offset != invalidOffset) {
Lines 1227-1255 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec2
1227
1229
1228
    PropertyOffset offset;
1230
    PropertyOffset offset;
1229
    size_t currentCapacity = this->structure()->outOfLineCapacity();
1231
    size_t currentCapacity = this->structure()->outOfLineCapacity();
1230
    if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, offset)) {
1232
    Structure* newStructure = Structure::addPropertyTransitionToExistingStructure(
1233
        structure, propertyName, attributes, offset);
1234
    if (newStructure) {
1235
        newStructure->willStoreValueForTransition(
1236
            vm, propertyName, value, slot.context() == PutPropertySlot::PutById);
1237
        
1231
        DeferGC deferGC(vm.heap);
1238
        DeferGC deferGC(vm.heap);
1232
        Butterfly* newButterfly = butterfly();
1239
        Butterfly* newButterfly = butterfly();
1233
        if (currentCapacity != structure->outOfLineCapacity()) {
1240
        if (currentCapacity != newStructure->outOfLineCapacity()) {
1234
            ASSERT(structure != this->structure());
1241
            ASSERT(newStructure != this->structure());
1235
            newButterfly = growOutOfLineStorage(vm, currentCapacity, structure->outOfLineCapacity());
1242
            newButterfly = growOutOfLineStorage(vm, currentCapacity, newStructure->outOfLineCapacity());
1236
        }
1243
        }
1237
1244
1238
        validateOffset(offset);
1245
        validateOffset(offset);
1239
        ASSERT(structure->isValidOffset(offset));
1246
        ASSERT(newStructure->isValidOffset(offset));
1240
        setStructureAndButterfly(vm, structure, newButterfly);
1247
        setStructureAndButterfly(vm, newStructure, newButterfly);
1241
        putDirect(vm, offset, value);
1248
        putDirect(vm, offset, value);
1242
        slot.setNewProperty(this, offset);
1249
        slot.setNewProperty(this, offset);
1243
        return true;
1250
        return true;
1244
    }
1251
    }
1245
1252
1246
    unsigned currentAttributes;
1253
    unsigned currentAttributes;
1247
    offset = structure->get(vm, propertyName, currentAttributes);
1254
    bool hasInferredType;
1255
    offset = structure->get(vm, propertyName, currentAttributes, hasInferredType);
1248
    if (offset != invalidOffset) {
1256
    if (offset != invalidOffset) {
1249
        if ((mode == PutModePut) && currentAttributes & ReadOnly)
1257
        if ((mode == PutModePut) && currentAttributes & ReadOnly)
1250
            return false;
1258
            return false;
1251
1259
1252
        structure->didReplaceProperty(offset);
1260
        structure->didReplaceProperty(offset);
1261
        if (UNLIKELY(hasInferredType)) {
1262
            structure->willStoreValueForReplace(
1263
                vm, propertyName, value, slot.context() == PutPropertySlot::PutById);
1264
        }
1265
1253
        slot.setExistingProperty(this, offset);
1266
        slot.setExistingProperty(this, offset);
1254
        putDirect(vm, offset, value);
1267
        putDirect(vm, offset, value);
1255
1268
Lines 1268-1283 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec3
1268
    // we want.
1281
    // we want.
1269
    DeferredStructureTransitionWatchpointFire deferredWatchpointFire;
1282
    DeferredStructureTransitionWatchpointFire deferredWatchpointFire;
1270
    
1283
    
1271
    structure = Structure::addPropertyTransition(vm, structure, propertyName, attributes, offset, slot.context(), &deferredWatchpointFire);
1284
    newStructure = Structure::addPropertyTransition(
1285
        vm, structure, propertyName, attributes, offset, slot.context(), &deferredWatchpointFire);
1286
    newStructure->willStoreValueForTransition(
1287
        vm, propertyName, value, slot.context() == PutPropertySlot::PutById);
1272
    
1288
    
1273
    validateOffset(offset);
1289
    validateOffset(offset);
1274
    ASSERT(structure->isValidOffset(offset));
1290
    ASSERT(newStructure->isValidOffset(offset));
1275
    setStructureAndReallocateStorageIfNecessary(vm, structure);
1291
    setStructureAndReallocateStorageIfNecessary(vm, newStructure);
1276
1292
1277
    putDirect(vm, offset, value);
1293
    putDirect(vm, offset, value);
1278
    slot.setNewProperty(this, offset);
1294
    slot.setNewProperty(this, offset);
1279
    if (attributes & ReadOnly)
1295
    if (attributes & ReadOnly)
1280
        structure->setContainsReadOnlyProperties();
1296
        newStructure->setContainsReadOnlyProperties();
1281
    return true;
1297
    return true;
1282
}
1298
}
1283
1299
Lines 1335-1342 inline void JSObject::putDirectWithoutTr Source/JavaScriptCore/runtime/JSObject.h_sec4
1335
    Butterfly* newButterfly = m_butterfly.get();
1351
    Butterfly* newButterfly = m_butterfly.get();
1336
    if (structure()->putWillGrowOutOfLineStorage())
1352
    if (structure()->putWillGrowOutOfLineStorage())
1337
        newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity());
1353
        newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity());
1338
    PropertyOffset offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes);
1354
    Structure* structure = this->structure();
1339
    setStructureAndButterfly(vm, structure(), newButterfly);
1355
    PropertyOffset offset = structure->addPropertyWithoutTransition(vm, propertyName, attributes);
1356
    bool shouldOptimize = false;
1357
    structure->willStoreValueForTransition(vm, propertyName, value, shouldOptimize);
1358
    setStructureAndButterfly(vm, structure, newButterfly);
1340
    putDirect(vm, offset, value);
1359
    putDirect(vm, offset, value);
1341
}
1360
}
1342
1361
- Source/JavaScriptCore/runtime/Structure.cpp +62 lines
Lines 350-360 void Structure::materializePropertyMap(V Source/JavaScriptCore/runtime/Structure.cpp_sec1
350
    else
350
    else
351
        propertyTable().set(vm, this, table);
351
        propertyTable().set(vm, this, table);
352
352
353
    InferredTypeTable* typeTable = m_inferredTypeTable.get();
354
353
    for (size_t i = structures.size(); i--;) {
355
    for (size_t i = structures.size(); i--;) {
354
        structure = structures[i];
356
        structure = structures[i];
355
        if (!structure->m_nameInPrevious)
357
        if (!structure->m_nameInPrevious)
356
            continue;
358
            continue;
357
        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious());
359
        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious());
360
        if (typeTable && typeTable->get(structure->m_nameInPrevious.get()))
361
            entry.hasInferredType = true;
358
        propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
362
        propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
359
    }
363
    }
360
    
364
    
Lines 464-469 Structure* Structure::addPropertyTransit Source/JavaScriptCore/runtime/Structure.cpp_sec2
464
    transition->setAttributesInPrevious(attributes);
468
    transition->setAttributesInPrevious(attributes);
465
    transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
469
    transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
466
    transition->m_offset = structure->m_offset;
470
    transition->m_offset = structure->m_offset;
471
    transition->m_inferredTypeTable.setMayBeNull(vm, transition, structure->m_inferredTypeTable.get());
467
472
468
    offset = transition->add(vm, propertyName, attributes);
473
    offset = transition->add(vm, propertyName, attributes);
469
474
Lines 479-484 Structure* Structure::addPropertyTransit Source/JavaScriptCore/runtime/Structure.cpp_sec3
479
484
480
Structure* Structure::removePropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, PropertyOffset& offset)
485
Structure* Structure::removePropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, PropertyOffset& offset)
481
{
486
{
487
    // NOTE: There are some good reasons why this goes directly to uncacheable dictionary rather than
488
    // caching the removal. We can fix all of these things, but we must remember to do so, if we ever try
489
    // to optimize this case.
490
    //
491
    // - Cached transitions usually steal the property table, and assume that this is possible because they
492
    //   can just rebuild the table by looking at past transitions. That code assumes that the table only
493
    //   grew and never shrank. To support removals, we'd have to change the property table materialization
494
    //   code to handle deletions. Also, we have logic to get the list of properties on a structure that
495
    //   lacks a property table by just looking back through the set of transitions since the last
496
    //   structure that had a pinned table. That logic would also have to be changed to handle cached
497
    //   removals.
498
    //
499
    // - InferredTypeTable assumes that removal has never happened. This is important since if we could
500
    //   remove a property and then re-add it later, then the "absence means top" optimization wouldn't
501
    //   work anymore, unless removal also either poisoned type inference (by doing something equivalent to
502
    //   hasBeenDictionary) or by strongly marking the entry as Top by ensuring that it is not absent, but
503
    //   instead, has a null entry.
504
    
482
    ASSERT(!structure->isUncacheableDictionary());
505
    ASSERT(!structure->isUncacheableDictionary());
483
506
484
    Structure* transition = toUncacheableDictionaryTransition(vm, structure);
507
    Structure* transition = toUncacheableDictionaryTransition(vm, structure);
Lines 841-846 void Structure::startWatchingInternalPro Source/JavaScriptCore/runtime/Structure.cpp_sec4
841
    setDidWatchInternalProperties(true);
864
    setDidWatchInternalProperties(true);
842
}
865
}
843
866
867
void Structure::willStoreValueSlow(
868
    VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize,
869
    InferredTypeTable::StoredPropertyAge age)
870
{
871
    ASSERT(!isCompilationThread());
872
    ASSERT(structure()->classInfo() == info());
873
    ASSERT(!hasBeenDictionary());
874
875
    // Create the inferred type table before doing anything else, so that we don't GC after we have already
876
    // grabbed a pointer into the property map.
877
    InferredTypeTable* table = m_inferredTypeTable.get();
878
    if (!table) {
879
        table = InferredTypeTable::create(vm);
880
        WTF::storeStoreFence();
881
        m_inferredTypeTable.set(vm, this, table);
882
    }
883
884
    // This only works if we've got a property table.
885
    PropertyTable* propertyTable;
886
    materializePropertyMapIfNecessary(vm, propertyTable);
887
888
    // We must be calling this after having created the given property or confirmed that it was present
889
    // already, so we must have a property table now.
890
    ASSERT(propertyTable);
891
892
    // ... and the property must be present.
893
    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
894
    ASSERT(entry);
895
896
    if (shouldOptimize)
897
        entry->hasInferredType = table->willStoreValue(vm, propertyName, value, age);
898
    else {
899
        table->makeTop(vm, propertyName, age);
900
        entry->hasInferredType = false;
901
    }
902
}
903
844
#if DUMP_PROPERTYMAP_STATS
904
#if DUMP_PROPERTYMAP_STATS
845
905
846
PropertyMapHashTableStats* propertyMapHashTableStats = 0;
906
PropertyMapHashTableStats* propertyMapHashTableStats = 0;
Lines 1058-1063 void Structure::visitChildren(JSCell* ce Source/JavaScriptCore/runtime/Structure.cpp_sec5
1058
        visitor.append(&thisObject->m_propertyTableUnsafe);
1118
        visitor.append(&thisObject->m_propertyTableUnsafe);
1059
    } else if (thisObject->m_propertyTableUnsafe)
1119
    } else if (thisObject->m_propertyTableUnsafe)
1060
        thisObject->m_propertyTableUnsafe.clear();
1120
        thisObject->m_propertyTableUnsafe.clear();
1121
1122
    visitor.append(&thisObject->m_inferredTypeTable);
1061
}
1123
}
1062
1124
1063
bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
1125
bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
- Source/JavaScriptCore/runtime/Structure.h +44 lines
Lines 29-34 Source/JavaScriptCore/runtime/Structure.h_sec1
29
#include "ClassInfo.h"
29
#include "ClassInfo.h"
30
#include "ConcurrentJITLock.h"
30
#include "ConcurrentJITLock.h"
31
#include "IndexingType.h"
31
#include "IndexingType.h"
32
#include "InferredTypeTable.h"
32
#include "JSCJSValue.h"
33
#include "JSCJSValue.h"
33
#include "JSCell.h"
34
#include "JSCell.h"
34
#include "JSType.h"
35
#include "JSType.h"
Lines 81-91 struct PropertyMapEntry { Source/JavaScriptCore/runtime/Structure.h_sec2
81
    UniquedStringImpl* key;
82
    UniquedStringImpl* key;
82
    PropertyOffset offset;
83
    PropertyOffset offset;
83
    uint8_t attributes;
84
    uint8_t attributes;
85
    bool hasInferredType; // This caches whether or not a property has an inferred type in the inferred type table, and is used for a fast check in JSObject::putDirectInternal().
84
86
85
    PropertyMapEntry()
87
    PropertyMapEntry()
86
        : key(nullptr)
88
        : key(nullptr)
87
        , offset(invalidOffset)
89
        , offset(invalidOffset)
88
        , attributes(0)
90
        , attributes(0)
91
        , hasInferredType(false)
89
    {
92
    {
90
    }
93
    }
91
    
94
    
Lines 93-98 struct PropertyMapEntry { Source/JavaScriptCore/runtime/Structure.h_sec3
93
        : key(key)
96
        : key(key)
94
        , offset(offset)
97
        , offset(offset)
95
        , attributes(attributes)
98
        , attributes(attributes)
99
        , hasInferredType(false)
96
    {
100
    {
97
        ASSERT(this->attributes == attributes);
101
        ASSERT(this->attributes == attributes);
98
    }
102
    }
Lines 323-328 public: Source/JavaScriptCore/runtime/Structure.h_sec4
323
327
324
    PropertyOffset get(VM&, PropertyName);
328
    PropertyOffset get(VM&, PropertyName);
325
    PropertyOffset get(VM&, PropertyName, unsigned& attributes);
329
    PropertyOffset get(VM&, PropertyName, unsigned& attributes);
330
    PropertyOffset get(VM&, PropertyName, unsigned& attributes, bool& hasInferredType);
326
331
327
    // This is a somewhat internalish method. It will call your functor while possibly holding the
332
    // This is a somewhat internalish method. It will call your functor while possibly holding the
328
    // Structure's lock. There is no guarantee whether the lock is held or not in any particular
333
    // Structure's lock. There is no guarantee whether the lock is held or not in any particular
Lines 481-486 public: Source/JavaScriptCore/runtime/Structure.h_sec5
481
            structure->startWatchingInternalPropertiesIfNecessary(vm);
486
            structure->startWatchingInternalPropertiesIfNecessary(vm);
482
    }
487
    }
483
488
489
    bool hasInferredTypes() const
490
    {
491
        return !!m_inferredTypeTable;
492
    }
493
494
    InferredType* inferredTypeFor(UniquedStringImpl* uid)
495
    {
496
        if (InferredTypeTable* table = m_inferredTypeTable.get())
497
            return table->get(uid);
498
        return nullptr;
499
    }
500
501
    InferredType::Descriptor inferredTypeDescriptorFor(UniquedStringImpl* uid)
502
    {
503
        if (InferredType* result = inferredTypeFor(uid))
504
            return result->descriptor();
505
        return InferredType::Top;
506
    }
507
508
    ALWAYS_INLINE void willStoreValueForTransition(
509
        VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize)
510
    {
511
        if (hasBeenDictionary() || (!shouldOptimize && !m_inferredTypeTable))
512
            return;
513
        willStoreValueSlow(vm, propertyName, value, shouldOptimize, InferredTypeTable::NewProperty);
514
    }
515
    ALWAYS_INLINE void willStoreValueForReplace(
516
        VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize)
517
    {
518
        if (hasBeenDictionary())
519
            return;
520
        willStoreValueSlow(vm, propertyName, value, shouldOptimize, InferredTypeTable::OldProperty);
521
    }
522
484
    PassRefPtr<StructureShape> toStructureShape(JSValue);
523
    PassRefPtr<StructureShape> toStructureShape(JSValue);
485
    
524
    
486
    // Determines if the two structures match enough that this one could be used for allocations
525
    // Determines if the two structures match enough that this one could be used for allocations
Lines 632-637 private: Source/JavaScriptCore/runtime/Structure.h_sec6
632
    
671
    
633
    void startWatchingInternalProperties(VM&);
672
    void startWatchingInternalProperties(VM&);
634
673
674
    JS_EXPORT_PRIVATE void willStoreValueSlow(
675
        VM&, PropertyName, JSValue, bool, InferredTypeTable::StoredPropertyAge);
676
635
    static const int s_maxTransitionLength = 64;
677
    static const int s_maxTransitionLength = 64;
636
    static const int s_maxTransitionLengthForNonEvalPutById = 512;
678
    static const int s_maxTransitionLengthForNonEvalPutById = 512;
637
679
Lines 655-660 private: Source/JavaScriptCore/runtime/Structure.h_sec7
655
    // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
697
    // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
656
    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
698
    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
657
699
700
    WriteBarrier<InferredTypeTable> m_inferredTypeTable;
701
658
    mutable InlineWatchpointSet m_transitionWatchpointSet;
702
    mutable InlineWatchpointSet m_transitionWatchpointSet;
659
703
660
    COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
704
    COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
- Source/JavaScriptCore/runtime/StructureInlines.h -10 / +11 lines
Lines 1-5 Source/JavaScriptCore/runtime/StructureInlines.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
2
 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 75-93 inline Structure* Structure::storedProto Source/JavaScriptCore/runtime/StructureInlines.h_sec2
75
75
76
ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
76
ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
77
{
77
{
78
    ASSERT(!isCompilationThread());
78
    unsigned attributes;
79
    ASSERT(structure()->classInfo() == info());
79
    bool hasInferredType;
80
    PropertyTable* propertyTable;
80
    return get(vm, propertyName, attributes, hasInferredType);
81
    materializePropertyMapIfNecessary(vm, propertyTable);
82
    if (!propertyTable)
83
        return invalidOffset;
84
85
    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
86
    return entry ? entry->offset : invalidOffset;
87
}
81
}
88
    
82
    
89
ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes)
83
ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes)
90
{
84
{
85
    bool hasInferredType;
86
    return get(vm, propertyName, attributes, hasInferredType);
87
}
88
89
ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes, bool& hasInferredType)
90
{
91
    ASSERT(!isCompilationThread());
91
    ASSERT(!isCompilationThread());
92
    ASSERT(structure()->classInfo() == info());
92
    ASSERT(structure()->classInfo() == info());
93
93
Lines 101-106 ALWAYS_INLINE PropertyOffset Structure:: Source/JavaScriptCore/runtime/StructureInlines.h_sec3
101
        return invalidOffset;
101
        return invalidOffset;
102
102
103
    attributes = entry->attributes;
103
    attributes = entry->attributes;
104
    hasInferredType = entry->hasInferredType;
104
    return entry->offset;
105
    return entry->offset;
105
}
106
}
106
107
- Source/JavaScriptCore/runtime/VM.cpp +3 lines
Lines 51-56 Source/JavaScriptCore/runtime/VM.cpp_sec1
51
#include "HostCallReturnValue.h"
51
#include "HostCallReturnValue.h"
52
#include "Identifier.h"
52
#include "Identifier.h"
53
#include "IncrementalSweeper.h"
53
#include "IncrementalSweeper.h"
54
#include "InferredTypeTable.h"
54
#include "Interpreter.h"
55
#include "Interpreter.h"
55
#include "JITCode.h"
56
#include "JITCode.h"
56
#include "JSAPIValueWrapper.h"
57
#include "JSAPIValueWrapper.h"
Lines 241-246 VM::VM(VMType vmType, HeapType heapType) Source/JavaScriptCore/runtime/VM.cpp_sec2
241
    propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull()));
242
    propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull()));
242
    weakMapDataStructure.set(*this, WeakMapData::createStructure(*this, 0, jsNull()));
243
    weakMapDataStructure.set(*this, WeakMapData::createStructure(*this, 0, jsNull()));
243
    inferredValueStructure.set(*this, InferredValue::createStructure(*this, 0, jsNull()));
244
    inferredValueStructure.set(*this, InferredValue::createStructure(*this, 0, jsNull()));
245
    inferredTypeStructure.set(*this, InferredType::createStructure(*this, 0, jsNull()));
246
    inferredTypeTableStructure.set(*this, InferredTypeTable::createStructure(*this, 0, jsNull()));
244
    functionRareDataStructure.set(*this, FunctionRareData::createStructure(*this, 0, jsNull()));
247
    functionRareDataStructure.set(*this, FunctionRareData::createStructure(*this, 0, jsNull()));
245
    exceptionStructure.set(*this, Exception::createStructure(*this, 0, jsNull()));
248
    exceptionStructure.set(*this, Exception::createStructure(*this, 0, jsNull()));
246
    promiseDeferredStructure.set(*this, JSPromiseDeferred::createStructure(*this, 0, jsNull()));
249
    promiseDeferredStructure.set(*this, JSPromiseDeferred::createStructure(*this, 0, jsNull()));
- Source/JavaScriptCore/runtime/VM.h +2 lines
Lines 302-307 public: Source/JavaScriptCore/runtime/VM.h_sec1
302
    Strong<Structure> propertyTableStructure;
302
    Strong<Structure> propertyTableStructure;
303
    Strong<Structure> weakMapDataStructure;
303
    Strong<Structure> weakMapDataStructure;
304
    Strong<Structure> inferredValueStructure;
304
    Strong<Structure> inferredValueStructure;
305
    Strong<Structure> inferredTypeStructure;
306
    Strong<Structure> inferredTypeTableStructure;
305
    Strong<Structure> functionRareDataStructure;
307
    Strong<Structure> functionRareDataStructure;
306
    Strong<Structure> exceptionStructure;
308
    Strong<Structure> exceptionStructure;
307
    Strong<Structure> promiseDeferredStructure;
309
    Strong<Structure> promiseDeferredStructure;
- Source/JavaScriptCore/tests/stress/prop-type-boolean-then-string.js +29 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-boolean-then-string.js_sec1
1
function foo(o) {
2
    return !!o.f;
3
}
4
5
function bar(o, v) {
6
    o.f = v;
7
}
8
9
noInline(foo);
10
noInline(bar);
11
12
var o = {};
13
for (var i = 0; i < 5; ++i)
14
    bar(o, true);
15
16
for (var i = 0; i < 10000; ++i) {
17
    var result = foo(o);
18
    if (result !== true)
19
        throw "Error: bad result: " + result;
20
}
21
22
bar(o, "hello");
23
var result = foo(o);
24
if (result !== true)
25
    throw "Error: bad result at end (true): " + result;
26
bar(o, "");
27
result = foo(o);
28
if (result !== false)
29
    throw "Error: bad result at end (false): " + result;
- Source/JavaScriptCore/tests/stress/prop-type-int32-then-string.js +25 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-int32-then-string.js_sec1
1
function foo(o) {
2
    return o.f + 1;
3
}
4
5
function bar(o, v) {
6
    o.f = v;
7
}
8
9
noInline(foo);
10
noInline(bar);
11
12
var o = {};
13
for (var i = 0; i < 5; ++i)
14
    bar(o, 42);
15
16
for (var i = 0; i < 10000; ++i) {
17
    var result = foo(o);
18
    if (result !== 43)
19
        throw "Error: bad result: " + result;
20
}
21
22
bar(o, "hello");
23
var result = foo(o);
24
if (result !== "hello1")
25
    throw "Error: bad result at end: " + result;
- Source/JavaScriptCore/tests/stress/prop-type-number-then-string.js +25 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-number-then-string.js_sec1
1
function foo(o) {
2
    return o.f + 1;
3
}
4
5
function bar(o, v) {
6
    o.f = v;
7
}
8
9
noInline(foo);
10
noInline(bar);
11
12
var o = {};
13
for (var i = 0; i < 5; ++i)
14
    bar(o, 4.2);
15
16
for (var i = 0; i < 10000; ++i) {
17
    var result = foo(o);
18
    if (result !== 5.2)
19
        throw "Error: bad result: " + result;
20
}
21
22
bar(o, "hello");
23
var result = foo(o);
24
if (result !== "hello1")
25
    throw "Error: bad result at end: " + result;
- Source/JavaScriptCore/tests/stress/prop-type-object-or-other-then-string.js +33 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-object-or-other-then-string.js_sec1
1
String.prototype.g = 44;
2
3
function foo(o) {
4
    return o.f == {toString:function() { return "hello"; }};
5
}
6
7
function bar(o, v) {
8
    o.f = v;
9
}
10
11
noInline(foo);
12
noInline(bar);
13
14
var o = {};
15
var p = {};
16
for (var i = 0; i < 5; ++i)
17
    bar(o, null);
18
for (var i = 0; i < 5; ++i)
19
    bar(p, {g:43});
20
21
for (var i = 0; i < 10000; ++i) {
22
    var result = foo(o);
23
    if (result !== false)
24
        throw "Error: bad result for o: " + result;
25
    result = foo(p);
26
    if (result !== false)
27
        throw "Error: bad result for p: " + result;
28
}
29
30
bar(o, "hello");
31
var result = foo(o);
32
if (result !== true)
33
    throw "Error: bad result at end: " + result;
- Source/JavaScriptCore/tests/stress/prop-type-object-then-string.js +25 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-object-then-string.js_sec1
1
function foo(o) {
2
    return o.f == {toString:function() { return "hello"; }};
3
}
4
5
function bar(o, v) {
6
    o.f = v;
7
}
8
9
noInline(foo);
10
noInline(bar);
11
12
var o = {};
13
for (var i = 0; i < 5; ++i)
14
    bar(o, {});
15
16
for (var i = 0; i < 10000; ++i) {
17
    var result = foo(o);
18
    if (result !== false)
19
        throw "Error: bad result: " + result;
20
}
21
22
bar(o, "hello");
23
var result = foo(o);
24
if (result !== true)
25
    throw "Error: bad result at end: " + result;
- Source/JavaScriptCore/tests/stress/prop-type-other-then-string.js +25 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-other-then-string.js_sec1
1
function foo(o) {
2
    return o.f == "hello";
3
}
4
5
function bar(o, v) {
6
    o.f = v;
7
}
8
9
noInline(foo);
10
noInline(bar);
11
12
var o = {};
13
for (var i = 0; i < 5; ++i)
14
    bar(o, null);
15
16
for (var i = 0; i < 10000; ++i) {
17
    var result = foo(o);
18
    if (result !== false)
19
        throw "Error: bad result: " + result;
20
}
21
22
bar(o, "hello");
23
var result = foo(o);
24
if (result !== true)
25
    throw "Error: bad result at end: " + result;
- Source/JavaScriptCore/tests/stress/prop-type-string-then-object.js +25 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-string-then-object.js_sec1
1
function foo(o) {
2
    return o.f + " world";
3
}
4
5
function bar(o, v) {
6
    o.f = v;
7
}
8
9
noInline(foo);
10
noInline(bar);
11
12
var o = {};
13
for (var i = 0; i < 5; ++i)
14
    bar(o, "hello");
15
16
for (var i = 0; i < 10000; ++i) {
17
    var result = foo(o);
18
    if (result != "hello world")
19
        throw "Error: bad result: " + result;
20
}
21
22
bar(o, {toString: function() { return "hello"; }});
23
var result = foo(o);
24
if (result != "hello world")
25
    throw "Error: bad result at end: " + result;
- Source/JavaScriptCore/tests/stress/prop-type-struct-or-other-then-string.js +36 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-struct-or-other-then-string.js_sec1
1
String.prototype.g = 44;
2
3
function foo(o) {
4
    var tmp = o.f;
5
    if (tmp)
6
        return tmp.g;
7
    return 42;
8
}
9
10
function bar(o, v) {
11
    o.f = v;
12
}
13
14
noInline(foo);
15
noInline(bar);
16
17
var o = {};
18
var p = {};
19
for (var i = 0; i < 5; ++i)
20
    bar(o, null);
21
for (var i = 0; i < 5; ++i)
22
    bar(p, {g:43});
23
24
for (var i = 0; i < 10000; ++i) {
25
    var result = foo(o);
26
    if (result !== 42)
27
        throw "Error: bad result for o: " + result;
28
    result = foo(p);
29
    if (result !== 43)
30
        throw "Error: bad result for p: " + result;
31
}
32
33
bar(o, "hello");
34
var result = foo(o);
35
if (result !== 44)
36
    throw "Error: bad result at end: " + result;
- Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-fold.js +34 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-fold.js_sec1
1
// This is like prop-type-struct-then-object.js, but it checks that the optimizing JITs emit the right type
2
// check above a hot put_by_id that starts polymorphic but is folded by AI.
3
4
function foo(o) {
5
    return o.f.g;
6
}
7
8
function bar(o, p, v) {
9
    if (isFinalTier() || o == p) {
10
        var tmp = p.f;
11
        o = p;
12
    }
13
    o.f = v;
14
}
15
16
noInline(foo);
17
noInline(bar);
18
19
var o = {f:{g:42}};
20
for (var i = 0; i < 10000; ++i) {
21
    bar(o, o, {g:42});
22
    bar({a:1, b:2}, o, {g:42});
23
}
24
25
for (var i = 0; i < 10000; ++i) {
26
    var result = foo(o);
27
    if (result !== 42)
28
        throw "Error: bad result: " + result;
29
}
30
31
bar(o, o, Object.create({g:43}));
32
var result = foo(o);
33
if (result !== 43)
34
    throw "Error: bad result at end: " + result;
- Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-multi.js +30 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-multi.js_sec1
1
// This is like prop-type-struct-then-object.js, but it checks that the optimizing JITs emit the right type
2
// check above a hot polymorphic put_by_id that ends up being compiled as a MultiPutByOffset.
3
4
function foo(o) {
5
    return o.f.g;
6
}
7
8
function bar(o, v) {
9
    o.f = v;
10
}
11
12
noInline(foo);
13
noInline(bar);
14
15
var o = {f:{g:42}};
16
for (var i = 0; i < 10000; ++i) {
17
    bar(o, {g:42});
18
    bar({a:1, b:2}, 42);
19
}
20
21
for (var i = 0; i < 10000; ++i) {
22
    var result = foo(o);
23
    if (result !== 42)
24
        throw "Error: bad result: " + result;
25
}
26
27
bar(o, Object.create({g:43}));
28
var result = foo(o);
29
if (result !== 43)
30
    throw "Error: bad result at end: " + result;
- Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt.js +28 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt.js_sec1
1
// This is like prop-type-struct-then-object.js, but it checks that the optimizing JITs emit the right type
2
// check above a hot put_by_id.
3
4
function foo(o) {
5
    return o.f.g;
6
}
7
8
function bar(o, v) {
9
    o.f = v;
10
}
11
12
noInline(foo);
13
noInline(bar);
14
15
var o = {f:{g:42}};
16
for (var i = 0; i < 10000; ++i)
17
    bar(o, {g:42});
18
19
for (var i = 0; i < 10000; ++i) {
20
    var result = foo(o);
21
    if (result !== 42)
22
        throw "Error: bad result: " + result;
23
}
24
25
bar(o, Object.create({g:43}));
26
var result = foo(o);
27
if (result !== 43)
28
    throw "Error: bad result at end: " + result;
- Source/JavaScriptCore/tests/stress/prop-type-struct-then-object.js +25 lines
Line 0 Source/JavaScriptCore/tests/stress/prop-type-struct-then-object.js_sec1
1
function foo(o) {
2
    return o.f.g;
3
}
4
5
function bar(o, v) {
6
    o.f = v;
7
}
8
9
noInline(foo);
10
noInline(bar);
11
12
var o = {};
13
for (var i = 0; i < 5; ++i)
14
    bar(o, {g:42});
15
16
for (var i = 0; i < 10000; ++i) {
17
    var result = foo(o);
18
    if (result !== 42)
19
        throw "Error: bad result: " + result;
20
}
21
22
bar(o, Object.create({g:43}));
23
var result = foo(o);
24
if (result !== 43)
25
    throw "Error: bad result at end: " + result;
- Source/WTF/ChangeLog +12 lines
Lines 1-3 Source/WTF/ChangeLog_sec1
1
2015-09-17  Filip Pizlo  <fpizlo@apple.com>
2
3
        JSC should infer property types
4
        https://bugs.webkit.org/show_bug.cgi?id=148610
5
6
        Reviewed by Geoffrey Garen.
7
8
        * wtf/HashTable.h:
9
        (WTF::HashTableAddResult::HashTableAddResult): Make it possible to say "HashMap::AddResult result" without assigning anything to it yet.
10
        * wtf/PrintStream.h:
11
        (WTF::printInternal): Beef up printing of some common WTF types, in particular RefPtr<UniquedStringImpl>.
12
1
2015-09-20  Youenn Fablet  <youenn.fablet@crf.canon.fr>
13
2015-09-20  Youenn Fablet  <youenn.fablet@crf.canon.fr>
2
14
3
        Remove XHR_TIMEOUT compilation guard
15
        Remove XHR_TIMEOUT compilation guard
- Source/WTF/wtf/HashTable.h +1 lines
Lines 286-291 namespace WTF { Source/WTF/wtf/HashTable.h_sec1
286
    };
286
    };
287
287
288
    template<typename IteratorType> struct HashTableAddResult {
288
    template<typename IteratorType> struct HashTableAddResult {
289
        HashTableAddResult() : isNewEntry(false) { }
289
        HashTableAddResult(IteratorType iter, bool isNewEntry) : iterator(iter), isNewEntry(isNewEntry) { }
290
        HashTableAddResult(IteratorType iter, bool isNewEntry) : iterator(iter), isNewEntry(isNewEntry) { }
290
        IteratorType iterator;
291
        IteratorType iterator;
291
        bool isNewEntry;
292
        bool isNewEntry;
- Source/WTF/wtf/PrintStream.h +9 lines
Lines 31-36 Source/WTF/wtf/PrintStream.h_sec1
31
#include <wtf/FastMalloc.h>
31
#include <wtf/FastMalloc.h>
32
#include <wtf/Noncopyable.h>
32
#include <wtf/Noncopyable.h>
33
#include <wtf/RawPointer.h>
33
#include <wtf/RawPointer.h>
34
#include <wtf/RefPtr.h>
34
#include <wtf/StdLibExtras.h>
35
#include <wtf/StdLibExtras.h>
35
36
36
namespace WTF {
37
namespace WTF {
Lines 74-85 WTF_EXPORT_PRIVATE void printInternal(Pr Source/WTF/wtf/PrintStream.h_sec2
74
WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const StringImpl*);
75
WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const StringImpl*);
75
inline void printInternal(PrintStream& out, const AtomicStringImpl* value) { printInternal(out, bitwise_cast<const StringImpl*>(value)); }
76
inline void printInternal(PrintStream& out, const AtomicStringImpl* value) { printInternal(out, bitwise_cast<const StringImpl*>(value)); }
76
inline void printInternal(PrintStream& out, const UniquedStringImpl* value) { printInternal(out, bitwise_cast<const StringImpl*>(value)); }
77
inline void printInternal(PrintStream& out, const UniquedStringImpl* value) { printInternal(out, bitwise_cast<const StringImpl*>(value)); }
78
inline void printInternal(PrintStream& out, const UniquedStringImpl& value) { printInternal(out, &value); }
77
inline void printInternal(PrintStream& out, char* value) { printInternal(out, static_cast<const char*>(value)); }
79
inline void printInternal(PrintStream& out, char* value) { printInternal(out, static_cast<const char*>(value)); }
78
inline void printInternal(PrintStream& out, CString& value) { printInternal(out, static_cast<const CString&>(value)); }
80
inline void printInternal(PrintStream& out, CString& value) { printInternal(out, static_cast<const CString&>(value)); }
79
inline void printInternal(PrintStream& out, String& value) { printInternal(out, static_cast<const String&>(value)); }
81
inline void printInternal(PrintStream& out, String& value) { printInternal(out, static_cast<const String&>(value)); }
80
inline void printInternal(PrintStream& out, StringImpl* value) { printInternal(out, static_cast<const StringImpl*>(value)); }
82
inline void printInternal(PrintStream& out, StringImpl* value) { printInternal(out, static_cast<const StringImpl*>(value)); }
81
inline void printInternal(PrintStream& out, AtomicStringImpl* value) { printInternal(out, static_cast<const AtomicStringImpl*>(value)); }
83
inline void printInternal(PrintStream& out, AtomicStringImpl* value) { printInternal(out, static_cast<const AtomicStringImpl*>(value)); }
82
inline void printInternal(PrintStream& out, UniquedStringImpl* value) { printInternal(out, static_cast<const UniquedStringImpl*>(value)); }
84
inline void printInternal(PrintStream& out, UniquedStringImpl* value) { printInternal(out, static_cast<const UniquedStringImpl*>(value)); }
85
inline void printInternal(PrintStream& out, UniquedStringImpl& value) { printInternal(out, &value); }
83
WTF_EXPORT_PRIVATE void printInternal(PrintStream&, bool);
86
WTF_EXPORT_PRIVATE void printInternal(PrintStream&, bool);
84
WTF_EXPORT_PRIVATE void printInternal(PrintStream&, signed char); // NOTE: this prints as a number, not as a character; use CharacterDump if you want the character
87
WTF_EXPORT_PRIVATE void printInternal(PrintStream&, signed char); // NOTE: this prints as a number, not as a character; use CharacterDump if you want the character
85
WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned char); // NOTE: see above.
88
WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned char); // NOTE: see above.
Lines 169-174 void printInternal(PrintStream& out, con Source/WTF/wtf/PrintStream.h_sec3
169
    out.print(pointerDump(value.get()));
172
    out.print(pointerDump(value.get()));
170
}
173
}
171
174
175
template<typename T>
176
void printInternal(PrintStream& out, const RefPtr<T>& value)
177
{
178
    out.print(pointerDump(value.get()));
179
}
180
172
template<typename T, typename U>
181
template<typename T, typename U>
173
class ValueInContext {
182
class ValueInContext {
174
public:
183
public:
- Tools/Scripts/run-jsc-stress-tests +4 lines
Lines 699-704 def runWithRAMSize(size) Tools/Scripts/run-jsc-stress-tests_sec1
699
    run("ram-size-#{size}", "--forceRAMSize=#{size}")
699
    run("ram-size-#{size}", "--forceRAMSize=#{size}")
700
end
700
end
701
701
702
def runNoJIT
703
    run("no-jit", "--useJIT=false")
704
end
705
702
def runNoLLInt
706
def runNoLLInt
703
    if $jitTests
707
    if $jitTests
704
        run("no-llint", "--useLLInt=false")
708
        run("no-llint", "--useLLInt=false")

Return to Bug 148610