Changeset 172129 in webkit
- Timestamp:
- Aug 5, 2014, 10:27:46 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 42 added
- 5 deleted
- 145 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/js/regress/gcse-expected.txt (added)
-
LayoutTests/js/regress/gcse-poly-get-expected.txt (added)
-
LayoutTests/js/regress/gcse-poly-get-less-obvious-expected.txt (added)
-
LayoutTests/js/regress/gcse-poly-get-less-obvious.html (added)
-
LayoutTests/js/regress/gcse-poly-get.html (added)
-
LayoutTests/js/regress/gcse.html (added)
-
LayoutTests/js/regress/infer-constant-global-property-expected.txt (added)
-
LayoutTests/js/regress/infer-constant-global-property.html (added)
-
LayoutTests/js/regress/infer-constant-property-expected.txt (added)
-
LayoutTests/js/regress/infer-constant-property.html (added)
-
LayoutTests/js/regress/script-tests/gcse-poly-get-less-obvious.js (added)
-
LayoutTests/js/regress/script-tests/gcse-poly-get.js (added)
-
LayoutTests/js/regress/script-tests/gcse.js (added)
-
LayoutTests/js/regress/script-tests/infer-constant-global-property.js (added)
-
LayoutTests/js/regress/script-tests/infer-constant-property.js (added)
-
LayoutTests/sputnik/Implementation_Diagnostics/S12.6.4_D1-expected.txt (deleted)
-
LayoutTests/sputnik/Implementation_Diagnostics/S12.6.4_D1.html (deleted)
-
Source/JavaScriptCore/CMakeLists.txt (modified) (3 diffs)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (modified) (6 diffs)
-
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (modified) (28 diffs)
-
Source/JavaScriptCore/bytecode/BytecodeList.json (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/BytecodeUseDef.h (modified) (2 diffs)
-
Source/JavaScriptCore/bytecode/CodeBlock.cpp (modified) (18 diffs)
-
Source/JavaScriptCore/bytecode/CodeBlock.h (modified) (5 diffs)
-
Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.cpp (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.h (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/ComplexGetStatus.cpp (added)
-
Source/JavaScriptCore/bytecode/ComplexGetStatus.h (added)
-
Source/JavaScriptCore/bytecode/GetByIdStatus.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/bytecode/GetByIdVariant.cpp (modified) (7 diffs)
-
Source/JavaScriptCore/bytecode/GetByIdVariant.h (modified) (3 diffs)
-
Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h (modified) (6 diffs)
-
Source/JavaScriptCore/bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp (deleted)
-
Source/JavaScriptCore/bytecode/ProfiledCodeBlockJettisoningWatchpoint.h (deleted)
-
Source/JavaScriptCore/bytecode/PutByIdStatus.cpp (modified) (15 diffs)
-
Source/JavaScriptCore/bytecode/PutByIdStatus.h (modified) (3 diffs)
-
Source/JavaScriptCore/bytecode/PutByIdVariant.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/bytecode/PutByIdVariant.h (modified) (9 diffs)
-
Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/TypeLocation.h (modified) (2 diffs)
-
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (modified) (3 diffs)
-
Source/JavaScriptCore/bytecode/VariableWatchpointSet.cpp (added)
-
Source/JavaScriptCore/bytecode/VariableWatchpointSet.h (modified) (3 diffs)
-
Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h (modified) (3 diffs)
-
Source/JavaScriptCore/bytecode/Watchpoint.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/bytecode/Watchpoint.h (modified) (9 diffs)
-
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (modified) (7 diffs)
-
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (modified) (4 diffs)
-
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (modified) (30 diffs)
-
Source/JavaScriptCore/debugger/Debugger.h (modified) (1 diff)
-
Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp (modified) (5 diffs)
-
Source/JavaScriptCore/debugger/DebuggerCallFrame.h (modified) (4 diffs)
-
Source/JavaScriptCore/debugger/DebuggerScope.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/debugger/DebuggerScope.h (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGAbstractHeap.h (modified) (6 diffs)
-
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (modified) (8 diffs)
-
Source/JavaScriptCore/dfg/DFGAdjacencyList.h (modified) (3 diffs)
-
Source/JavaScriptCore/dfg/DFGBasicBlock.h (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (modified) (18 diffs)
-
Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGCSEPhase.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/dfg/DFGCSEPhase.h (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGCapabilities.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGCapabilities.h (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGClobberSet.cpp (modified) (5 diffs)
-
Source/JavaScriptCore/dfg/DFGClobberize.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGClobberize.h (modified) (43 diffs)
-
Source/JavaScriptCore/dfg/DFGCommonData.h (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGDCEPhase.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/dfg/DFGDesiredWeakReferences.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGEdgeDominates.h (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGGraph.cpp (modified) (5 diffs)
-
Source/JavaScriptCore/dfg/DFGGraph.h (modified) (5 diffs)
-
Source/JavaScriptCore/dfg/DFGHeapLocation.cpp (added)
-
Source/JavaScriptCore/dfg/DFGHeapLocation.h (added)
-
Source/JavaScriptCore/dfg/DFGLICMPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGNode.h (modified) (11 diffs)
-
Source/JavaScriptCore/dfg/DFGOSREntry.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGOperations.cpp (modified) (5 diffs)
-
Source/JavaScriptCore/dfg/DFGOperations.h (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp (added)
-
Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.h (added)
-
Source/JavaScriptCore/dfg/DFGPlan.cpp (modified) (8 diffs)
-
Source/JavaScriptCore/dfg/DFGPureValue.cpp (added)
-
Source/JavaScriptCore/dfg/DFGPureValue.h (added)
-
Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp (modified) (8 diffs)
-
Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/dfg/DFGWatchableStructureWatchingPhase.cpp (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLCapabilities.cpp (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLCompile.cpp (modified) (5 diffs)
-
Source/JavaScriptCore/ftl/FTLForOSREntryJITCode.cpp (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLInlineCacheDescriptor.h (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLInlineCacheSize.h (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (modified) (5 diffs)
-
Source/JavaScriptCore/ftl/FTLOSREntry.cpp (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLSlowPathCall.cpp (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLSlowPathCall.h (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLState.h (modified) (1 diff)
-
Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/inspector/JavaScriptCallFrame.h (modified) (2 diffs)
-
Source/JavaScriptCore/inspector/ScriptDebugServer.cpp (modified) (1 diff)
-
Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp (modified) (1 diff)
-
Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h (modified) (1 diff)
-
Source/JavaScriptCore/inspector/protocol/Runtime.json (modified) (1 diff)
-
Source/JavaScriptCore/interpreter/Interpreter.cpp (modified) (1 diff)
-
Source/JavaScriptCore/jit/JITOperations.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/jit/JITOperations.h (modified) (1 diff)
-
Source/JavaScriptCore/jit/Repatch.cpp (modified) (7 diffs)
-
Source/JavaScriptCore/jsc.cpp (modified) (1 diff)
-
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (modified) (7 diffs)
-
Source/JavaScriptCore/llint/LLIntSlowPaths.h (modified) (1 diff)
-
Source/JavaScriptCore/llint/LowLevelInterpreter.asm (modified) (1 diff)
-
Source/JavaScriptCore/profiler/ProfilerCompilation.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/profiler/ProfilerCompilation.h (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/ArrayBuffer.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/CommonIdentifiers.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/CommonSlowPaths.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/Executable.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/Executable.h (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/GetterSetter.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/GetterSetter.h (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/HighFidelityLog.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/runtime/HighFidelityLog.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/HighFidelityTypeProfiler.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/HighFidelityTypeProfiler.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/Identifier.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/Identifier.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/IndexingHeader.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/IntendedStructureChain.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/IntendedStructureChain.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSActivation.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSCJSValue.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSFunction.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/JSGlobalObject.cpp (modified) (7 diffs)
-
Source/JavaScriptCore/runtime/JSGlobalObject.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/JSObject.cpp (modified) (12 diffs)
-
Source/JavaScriptCore/runtime/JSObject.h (modified) (21 diffs)
-
Source/JavaScriptCore/runtime/JSScope.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSScope.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSSymbolTableObject.h (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/PropertyMapHashTable.h (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/PropertyName.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/PropertyTable.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/runtime/Structure.cpp (modified) (28 diffs)
-
Source/JavaScriptCore/runtime/Structure.h (modified) (12 diffs)
-
Source/JavaScriptCore/runtime/StructureInlines.h (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/StructureRareData.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/StructureRareData.h (modified) (5 diffs)
-
Source/JavaScriptCore/runtime/SymbolTable.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/SymbolTable.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/TypeSet.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/runtime/TypeSet.h (modified) (4 diffs)
-
Source/JavaScriptCore/runtime/VM.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/VM.h (modified) (2 diffs)
-
Source/JavaScriptCore/tests/stress/cached-prototype-setter.js (added)
-
Source/JavaScriptCore/tests/stress/exit-from-setter.js (added)
-
Source/JavaScriptCore/tests/stress/ftl-checkin-variable.js (added)
-
Source/JavaScriptCore/tests/stress/ftl-checkin.js (added)
-
Source/JavaScriptCore/tests/stress/infer-constant-global-property.js (added)
-
Source/JavaScriptCore/tests/stress/infer-constant-property.js (added)
-
Source/JavaScriptCore/tests/stress/jit-cache-poly-replace-then-cache-get-and-fold-then-invalidate.js (added)
-
Source/JavaScriptCore/tests/stress/jit-cache-replace-then-cache-get-and-fold-then-invalidate.js (added)
-
Source/JavaScriptCore/tests/stress/jit-put-to-scope-global-cache-watchpoint-invalidate.js (added)
-
Source/JavaScriptCore/tests/stress/llint-cache-replace-then-cache-get-and-fold-then-invalidate.js (added)
-
Source/JavaScriptCore/tests/stress/llint-put-to-scope-global-cache-watchpoint-invalidate.js (added)
-
Source/JavaScriptCore/tests/stress/poly-chain-setter.js (added)
-
Source/JavaScriptCore/tests/stress/poly-chain-then-setter.js (added)
-
Source/JavaScriptCore/tests/stress/poly-setter-combo.js (added)
-
Source/JavaScriptCore/tests/stress/poly-setter-then-self.js (added)
-
Source/JavaScriptCore/tests/stress/repeat-put-to-scope-global-with-same-value-watchpoint-invalidate.js (added)
-
Source/JavaScriptCore/tests/stress/weird-setter-counter-syntactic.js (added)
-
Source/JavaScriptCore/tests/stress/weird-setter-counter.js (added)
-
Source/WTF/wtf/PrintStream.h (modified) (3 diffs)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/ForwardingHeaders/debugger/DebuggerCallFrame.h (deleted)
-
Source/WebCore/bindings/js/JSDOMWindowBase.cpp (modified) (1 diff)
-
Source/WebCore/bindings/js/ScriptController.cpp (modified) (1 diff)
-
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/Scripts/display-profiler-output (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r172120 r172129 1 2014-07-29 Filip Pizlo <fpizlo@apple.com> 2 3 Merge r170564, r170571, r170604, r170628, r170672, r170680, r170724, r170728, r170729, r170819, r170821, r170836, r170855, r170860, r170890, r170907, r170929, r171052, r171106, r171152, r171153, r171214 from ftlopt. 4 5 2014-07-16 Mark Hahnenberg <mhahnenberg@apple.com> 6 7 sputnik/Implementation_Diagnostics/S12.6.4_D1.html depends on undefined behavior 8 https://bugs.webkit.org/show_bug.cgi?id=135007 9 10 Reviewed by Filip Pizlo. 11 12 EcmaScript 5.1 specifies that during for-in enumeration newly added properties may or may not be 13 visited during the current enumeration. Specifically, in section 12.6.4 the spec states: 14 15 "If new properties are added to the object being enumerated during enumeration, the newly added properties 16 are not guaranteed to be visited in the active enumeration." 17 18 The sputnik/Implementation_Diagnostics/S12.6.4_D1.html layout test is from before sputnik was added 19 to the test262 suite. I believe it has since been removed, so it would probably be okay to remove it 20 from our layout test suite. 21 22 * sputnik/Implementation_Diagnostics/S12.6.4_D1-expected.txt: Removed. 23 * sputnik/Implementation_Diagnostics/S12.6.4_D1.html: Removed. 24 25 2014-07-13 Filip Pizlo <fpizlo@apple.com> 26 27 [ftlopt] DFG should be able to do GCSE in SSA and this should be unified with the CSE in CPS, and both of these things should use abstract heaps for reasoning about effects 28 https://bugs.webkit.org/show_bug.cgi?id=134677 29 30 Reviewed by Sam Weinig. 31 32 * js/regress/gcse-expected.txt: Added. 33 * js/regress/gcse-poly-get-expected.txt: Added. 34 * js/regress/gcse-poly-get-less-obvious-expected.txt: Added. 35 * js/regress/gcse-poly-get-less-obvious.html: Added. 36 * js/regress/gcse-poly-get.html: Added. 37 * js/regress/gcse.html: Added. 38 * js/regress/script-tests/gcse-poly-get-less-obvious.js: Added. 39 * js/regress/script-tests/gcse-poly-get.js: Added. 40 * js/regress/script-tests/gcse.js: Added. 41 42 2014-07-04 Filip Pizlo <fpizlo@apple.com> 43 44 [ftlopt] Infer immutable object properties 45 https://bugs.webkit.org/show_bug.cgi?id=134567 46 47 Reviewed by Mark Hahnenberg. 48 49 * js/regress/infer-constant-global-property-expected.txt: Added. 50 * js/regress/infer-constant-global-property.html: Added. 51 * js/regress/infer-constant-property-expected.txt: Added. 52 * js/regress/infer-constant-property.html: Added. 53 * js/regress/script-tests/infer-constant-global-property.js: Added. 54 * js/regress/script-tests/infer-constant-property.js: Added. 55 1 56 2014-08-05 Commit Queue <commit-queue@webkit.org> 2 57 -
trunk/Source/JavaScriptCore/CMakeLists.txt
r172093 r172129 72 72 bytecode/CodeOrigin.cpp 73 73 bytecode/CodeType.cpp 74 bytecode/ComplerGetStatus.cpp 74 75 bytecode/ConstantStructureCheck.cpp 75 76 bytecode/DFGExitProfile.cpp … … 156 157 dfg/DFGGraph.cpp 157 158 dfg/DFGGraphSafepoint.cpp 159 dfg/DFGHeapLocation.cpp 158 160 dfg/DFGInPlaceAbstractState.cpp 159 161 dfg/DFGIntegerCheckCombiningPhase.cpp … … 185 187 dfg/DFGOSRExitPreparation.cpp 186 188 dfg/DFGOperations.cpp 189 dfg/DFGPhantomRemovalPhase.cpp 187 190 dfg/DFGPhase.cpp 188 191 dfg/DFGPlan.cpp 189 192 dfg/DFGPredictionInjectionPhase.cpp 190 193 dfg/DFGPredictionPropagationPhase.cpp 194 dfg/DFGPureValue.cpp 191 195 dfg/DFGResurrectionForValidationPhase.cpp 192 196 dfg/DFGSSAConversionPhase.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r172120 r172129 1 2014-07-29 Filip Pizlo <fpizlo@apple.com> 2 3 Merge r170564, r170571, r170604, r170628, r170672, r170680, r170724, r170728, r170729, r170819, r170821, r170836, r170855, r170860, r170890, r170907, r170929, r171052, r171106, r171152, r171153, r171214 from ftlopt. 4 5 This part of the merge delivers roughly a 2% across-the-board performance 6 improvement, mostly due to immutable property inference and DFG-side GCSE. It also 7 almost completely resolves accessor performance issues; in the common case the DFG 8 will compile a getter/setter access into code that is just as efficient as a normal 9 property access. 10 11 Another major highlight of this part of the merge is the work to add a type profiler 12 to the inspector. This work is still on-going but this greatly increases coverage. 13 14 Note that this merge fixes a minor bug in the GetterSetter refactoring from 15 http://trac.webkit.org/changeset/170729 (https://bugs.webkit.org/show_bug.cgi?id=134518). 16 It also adds a new tests to tests/stress to cover that bug. That bug was previously only 17 covered by layout tests. 18 19 2014-07-17 Filip Pizlo <fpizlo@apple.com> 20 21 [ftlopt] DFG Flush(SetLocal) store elimination is overzealous for captured variables in the presence of nodes that have no effects but may throw (merge trunk r171190) 22 https://bugs.webkit.org/show_bug.cgi?id=135019 23 24 Reviewed by Oliver Hunt. 25 26 Behaviorally, this is just a merge of trunk r171190, except that the relevant functionality 27 has moved to StrengthReductionPhase and is written in a different style. Same algorithm, 28 different code. 29 30 * dfg/DFGNodeType.h: 31 * dfg/DFGStrengthReductionPhase.cpp: 32 (JSC::DFG::StrengthReductionPhase::handleNode): 33 * tests/stress/capture-escape-and-throw.js: Added. 34 (foo.f): 35 (foo): 36 * tests/stress/new-array-with-size-throw-exception-and-tear-off-arguments.js: Added. 37 (foo): 38 (bar): 39 40 2014-07-15 Filip Pizlo <fpizlo@apple.com> 41 42 [ftlopt] Constant fold GetGetter and GetSetter if the GetterSetter is a constant 43 https://bugs.webkit.org/show_bug.cgi?id=134962 44 45 Reviewed by Oliver Hunt. 46 47 This removes yet another steady-state-throughput implication of using getters and setters: 48 if your accessor call is monomorphic then you'll just get a structure check, nothing more. 49 No more loads to get to the GetterSetter object or the accessor function object. 50 51 * dfg/DFGAbstractInterpreterInlines.h: 52 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 53 * runtime/GetterSetter.h: 54 (JSC::GetterSetter::getterConcurrently): 55 (JSC::GetterSetter::setGetter): 56 (JSC::GetterSetter::setterConcurrently): 57 (JSC::GetterSetter::setSetter): 58 59 2014-07-15 Filip Pizlo <fpizlo@apple.com> 60 61 [ftlopt] Identity replacement in CSE shouldn't create a Phantom over the Identity's children 62 https://bugs.webkit.org/show_bug.cgi?id=134893 63 64 Reviewed by Oliver Hunt. 65 66 Replace Identity with Check instead of Phantom. Phantom means that the child of the 67 Identity should be unconditionally live. The liveness semantics of Identity are such that 68 if the parents of Identity are live then the child is live. Removing the Identity entirely 69 preserves such liveness semantics. So, the only thing that should be left behind is the 70 type check on the child, which is what Check means: do the check but don't keep the child 71 alive if the check isn't needed. 72 73 * dfg/DFGCSEPhase.cpp: 74 * dfg/DFGNode.h: 75 (JSC::DFG::Node::convertToCheck): 76 77 2014-07-13 Filip Pizlo <fpizlo@apple.com> 78 79 [ftlopt] DFG should be able to do GCSE in SSA and this should be unified with the CSE in CPS, and both of these things should use abstract heaps for reasoning about effects 80 https://bugs.webkit.org/show_bug.cgi?id=134677 81 82 Reviewed by Sam Weinig. 83 84 This removes the old local CSE phase, which was based on manually written backward-search 85 rules for all of the different kinds of things we cared about, and adds a new local/global 86 CSE (local for CPS and global for SSA) that leaves the node semantics almost entirely up to 87 clobberize(). Thus, the CSE phase itself just worries about the algorithms and data 88 structures used for storing sets of available values. This results in a large reduction in 89 code size in CSEPhase.cpp while greatly increasing the phase's power (since it now does 90 global CSE) and reducing compile time (since local CSE is now rewritten to use smarter data 91 structures). Even though LLVM was already running GVN, the extra GCSE at DFG IR level means 92 that this is a significant (~0.7%) throughput improvement. 93 94 This work is based on the concept of "def" to clobberize(). If clobberize() calls def(), it 95 means that the node being analyzed makes available some value in some DFG node, and that 96 future attempts to compute that value can simply use that node. In other words, it 97 establishes an available value mapping of the form value=>node. There are two kinds of 98 values that can be passed to def(): 99 100 PureValue. This captures everything needed to determine whether two pure nodes - nodes that 101 neither read nor write, and produce a value that is a CSE candidate - are identical. It 102 carries the NodeType, an AdjacencyList, and one word of meta-data. The meta-data is 103 usually used for things like the arithmetic mode or constant pointer. Passing a 104 PureValue to def() means that the node produces a value that is valid anywhere that the 105 node dominates. 106 107 HeapLocation. This describes a location in the heap that could be written to or read from. 108 Both stores and loads can def() a HeapLocation. HeapLocation carries around an abstract 109 heap that both serves as part of the "name" of the heap location (together with the 110 other fields of HeapLocation) and also tells us what write()'s to watch for. If someone 111 write()'s to an abstract heap that overlaps the heap associated with the HeapLocation, 112 then it means that the values for that location are no longer available. 113 114 This approach is sufficiently clever that the CSEPhase itself can focus on the mechanism of 115 tracking the PureValue=>node and HeapLocation=>node maps, without having to worry about 116 interpreting the semantics of different DFG node types - that is now almost entirely in 117 clobberize(). The only things we special-case inside CSEPhase are the Identity node, which 118 CSE is traditionally responsible for eliminating even though it has nothing to do with CSE, 119 and the LocalCSE rule for turning PutByVal into PutByValAlias. 120 121 This is a slight Octane, SunSpider, and Kraken speed-up - all somewhere arond 0.7% . It's 122 not a bigger win because LLVM was already giving us most of what we needed in its GVN. 123 Also, the SunSpider speed-up isn't from GCSE as much as it's a clean-up of local CSE - that 124 is no longer O(n^2). Basically this is purely good: it reduces the amount of LLVM IR we 125 generate, it removes the old CSE's heap modeling (which was a constant source of bugs), and 126 it improves both the quality of the code we generate and the speed with which we generate 127 it. Also, any future optimizations that depend on GCSE will now be easier to implement. 128 129 During the development of this patch I also rationalized some other stuff, like Graph's 130 ordered traversals - we now have preorder and postorder rather than just "depth first". 131 132 * CMakeLists.txt: 133 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 134 * JavaScriptCore.xcodeproj/project.pbxproj: 135 * dfg/DFGAbstractHeap.h: 136 * dfg/DFGAdjacencyList.h: 137 (JSC::DFG::AdjacencyList::hash): 138 (JSC::DFG::AdjacencyList::operator==): 139 * dfg/DFGBasicBlock.h: 140 * dfg/DFGCSEPhase.cpp: 141 (JSC::DFG::performLocalCSE): 142 (JSC::DFG::performGlobalCSE): 143 (JSC::DFG::CSEPhase::CSEPhase): Deleted. 144 (JSC::DFG::CSEPhase::run): Deleted. 145 (JSC::DFG::CSEPhase::endIndexForPureCSE): Deleted. 146 (JSC::DFG::CSEPhase::pureCSE): Deleted. 147 (JSC::DFG::CSEPhase::constantCSE): Deleted. 148 (JSC::DFG::CSEPhase::constantStoragePointerCSE): Deleted. 149 (JSC::DFG::CSEPhase::getCalleeLoadElimination): Deleted. 150 (JSC::DFG::CSEPhase::getArrayLengthElimination): Deleted. 151 (JSC::DFG::CSEPhase::globalVarLoadElimination): Deleted. 152 (JSC::DFG::CSEPhase::scopedVarLoadElimination): Deleted. 153 (JSC::DFG::CSEPhase::varInjectionWatchpointElimination): Deleted. 154 (JSC::DFG::CSEPhase::getByValLoadElimination): Deleted. 155 (JSC::DFG::CSEPhase::checkFunctionElimination): Deleted. 156 (JSC::DFG::CSEPhase::checkExecutableElimination): Deleted. 157 (JSC::DFG::CSEPhase::checkStructureElimination): Deleted. 158 (JSC::DFG::CSEPhase::structureTransitionWatchpointElimination): Deleted. 159 (JSC::DFG::CSEPhase::getByOffsetLoadElimination): Deleted. 160 (JSC::DFG::CSEPhase::getGetterSetterByOffsetLoadElimination): Deleted. 161 (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination): Deleted. 162 (JSC::DFG::CSEPhase::checkArrayElimination): Deleted. 163 (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination): Deleted. 164 (JSC::DFG::CSEPhase::getInternalFieldLoadElimination): Deleted. 165 (JSC::DFG::CSEPhase::getMyScopeLoadElimination): Deleted. 166 (JSC::DFG::CSEPhase::getLocalLoadElimination): Deleted. 167 (JSC::DFG::CSEPhase::invalidationPointElimination): Deleted. 168 (JSC::DFG::CSEPhase::setReplacement): Deleted. 169 (JSC::DFG::CSEPhase::eliminate): Deleted. 170 (JSC::DFG::CSEPhase::performNodeCSE): Deleted. 171 (JSC::DFG::CSEPhase::performBlockCSE): Deleted. 172 (JSC::DFG::performCSE): Deleted. 173 * dfg/DFGCSEPhase.h: 174 * dfg/DFGClobberSet.cpp: 175 (JSC::DFG::addReads): 176 (JSC::DFG::addWrites): 177 (JSC::DFG::addReadsAndWrites): 178 (JSC::DFG::readsOverlap): 179 (JSC::DFG::writesOverlap): 180 * dfg/DFGClobberize.cpp: 181 (JSC::DFG::doesWrites): 182 (JSC::DFG::accessesOverlap): 183 (JSC::DFG::writesOverlap): 184 * dfg/DFGClobberize.h: 185 (JSC::DFG::clobberize): 186 (JSC::DFG::NoOpClobberize::operator()): 187 (JSC::DFG::CheckClobberize::operator()): 188 (JSC::DFG::ReadMethodClobberize::ReadMethodClobberize): 189 (JSC::DFG::ReadMethodClobberize::operator()): 190 (JSC::DFG::WriteMethodClobberize::WriteMethodClobberize): 191 (JSC::DFG::WriteMethodClobberize::operator()): 192 (JSC::DFG::DefMethodClobberize::DefMethodClobberize): 193 (JSC::DFG::DefMethodClobberize::operator()): 194 * dfg/DFGDCEPhase.cpp: 195 (JSC::DFG::DCEPhase::run): 196 (JSC::DFG::DCEPhase::fixupBlock): 197 * dfg/DFGGraph.cpp: 198 (JSC::DFG::Graph::getBlocksInPreOrder): 199 (JSC::DFG::Graph::getBlocksInPostOrder): 200 (JSC::DFG::Graph::addForDepthFirstSort): Deleted. 201 (JSC::DFG::Graph::getBlocksInDepthFirstOrder): Deleted. 202 * dfg/DFGGraph.h: 203 * dfg/DFGHeapLocation.cpp: Added. 204 (JSC::DFG::HeapLocation::dump): 205 (WTF::printInternal): 206 * dfg/DFGHeapLocation.h: Added. 207 (JSC::DFG::HeapLocation::HeapLocation): 208 (JSC::DFG::HeapLocation::operator!): 209 (JSC::DFG::HeapLocation::kind): 210 (JSC::DFG::HeapLocation::heap): 211 (JSC::DFG::HeapLocation::base): 212 (JSC::DFG::HeapLocation::index): 213 (JSC::DFG::HeapLocation::hash): 214 (JSC::DFG::HeapLocation::operator==): 215 (JSC::DFG::HeapLocation::isHashTableDeletedValue): 216 (JSC::DFG::HeapLocationHash::hash): 217 (JSC::DFG::HeapLocationHash::equal): 218 * dfg/DFGLICMPhase.cpp: 219 (JSC::DFG::LICMPhase::run): 220 * dfg/DFGNode.h: 221 (JSC::DFG::Node::replaceWith): 222 (JSC::DFG::Node::convertToPhantomUnchecked): Deleted. 223 * dfg/DFGPlan.cpp: 224 (JSC::DFG::Plan::compileInThreadImpl): 225 * dfg/DFGPureValue.cpp: Added. 226 (JSC::DFG::PureValue::dump): 227 * dfg/DFGPureValue.h: Added. 228 (JSC::DFG::PureValue::PureValue): 229 (JSC::DFG::PureValue::operator!): 230 (JSC::DFG::PureValue::op): 231 (JSC::DFG::PureValue::children): 232 (JSC::DFG::PureValue::info): 233 (JSC::DFG::PureValue::hash): 234 (JSC::DFG::PureValue::operator==): 235 (JSC::DFG::PureValue::isHashTableDeletedValue): 236 (JSC::DFG::PureValueHash::hash): 237 (JSC::DFG::PureValueHash::equal): 238 * dfg/DFGSSAConversionPhase.cpp: 239 (JSC::DFG::SSAConversionPhase::run): 240 * ftl/FTLLowerDFGToLLVM.cpp: 241 (JSC::FTL::LowerDFGToLLVM::lower): 242 243 2014-07-13 Filip Pizlo <fpizlo@apple.com> 244 245 Unreviewed, revert unintended change in r171051. 246 247 * dfg/DFGCSEPhase.cpp: 248 249 2014-07-08 Filip Pizlo <fpizlo@apple.com> 250 251 [ftlopt] Move Flush(SetLocal) store elimination to StrengthReductionPhase 252 https://bugs.webkit.org/show_bug.cgi?id=134739 253 254 Reviewed by Mark Hahnenberg. 255 256 I'm going to streamline CSE around clobberize() as part of 257 https://bugs.webkit.org/show_bug.cgi?id=134677, and so Flush(SetLocal) store 258 elimination wouldn't belong in CSE anymore. It doesn't quite belong anywhere, which 259 means that it belongs in StrengthReductionPhase, since that's intended to be our 260 dumping ground. 261 262 To do this I had to add some missing smarts to clobberize(). Previously clobberize() 263 could play a bit loose with reads of Variables because it wasn't used for store 264 elimination. The main client of read() was LICM, but it would only use it to 265 determine hoistability and anything that did a write() was not hoistable - so, we had 266 benign (but still wrong) missing read() calls in places that did write()s. This fixes 267 a bunch of those cases. 268 269 * dfg/DFGCSEPhase.cpp: 270 (JSC::DFG::CSEPhase::performNodeCSE): 271 (JSC::DFG::CSEPhase::setLocalStoreElimination): Deleted. 272 * dfg/DFGClobberize.cpp: 273 (JSC::DFG::accessesOverlap): 274 * dfg/DFGClobberize.h: 275 (JSC::DFG::clobberize): Make clobberize() smart enough for detecting when this store elimination would be sound. 276 * dfg/DFGStrengthReductionPhase.cpp: 277 (JSC::DFG::StrengthReductionPhase::handleNode): Implement the store elimination in terms of clobberize(). 278 279 2014-07-08 Filip Pizlo <fpizlo@apple.com> 280 281 [ftlopt] Phantom simplification should be in its own phase 282 https://bugs.webkit.org/show_bug.cgi?id=134742 283 284 Reviewed by Geoffrey Garen. 285 286 This moves Phantom simplification out of CSE, which greatly simplifies CSE and gives it 287 more focus. Also this finally adds a phase that removes empty Phantoms. We sort of had 288 this in CPSRethreading, but that phase runs too infrequently and doesn't run at all for 289 SSA. 290 291 * CMakeLists.txt: 292 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 293 * JavaScriptCore.xcodeproj/project.pbxproj: 294 * dfg/DFGAdjacencyList.h: 295 * dfg/DFGCSEPhase.cpp: 296 (JSC::DFG::CSEPhase::run): 297 (JSC::DFG::CSEPhase::setReplacement): 298 (JSC::DFG::CSEPhase::eliminate): 299 (JSC::DFG::CSEPhase::performNodeCSE): 300 (JSC::DFG::CSEPhase::eliminateIrrelevantPhantomChildren): Deleted. 301 * dfg/DFGPhantomRemovalPhase.cpp: Added. 302 (JSC::DFG::PhantomRemovalPhase::PhantomRemovalPhase): 303 (JSC::DFG::PhantomRemovalPhase::run): 304 (JSC::DFG::performCleanUp): 305 * dfg/DFGPhantomRemovalPhase.h: Added. 306 * dfg/DFGPlan.cpp: 307 (JSC::DFG::Plan::compileInThreadImpl): 308 309 2014-07-08 Filip Pizlo <fpizlo@apple.com> 310 311 [ftlopt] Get rid of Node::misc by moving the fields out of the union so that you can use replacement and owner simultaneously 312 https://bugs.webkit.org/show_bug.cgi?id=134730 313 314 Reviewed by Mark Lam. 315 316 This will allow for a better GCSE implementation. 317 318 * dfg/DFGCPSRethreadingPhase.cpp: 319 (JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor): 320 * dfg/DFGCSEPhase.cpp: 321 (JSC::DFG::CSEPhase::setReplacement): 322 * dfg/DFGEdgeDominates.h: 323 (JSC::DFG::EdgeDominates::operator()): 324 * dfg/DFGGraph.cpp: 325 (JSC::DFG::Graph::clearReplacements): 326 (JSC::DFG::Graph::initializeNodeOwners): 327 * dfg/DFGGraph.h: 328 (JSC::DFG::Graph::performSubstitutionForEdge): 329 * dfg/DFGLICMPhase.cpp: 330 (JSC::DFG::LICMPhase::attemptHoist): 331 * dfg/DFGNode.h: 332 (JSC::DFG::Node::Node): 333 * dfg/DFGSSAConversionPhase.cpp: 334 (JSC::DFG::SSAConversionPhase::run): 335 336 2014-07-04 Filip Pizlo <fpizlo@apple.com> 337 338 [ftlopt] Infer immutable object properties 339 https://bugs.webkit.org/show_bug.cgi?id=134567 340 341 Reviewed by Mark Hahnenberg. 342 343 This introduces a new way of inferring immutable object properties. A property is said to 344 be immutable if after its creation (i.e. the transition that creates it), we never 345 overwrite it (i.e. replace it) or delete it. Immutability is a property of an "own 346 property" - so if we say that "f" is immutable at "o" then we are implying that "o" has "f" 347 directly and not on a prototype. More specifically, the immutability inference will prove 348 that a property on some structure is immutable. This means that, for example, we may have a 349 structure S1 with property "f" where we claim that "f" at S1 is immutable, but S1 has a 350 transition to S2 that adds a new property "g" and we may claim that "f" at S2 is actually 351 mutable. This is mainly for convenience; it allows us to decouple immutability logic from 352 transition logic. Immutability can be used to constant-fold accesses to objects at 353 DFG-time. The DFG needs to prove the following to constant-fold the access: 354 355 - The base of the access must be a constant object pointer. We prove that a property at a 356 structure is immutable, but that says nothing of its value; each actual instance of that 357 property may have a different value. So, a constant object pointer is needed to get an 358 actual constant instance of the immutable value. 359 360 - A check (or watchpoint) must have been emitted proving that the object has a structure 361 that allows loading the property in question. 362 363 - The replacement watchpoint set of the property in the structure that we've proven the 364 object to have is still valid and we add a watchpoint to it lazily. The replacement 365 watchpoint set is the key new mechanism that this change adds. It's possible that we have 366 proven that the object has one of many structures, in which case each of those structures 367 needs a valid replacement watchpoint set. 368 369 The replacement watchpoint set is created the first time that any access to the property is 370 cached. A put replace cache will create, and immediately invalidate, the watchpoint set. A 371 get cache will create the watchpoint set and make it start watching. Any non-cached put 372 access will invalidate the watchpoint set if one had been created; the underlying algorithm 373 ensures that checking for the existence of a replacement watchpoint set is very fast in the 374 common case. This algorithm ensures that no cached access needs to ever do any work to 375 invalidate, or check the validity of, any replacement watchpoint sets. It also has some 376 other nice properties: 377 378 - It's very robust in its definition of immutability. The strictest that it will ever be is 379 that for any instance of the object, the property must be written to only once, 380 specifically at the time that the property is created. But it's looser than this in 381 practice. For example, the property may be written to any number of times before we add 382 the final property that the object will have before anyone reads the property; this works 383 since for optimization purposes we only care if we detect immutability on the structure 384 that the object will have when it is most frequently read from, not any previous 385 structure that the object had. Also, we may write to the property any number of times 386 before anyone caches accesses to it. 387 388 - It is mostly orthogonal to structure transitions. No new structures need to be created to 389 track the immutability of a property. Hence, there is no risk from this feature causing 390 more polymorphism. This is different from the previous "specificValue" constant 391 inference, which did cause additional structures to be created and sometimes those 392 structures led to fake polymorphism. This feature does leverage existing transitions to 393 do some of the watchpointing: property deletions don't fire the replacement watchpoint 394 set because that would cause a new structure and so the mandatory structure check would 395 fail. Also, this feature is guaranteed to never kick in for uncacheable dictionaries 396 because those wouldn't allow for cacheable accesses - and it takes a cacheable access for 397 this feature to be enabled. 398 399 - No memory overhead is incurred except when accesses to the property are cached. 400 Dictionary properties will typically have no meta-data for immutability. The number of 401 replacement watchpoint sets we allocate is proportional to the number of inline caches in 402 the program, which is typically must smaller than the number of structures or even the 403 number of objects. 404 405 This inference is far more powerful than the previous "specificValue" inference, so this 406 change also removes all of that code. It's interesting that the amount of code that is 407 changed to remove that feature is almost as big as the amount of code added to support the 408 new inference - and that's if you include the new tests in the tally. Without new tests, 409 it appears that the new feature actually touches less code! 410 411 There is one corner case where the previous "specificValue" inference was more powerful. 412 You can imagine someone creating objects with functions as self properties on those 413 objects, such that each object instance had the same function pointers - essentially, 414 someone might be trying to create a vtable but failing at the whole "one vtable for many 415 instances" concept. The "specificValue" inference would do very well for such programs, 416 because a structure check would be sufficient to prove a constant value for all of the 417 function properties. This new inference will fail because it doesn't track the constant 418 values of constant properties; instead it detects the immutability of otherwise variable 419 properties (in the sense that each instance of the property may have a different value). 420 So, the new inference requires having a particular object instance to actually get the 421 constant value. I think it's OK to lose this antifeature. It took a lot of code to support 422 and was a constant source of grief in our transition logic, and there doesn't appear to be 423 any real evidence that programs benefited from that particular kind of inference since 424 usually it's the singleton prototype instance that has all of the functions. 425 426 This change is a speed-up on everything. date-format-xparb and both SunSpider/raytrace and 427 V8/raytrace seem to be the biggest winners among the macrobenchmarks; they see >5% 428 speed-ups. Many of our microbenchmarks see very large performance improvements, even 80% in 429 one case. 430 431 * bytecode/ComplexGetStatus.cpp: 432 (JSC::ComplexGetStatus::computeFor): 433 * bytecode/GetByIdStatus.cpp: 434 (JSC::GetByIdStatus::computeFromLLInt): 435 (JSC::GetByIdStatus::computeForStubInfo): 436 (JSC::GetByIdStatus::computeFor): 437 * bytecode/GetByIdVariant.cpp: 438 (JSC::GetByIdVariant::GetByIdVariant): 439 (JSC::GetByIdVariant::operator=): 440 (JSC::GetByIdVariant::attemptToMerge): 441 (JSC::GetByIdVariant::dumpInContext): 442 * bytecode/GetByIdVariant.h: 443 (JSC::GetByIdVariant::alternateBase): 444 (JSC::GetByIdVariant::specificValue): Deleted. 445 * bytecode/PutByIdStatus.cpp: 446 (JSC::PutByIdStatus::computeForStubInfo): 447 (JSC::PutByIdStatus::computeFor): 448 * bytecode/PutByIdVariant.cpp: 449 (JSC::PutByIdVariant::operator=): 450 (JSC::PutByIdVariant::setter): 451 (JSC::PutByIdVariant::dumpInContext): 452 * bytecode/PutByIdVariant.h: 453 (JSC::PutByIdVariant::specificValue): Deleted. 454 * bytecode/Watchpoint.cpp: 455 (JSC::WatchpointSet::fireAllSlow): 456 (JSC::WatchpointSet::fireAll): Deleted. 457 * bytecode/Watchpoint.h: 458 (JSC::WatchpointSet::fireAll): 459 * dfg/DFGAbstractInterpreterInlines.h: 460 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 461 * dfg/DFGByteCodeParser.cpp: 462 (JSC::DFG::ByteCodeParser::handleGetByOffset): 463 (JSC::DFG::ByteCodeParser::handleGetById): 464 (JSC::DFG::ByteCodeParser::handlePutById): 465 (JSC::DFG::ByteCodeParser::parseBlock): 466 * dfg/DFGConstantFoldingPhase.cpp: 467 (JSC::DFG::ConstantFoldingPhase::emitGetByOffset): 468 * dfg/DFGFixupPhase.cpp: 469 (JSC::DFG::FixupPhase::isStringPrototypeMethodSane): 470 (JSC::DFG::FixupPhase::canOptimizeStringObjectAccess): 471 * dfg/DFGGraph.cpp: 472 (JSC::DFG::Graph::tryGetConstantProperty): 473 (JSC::DFG::Graph::visitChildren): 474 * dfg/DFGGraph.h: 475 * dfg/DFGWatchableStructureWatchingPhase.cpp: 476 (JSC::DFG::WatchableStructureWatchingPhase::run): 477 * ftl/FTLLowerDFGToLLVM.cpp: 478 (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset): 479 * jit/JITOperations.cpp: 480 * jit/Repatch.cpp: 481 (JSC::repatchByIdSelfAccess): 482 (JSC::generateByIdStub): 483 (JSC::tryCacheGetByID): 484 (JSC::tryCachePutByID): 485 (JSC::tryBuildPutByIdList): 486 * llint/LLIntSlowPaths.cpp: 487 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 488 (JSC::LLInt::putToScopeCommon): 489 * runtime/CommonSlowPaths.h: 490 (JSC::CommonSlowPaths::tryCachePutToScopeGlobal): 491 * runtime/IntendedStructureChain.cpp: 492 (JSC::IntendedStructureChain::mayInterceptStoreTo): 493 * runtime/JSCJSValue.cpp: 494 (JSC::JSValue::putToPrimitive): 495 * runtime/JSGlobalObject.cpp: 496 (JSC::JSGlobalObject::reset): 497 * runtime/JSObject.cpp: 498 (JSC::JSObject::put): 499 (JSC::JSObject::putDirectNonIndexAccessor): 500 (JSC::JSObject::deleteProperty): 501 (JSC::JSObject::defaultValue): 502 (JSC::getCallableObjectSlow): Deleted. 503 (JSC::JSObject::getPropertySpecificValue): Deleted. 504 * runtime/JSObject.h: 505 (JSC::JSObject::getDirect): 506 (JSC::JSObject::getDirectOffset): 507 (JSC::JSObject::inlineGetOwnPropertySlot): 508 (JSC::JSObject::putDirectInternal): 509 (JSC::JSObject::putOwnDataProperty): 510 (JSC::JSObject::putDirect): 511 (JSC::JSObject::putDirectWithoutTransition): 512 (JSC::getCallableObject): Deleted. 513 * runtime/JSScope.cpp: 514 (JSC::abstractAccess): 515 * runtime/PropertyMapHashTable.h: 516 (JSC::PropertyMapEntry::PropertyMapEntry): 517 (JSC::PropertyTable::copy): 518 * runtime/PropertyTable.cpp: 519 (JSC::PropertyTable::clone): 520 (JSC::PropertyTable::PropertyTable): 521 (JSC::PropertyTable::visitChildren): Deleted. 522 * runtime/Structure.cpp: 523 (JSC::Structure::Structure): 524 (JSC::Structure::materializePropertyMap): 525 (JSC::Structure::addPropertyTransitionToExistingStructureImpl): 526 (JSC::Structure::addPropertyTransitionToExistingStructure): 527 (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently): 528 (JSC::Structure::addPropertyTransition): 529 (JSC::Structure::changePrototypeTransition): 530 (JSC::Structure::attributeChangeTransition): 531 (JSC::Structure::toDictionaryTransition): 532 (JSC::Structure::preventExtensionsTransition): 533 (JSC::Structure::takePropertyTableOrCloneIfPinned): 534 (JSC::Structure::nonPropertyTransition): 535 (JSC::Structure::addPropertyWithoutTransition): 536 (JSC::Structure::allocateRareData): 537 (JSC::Structure::ensurePropertyReplacementWatchpointSet): 538 (JSC::Structure::startWatchingPropertyForReplacements): 539 (JSC::Structure::didCachePropertyReplacement): 540 (JSC::Structure::startWatchingInternalProperties): 541 (JSC::Structure::copyPropertyTable): 542 (JSC::Structure::copyPropertyTableForPinning): 543 (JSC::Structure::getConcurrently): 544 (JSC::Structure::get): 545 (JSC::Structure::add): 546 (JSC::Structure::visitChildren): 547 (JSC::Structure::prototypeChainMayInterceptStoreTo): 548 (JSC::Structure::dump): 549 (JSC::Structure::despecifyDictionaryFunction): Deleted. 550 (JSC::Structure::despecifyFunctionTransition): Deleted. 551 (JSC::Structure::despecifyFunction): Deleted. 552 (JSC::Structure::despecifyAllFunctions): Deleted. 553 (JSC::Structure::putSpecificValue): Deleted. 554 * runtime/Structure.h: 555 (JSC::Structure::startWatchingPropertyForReplacements): 556 (JSC::Structure::startWatchingInternalPropertiesIfNecessary): 557 (JSC::Structure::startWatchingInternalPropertiesIfNecessaryForEntireChain): 558 (JSC::Structure::transitionDidInvolveSpecificValue): Deleted. 559 (JSC::Structure::disableSpecificFunctionTracking): Deleted. 560 * runtime/StructureInlines.h: 561 (JSC::Structure::getConcurrently): 562 (JSC::Structure::didReplaceProperty): 563 (JSC::Structure::propertyReplacementWatchpointSet): 564 * runtime/StructureRareData.cpp: 565 (JSC::StructureRareData::destroy): 566 * runtime/StructureRareData.h: 567 * tests/stress/infer-constant-global-property.js: Added. 568 (foo.Math.sin): 569 (foo): 570 * tests/stress/infer-constant-property.js: Added. 571 (foo): 572 * tests/stress/jit-cache-poly-replace-then-cache-get-and-fold-then-invalidate.js: Added. 573 (foo): 574 (bar): 575 * tests/stress/jit-cache-replace-then-cache-get-and-fold-then-invalidate.js: Added. 576 (foo): 577 (bar): 578 * tests/stress/jit-put-to-scope-global-cache-watchpoint-invalidate.js: Added. 579 (foo): 580 (bar): 581 * tests/stress/llint-cache-replace-then-cache-get-and-fold-then-invalidate.js: Added. 582 (foo): 583 (bar): 584 * tests/stress/llint-put-to-scope-global-cache-watchpoint-invalidate.js: Added. 585 (foo): 586 (bar): 587 * tests/stress/repeat-put-to-scope-global-with-same-value-watchpoint-invalidate.js: Added. 588 (foo): 589 (bar): 590 591 2014-07-03 Saam Barati <sbarati@apple.com> 592 593 Add more coverage for the profile_types_with_high_fidelity op code. 594 https://bugs.webkit.org/show_bug.cgi?id=134616 595 596 Reviewed by Filip Pizlo. 597 598 More operations are now being recorded by the profile_types_with_high_fidelity 599 opcode. Specifically: function parameters, function return values, 600 function 'this' value, get_by_id, get_by_value, resolve nodes, function return 601 values at the call site. Added more flags to the profile_types_with_high_fidelity 602 opcode so more focused tasks can take place when the instruction is 603 being linked in CodeBlock. Re-worked the type profiler to search 604 through character offset ranges when asked for the type of an expression 605 at a given offset. Removed redundant calls to Structure::toStructureShape 606 in HighFidelityLog and TypeSet by caching calls based on StructureID. 607 608 * bytecode/BytecodeList.json: 609 * bytecode/BytecodeUseDef.h: 610 (JSC::computeUsesForBytecodeOffset): 611 (JSC::computeDefsForBytecodeOffset): 612 * bytecode/CodeBlock.cpp: 613 (JSC::CodeBlock::CodeBlock): 614 (JSC::CodeBlock::finalizeUnconditionally): 615 (JSC::CodeBlock::scopeDependentProfile): 616 * bytecode/CodeBlock.h: 617 (JSC::CodeBlock::returnStatementTypeSet): 618 * bytecode/TypeLocation.h: 619 * bytecode/UnlinkedCodeBlock.cpp: 620 (JSC::UnlinkedCodeBlock::highFidelityTypeProfileExpressionInfoForBytecodeOffset): 621 (JSC::UnlinkedCodeBlock::addHighFidelityTypeProfileExpressionInfo): 622 * bytecode/UnlinkedCodeBlock.h: 623 * bytecompiler/BytecodeGenerator.cpp: 624 (JSC::BytecodeGenerator::emitMove): 625 (JSC::BytecodeGenerator::emitProfileTypesWithHighFidelity): 626 (JSC::BytecodeGenerator::emitGetFromScopeWithProfile): 627 (JSC::BytecodeGenerator::emitPutToScope): 628 (JSC::BytecodeGenerator::emitPutToScopeWithProfile): 629 (JSC::BytecodeGenerator::emitPutById): 630 (JSC::BytecodeGenerator::emitPutByVal): 631 * bytecompiler/BytecodeGenerator.h: 632 (JSC::BytecodeGenerator::emitHighFidelityTypeProfilingExpressionInfo): 633 * bytecompiler/NodesCodegen.cpp: 634 (JSC::ResolveNode::emitBytecode): 635 (JSC::BracketAccessorNode::emitBytecode): 636 (JSC::DotAccessorNode::emitBytecode): 637 (JSC::FunctionCallValueNode::emitBytecode): 638 (JSC::FunctionCallResolveNode::emitBytecode): 639 (JSC::FunctionCallBracketNode::emitBytecode): 640 (JSC::FunctionCallDotNode::emitBytecode): 641 (JSC::CallFunctionCallDotNode::emitBytecode): 642 (JSC::ApplyFunctionCallDotNode::emitBytecode): 643 (JSC::PostfixNode::emitResolve): 644 (JSC::PostfixNode::emitBracket): 645 (JSC::PostfixNode::emitDot): 646 (JSC::PrefixNode::emitResolve): 647 (JSC::PrefixNode::emitBracket): 648 (JSC::PrefixNode::emitDot): 649 (JSC::ReadModifyResolveNode::emitBytecode): 650 (JSC::AssignResolveNode::emitBytecode): 651 (JSC::AssignDotNode::emitBytecode): 652 (JSC::ReadModifyDotNode::emitBytecode): 653 (JSC::AssignBracketNode::emitBytecode): 654 (JSC::ReadModifyBracketNode::emitBytecode): 655 (JSC::ReturnNode::emitBytecode): 656 (JSC::FunctionBodyNode::emitBytecode): 657 * inspector/agents/InspectorRuntimeAgent.cpp: 658 (Inspector::InspectorRuntimeAgent::getRuntimeTypeForVariableAtOffset): 659 (Inspector::InspectorRuntimeAgent::getRuntimeTypeForVariableInTextRange): Deleted. 660 * inspector/agents/InspectorRuntimeAgent.h: 661 * inspector/protocol/Runtime.json: 662 * llint/LLIntSlowPaths.cpp: 663 (JSC::LLInt::getFromScopeCommon): 664 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 665 * llint/LLIntSlowPaths.h: 666 * llint/LowLevelInterpreter.asm: 667 * runtime/HighFidelityLog.cpp: 668 (JSC::HighFidelityLog::processHighFidelityLog): 669 (JSC::HighFidelityLog::actuallyProcessLogThreadFunction): 670 (JSC::HighFidelityLog::recordTypeInformationForLocation): Deleted. 671 * runtime/HighFidelityLog.h: 672 (JSC::HighFidelityLog::recordTypeInformationForLocation): 673 * runtime/HighFidelityTypeProfiler.cpp: 674 (JSC::HighFidelityTypeProfiler::getTypesForVariableInAtOffset): 675 (JSC::HighFidelityTypeProfiler::getGlobalTypesForVariableAtOffset): 676 (JSC::HighFidelityTypeProfiler::getLocalTypesForVariableAtOffset): 677 (JSC::HighFidelityTypeProfiler::insertNewLocation): 678 (JSC::HighFidelityTypeProfiler::findLocation): 679 (JSC::HighFidelityTypeProfiler::getTypesForVariableInRange): Deleted. 680 (JSC::HighFidelityTypeProfiler::getGlobalTypesForVariableInRange): Deleted. 681 (JSC::HighFidelityTypeProfiler::getLocalTypesForVariableInRange): Deleted. 682 (JSC::HighFidelityTypeProfiler::getLocationBasedHash): Deleted. 683 * runtime/HighFidelityTypeProfiler.h: 684 (JSC::LocationKey::LocationKey): Deleted. 685 (JSC::LocationKey::hash): Deleted. 686 (JSC::LocationKey::operator==): Deleted. 687 * runtime/Structure.cpp: 688 (JSC::Structure::toStructureShape): 689 * runtime/Structure.h: 690 * runtime/TypeSet.cpp: 691 (JSC::TypeSet::TypeSet): 692 (JSC::TypeSet::addTypeForValue): 693 (JSC::TypeSet::seenTypes): 694 (JSC::TypeSet::removeDuplicatesInStructureHistory): Deleted. 695 * runtime/TypeSet.h: 696 (JSC::StructureShape::setConstructorName): 697 * runtime/VM.cpp: 698 (JSC::VM::getTypesForVariableAtOffset): 699 (JSC::VM::dumpHighFidelityProfilingTypes): 700 (JSC::VM::getTypesForVariableInRange): Deleted. 701 * runtime/VM.h: 702 703 2014-07-04 Filip Pizlo <fpizlo@apple.com> 704 705 [ftlopt][REGRESSION] debug tests fail because PutByIdDirect is now implemented in terms of In 706 https://bugs.webkit.org/show_bug.cgi?id=134642 707 708 Rubber stamped by Andreas Kling. 709 710 * ftl/FTLLowerDFGToLLVM.cpp: 711 (JSC::FTL::LowerDFGToLLVM::compileNode): 712 713 2014-07-01 Filip Pizlo <fpizlo@apple.com> 714 715 [ftlopt] Allocate a new GetterSetter if we change the value of any of its entries other than when they were previously null, so that if we constant-infer an accessor slot then we immediately get the function constant for free 716 https://bugs.webkit.org/show_bug.cgi?id=134518 717 718 Reviewed by Mark Hahnenberg. 719 720 This has no real effect right now, particularly since almost all uses of 721 setSetter/setGetter were already allocating a branch new GetterSetter. But once we start 722 doing more aggressive constant property inference, this change will allow us to remove 723 all runtime checks from getter/setter calls. 724 725 * runtime/GetterSetter.cpp: 726 (JSC::GetterSetter::withGetter): 727 (JSC::GetterSetter::withSetter): 728 * runtime/GetterSetter.h: 729 (JSC::GetterSetter::setGetter): 730 (JSC::GetterSetter::setSetter): 731 * runtime/JSObject.cpp: 732 (JSC::JSObject::defineOwnNonIndexProperty): 733 734 2014-07-02 Filip Pizlo <fpizlo@apple.com> 735 736 [ftlopt] Rename notifyTransitionFromThisStructure to didTransitionFromThisStructure 737 738 Rubber stamped by Mark Hahnenberg. 739 740 * runtime/Structure.cpp: 741 (JSC::Structure::Structure): 742 (JSC::Structure::nonPropertyTransition): 743 (JSC::Structure::didTransitionFromThisStructure): 744 (JSC::Structure::notifyTransitionFromThisStructure): Deleted. 745 * runtime/Structure.h: 746 747 2014-07-02 Filip Pizlo <fpizlo@apple.com> 748 749 [ftlopt] Remove the functionality for cloning StructureRareData since we never do that anymore. 750 751 Rubber stamped by Mark Hahnenberg. 752 753 * runtime/Structure.cpp: 754 (JSC::Structure::Structure): 755 (JSC::Structure::cloneRareDataFrom): Deleted. 756 * runtime/Structure.h: 757 * runtime/StructureRareData.cpp: 758 (JSC::StructureRareData::clone): Deleted. 759 (JSC::StructureRareData::StructureRareData): Deleted. 760 * runtime/StructureRareData.h: 761 (JSC::StructureRareData::needsCloning): Deleted. 762 763 2014-07-01 Mark Lam <mark.lam@apple.com> 764 765 [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope. 766 <https://webkit.org/b/134420> 767 768 Reviewed by Geoffrey Garen. 769 770 Previously, DebuggerCallFrame::scope() returns a JSActivation (and relevant 771 peers) which the WebInspector will use to introspect CallFrame variables. 772 Instead, we should be returning a DebuggerScope as an abstraction layer that 773 provides the introspection functionality that the WebInspector needs. This 774 is the first step towards not forcing every frame to have a JSActivation 775 object just because the debugger is enabled. 776 777 1. Instantiate the debuggerScopeStructure as a member of the JSGlobalObject 778 instead of the VM. This allows JSObject::globalObject() to be able to 779 return the global object for the DebuggerScope. 780 781 2. On the DebuggerScope's life-cycle management: 782 783 The DebuggerCallFrame is designed to be "valid" only during a debugging session 784 (while the debugger is broken) through the use of a DebuggerCallFrameScope in 785 Debugger::pauseIfNeeded(). Once the debugger resumes from the break, the 786 DebuggerCallFrameScope destructs, and the DebuggerCallFrame will be invalidated. 787 We can't guarantee (from this code alone) that the Inspector code isn't still 788 holding a ref to the DebuggerCallFrame (though they shouldn't), but by contract, 789 the frame will be invalidated, and any attempt to query it will return null values. 790 This is pre-existing behavior. 791 792 Now, we're adding the DebuggerScope into the picture. While a single debugger 793 pause session is in progress, the Inspector may request the scope from the 794 DebuggerCallFrame. While the DebuggerCallFrame is still valid, we want 795 DebuggerCallFrame::scope() to always return the same DebuggerScope object. 796 This is why we hold on to the DebuggerScope with a strong ref. 797 798 If we use a weak ref instead, the following cooky behavior can manifest: 799 1. The Inspector calls Debugger::scope() to get the top scope. 800 2. The Inspector iterates down the scope chain and is now only holding a 801 reference to a parent scope. It is no longer referencing the top scope. 802 3. A GC occurs, and the DebuggerCallFrame's weak m_scope ref to the top scope 803 gets cleared. 804 4. The Inspector calls DebuggerCallFrame::scope() to get the top scope again but gets 805 a different DebuggerScope instance. 806 5. The Inspector iterates down the scope chain but never sees the parent scope 807 instance that retained a ref to in step 2 above. This is because when iterating 808 this new DebuggerScope instance (which has no knowledge of the previous parent 809 DebuggerScope instance), a new DebuggerScope instance will get created for the 810 same parent scope. 811 812 Since the DebuggerScope is a JSObject, it's liveness is determined by its reachability. 813 However, it's "validity" is determined by the life-cycle of its owner DebuggerCallFrame. 814 When the owner DebuggerCallFrame gets invalidated, its debugger scope chain (if 815 instantiated) will also get invalidated. This is why we need the 816 DebuggerScope::invalidateChain() method. The Inspector should not be using the 817 DebuggerScope instance after its owner DebuggerCallFrame is invalidated. If it does, 818 those methods will do nothing or returned a failed status. 819 820 * debugger/Debugger.h: 821 * debugger/DebuggerCallFrame.cpp: 822 (JSC::DebuggerCallFrame::scope): 823 (JSC::DebuggerCallFrame::evaluate): 824 (JSC::DebuggerCallFrame::invalidate): 825 (JSC::DebuggerCallFrame::vm): 826 (JSC::DebuggerCallFrame::lexicalGlobalObject): 827 * debugger/DebuggerCallFrame.h: 828 * debugger/DebuggerScope.cpp: 829 (JSC::DebuggerScope::DebuggerScope): 830 (JSC::DebuggerScope::finishCreation): 831 (JSC::DebuggerScope::visitChildren): 832 (JSC::DebuggerScope::className): 833 (JSC::DebuggerScope::getOwnPropertySlot): 834 (JSC::DebuggerScope::put): 835 (JSC::DebuggerScope::deleteProperty): 836 (JSC::DebuggerScope::getOwnPropertyNames): 837 (JSC::DebuggerScope::defineOwnProperty): 838 (JSC::DebuggerScope::next): 839 (JSC::DebuggerScope::invalidateChain): 840 (JSC::DebuggerScope::isWithScope): 841 (JSC::DebuggerScope::isGlobalScope): 842 (JSC::DebuggerScope::isFunctionScope): 843 * debugger/DebuggerScope.h: 844 (JSC::DebuggerScope::create): 845 (JSC::DebuggerScope::Iterator::Iterator): 846 (JSC::DebuggerScope::Iterator::get): 847 (JSC::DebuggerScope::Iterator::operator++): 848 (JSC::DebuggerScope::Iterator::operator==): 849 (JSC::DebuggerScope::Iterator::operator!=): 850 (JSC::DebuggerScope::isValid): 851 (JSC::DebuggerScope::jsScope): 852 (JSC::DebuggerScope::begin): 853 (JSC::DebuggerScope::end): 854 * inspector/JSJavaScriptCallFrame.cpp: 855 (Inspector::JSJavaScriptCallFrame::scopeType): 856 (Inspector::JSJavaScriptCallFrame::scopeChain): 857 * inspector/JavaScriptCallFrame.h: 858 (Inspector::JavaScriptCallFrame::scopeChain): 859 * inspector/ScriptDebugServer.cpp: 860 * runtime/JSGlobalObject.cpp: 861 (JSC::JSGlobalObject::reset): 862 (JSC::JSGlobalObject::visitChildren): 863 * runtime/JSGlobalObject.h: 864 (JSC::JSGlobalObject::debuggerScopeStructure): 865 * runtime/JSObject.h: 866 (JSC::JSObject::isWithScope): 867 * runtime/JSScope.h: 868 * runtime/VM.cpp: 869 (JSC::VM::VM): 870 * runtime/VM.h: 871 872 2014-07-01 Filip Pizlo <fpizlo@apple.com> 873 874 [ftlopt] DFG bytecode parser should turn PutById with nothing but a Setter stub as stuff+handleCall, and handleCall should be allowed to inline if it wants to 875 https://bugs.webkit.org/show_bug.cgi?id=130756 876 877 Reviewed by Oliver Hunt. 878 879 The enables exposing the call to setters in the DFG, and then inlining it. Previously we 880 already supproted inlined-cached calls to setters from within put_by_id inline caches, 881 and the DFG could certainly emit such IC's. Now, if an IC had a setter call, then the DFG 882 will either emit the GetGetterSetterByOffset/GetSetter/Call combo, or it will do one 883 better and inline the call. 884 885 A lot of the core functionality was already available from the previous work to inline 886 getters. So, there are some refactorings in this patch that move preexisting 887 functionality around. For example, the work to figure out how the DFG should go about 888 getting to what we call the "loaded value" - i.e. the GetterSetter object reference in 889 the case of accessors - is now shared in ComplexGetStatus, and both GetByIdStatus and 890 PutByIdStatus use it. This means that we can keep the safety checks common. This patch 891 also does additional refactorings in DFG::ByteCodeParser so that we can continue to reuse 892 handleCall() for all of the various kinds of calls we can now emit. 893 894 83% speed-up on getter-richards, 2% speed-up on box2d. 895 896 * CMakeLists.txt: 897 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 898 * JavaScriptCore.xcodeproj/project.pbxproj: 899 * bytecode/ComplexGetStatus.cpp: Added. 900 (JSC::ComplexGetStatus::computeFor): 901 * bytecode/ComplexGetStatus.h: Added. 902 (JSC::ComplexGetStatus::ComplexGetStatus): 903 (JSC::ComplexGetStatus::skip): 904 (JSC::ComplexGetStatus::takesSlowPath): 905 (JSC::ComplexGetStatus::kind): 906 (JSC::ComplexGetStatus::attributes): 907 (JSC::ComplexGetStatus::specificValue): 908 (JSC::ComplexGetStatus::offset): 909 (JSC::ComplexGetStatus::chain): 910 * bytecode/GetByIdStatus.cpp: 911 (JSC::GetByIdStatus::computeForStubInfo): 912 * bytecode/GetByIdVariant.cpp: 913 (JSC::GetByIdVariant::GetByIdVariant): 914 * bytecode/PolymorphicPutByIdList.h: 915 (JSC::PutByIdAccess::PutByIdAccess): 916 (JSC::PutByIdAccess::setter): 917 (JSC::PutByIdAccess::structure): 918 (JSC::PutByIdAccess::chainCount): 919 * bytecode/PutByIdStatus.cpp: 920 (JSC::PutByIdStatus::computeFromLLInt): 921 (JSC::PutByIdStatus::computeFor): 922 (JSC::PutByIdStatus::computeForStubInfo): 923 (JSC::PutByIdStatus::makesCalls): 924 * bytecode/PutByIdStatus.h: 925 (JSC::PutByIdStatus::makesCalls): Deleted. 926 * bytecode/PutByIdVariant.cpp: 927 (JSC::PutByIdVariant::PutByIdVariant): 928 (JSC::PutByIdVariant::operator=): 929 (JSC::PutByIdVariant::replace): 930 (JSC::PutByIdVariant::transition): 931 (JSC::PutByIdVariant::setter): 932 (JSC::PutByIdVariant::writesStructures): 933 (JSC::PutByIdVariant::reallocatesStorage): 934 (JSC::PutByIdVariant::makesCalls): 935 (JSC::PutByIdVariant::dumpInContext): 936 * bytecode/PutByIdVariant.h: 937 (JSC::PutByIdVariant::PutByIdVariant): 938 (JSC::PutByIdVariant::structure): 939 (JSC::PutByIdVariant::oldStructure): 940 (JSC::PutByIdVariant::alternateBase): 941 (JSC::PutByIdVariant::specificValue): 942 (JSC::PutByIdVariant::callLinkStatus): 943 (JSC::PutByIdVariant::replace): Deleted. 944 (JSC::PutByIdVariant::transition): Deleted. 945 * dfg/DFGByteCodeParser.cpp: 946 (JSC::DFG::ByteCodeParser::addCallWithoutSettingResult): 947 (JSC::DFG::ByteCodeParser::addCall): 948 (JSC::DFG::ByteCodeParser::handleCall): 949 (JSC::DFG::ByteCodeParser::handleInlining): 950 (JSC::DFG::ByteCodeParser::handleGetById): 951 (JSC::DFG::ByteCodeParser::handlePutById): 952 (JSC::DFG::ByteCodeParser::parseBlock): 953 * jit/Repatch.cpp: 954 (JSC::tryCachePutByID): 955 (JSC::tryBuildPutByIdList): 956 * runtime/IntendedStructureChain.cpp: 957 (JSC::IntendedStructureChain::takesSlowPathInDFGForImpureProperty): 958 * runtime/IntendedStructureChain.h: 959 * tests/stress/exit-from-setter.js: Added. 960 * tests/stress/poly-chain-setter.js: Added. 961 (Cons): 962 (foo): 963 (test): 964 * tests/stress/poly-chain-then-setter.js: Added. 965 (Cons1): 966 (Cons2): 967 (foo): 968 (test): 969 * tests/stress/poly-setter-combo.js: Added. 970 (Cons1): 971 (Cons2): 972 (foo): 973 (test): 974 (.test): 975 * tests/stress/poly-setter-then-self.js: Added. 976 (foo): 977 (test): 978 (.test): 979 * tests/stress/weird-setter-counter.js: Added. 980 (foo): 981 (test): 982 * tests/stress/weird-setter-counter-syntactic.js: Added. 983 (foo): 984 (test): 985 986 2014-07-01 Matthew Mirman <mmirman@apple.com> 987 988 Added an implementation of the "in" check to FTL. 989 https://bugs.webkit.org/show_bug.cgi?id=134508 990 991 Reviewed by Filip Pizlo. 992 993 * ftl/FTLCapabilities.cpp: enabled compilation for "in" 994 (JSC::FTL::canCompile): ditto 995 * ftl/FTLCompile.cpp: 996 (JSC::FTL::generateCheckInICFastPath): added. 997 (JSC::FTL::fixFunctionBasedOnStackMaps): added case for CheckIn descriptors. 998 * ftl/FTLInlineCacheDescriptor.h: 999 (JSC::FTL::CheckInGenerator::CheckInGenerator): added. 1000 (JSC::FTL::CheckInDescriptor::CheckInDescriptor): added. 1001 * ftl/FTLInlineCacheSize.cpp: 1002 (JSC::FTL::sizeOfCheckIn): added. Currently larger than necessary. 1003 * ftl/FTLInlineCacheSize.h: ditto 1004 * ftl/FTLIntrinsicRepository.h: Added function type for operationInGeneric 1005 * ftl/FTLLowerDFGToLLVM.cpp: 1006 (JSC::FTL::LowerDFGToLLVM::compileNode): added case for In. 1007 (JSC::FTL::LowerDFGToLLVM::compileIn): added. 1008 * ftl/FTLSlowPathCall.cpp: Added a callOperation for operationIn 1009 (JSC::FTL::callOperation): ditto 1010 * ftl/FTLSlowPathCall.h: ditto 1011 * ftl/FTLState.h: Added a vector to hold CheckIn descriptors. 1012 * jit/JITOperations.h: made operationIns internal. 1013 * tests/stress/ftl-checkin.js: Added. 1014 * tests/stress/ftl-checkin-variable.js: Added. 1015 1016 2014-06-30 Mark Hahnenberg <mhahnenberg@apple.com> 1017 1018 CodeBlock::stronglyVisitWeakReferences should mark DFG::CommonData::weakStructureReferences 1019 https://bugs.webkit.org/show_bug.cgi?id=134455 1020 1021 Reviewed by Geoffrey Garen. 1022 1023 Otherwise we get hanging pointers which can cause us to die later. 1024 1025 * bytecode/CodeBlock.cpp: 1026 (JSC::CodeBlock::stronglyVisitWeakReferences): 1027 1028 2014-06-27 Filip Pizlo <fpizlo@apple.com> 1029 1030 [ftlopt] Reduce the GC's influence on optimization decisions 1031 https://bugs.webkit.org/show_bug.cgi?id=134427 1032 1033 Reviewed by Oliver Hunt. 1034 1035 This is a slight speed-up on some platforms, that arises from a bunch of fixes that I made 1036 while trying to make the GC keep more structures alive 1037 (https://bugs.webkit.org/show_bug.cgi?id=128072). 1038 1039 The fixes are, roughly: 1040 1041 - If the GC clears an inline cache, then this no longer causes the IC to be forever 1042 polymorphic. 1043 1044 - If we exit in inlined code into a function that tries to OSR enter, then we jettison 1045 sooner. 1046 1047 - Some variables being uninitialized led to rage-recompilations. 1048 1049 This is a pretty strong step in the direction of keeping more Structures alive and not 1050 blowing away code just because a Structure died. But, it seems like there is still a slight 1051 speed-up to be had from blowing away code that references dead Structures. 1052 1053 * bytecode/CodeBlock.cpp: 1054 (JSC::CodeBlock::dumpAssumingJITType): 1055 (JSC::shouldMarkTransition): 1056 (JSC::CodeBlock::propagateTransitions): 1057 (JSC::CodeBlock::determineLiveness): 1058 * bytecode/GetByIdStatus.cpp: 1059 (JSC::GetByIdStatus::computeForStubInfo): 1060 * bytecode/PutByIdStatus.cpp: 1061 (JSC::PutByIdStatus::computeForStubInfo): 1062 * dfg/DFGCapabilities.cpp: 1063 (JSC::DFG::isSupportedForInlining): 1064 (JSC::DFG::mightInlineFunctionForCall): 1065 (JSC::DFG::mightInlineFunctionForClosureCall): 1066 (JSC::DFG::mightInlineFunctionForConstruct): 1067 * dfg/DFGCapabilities.h: 1068 * dfg/DFGCommonData.h: 1069 * dfg/DFGDesiredWeakReferences.cpp: 1070 (JSC::DFG::DesiredWeakReferences::reallyAdd): 1071 * dfg/DFGOSREntry.cpp: 1072 (JSC::DFG::prepareOSREntry): 1073 * dfg/DFGOSRExitCompilerCommon.cpp: 1074 (JSC::DFG::handleExitCounts): 1075 * dfg/DFGOperations.cpp: 1076 * dfg/DFGOperations.h: 1077 * ftl/FTLForOSREntryJITCode.cpp: 1078 (JSC::FTL::ForOSREntryJITCode::ForOSREntryJITCode): These variables being uninitialized is benign in terms of correctness but can sometimes cause rage-recompilations. For some reason it took this patch to reveal this. 1079 * ftl/FTLOSREntry.cpp: 1080 (JSC::FTL::prepareOSREntry): 1081 * runtime/Executable.cpp: 1082 (JSC::ExecutableBase::destroy): 1083 (JSC::NativeExecutable::destroy): 1084 (JSC::ScriptExecutable::ScriptExecutable): 1085 (JSC::ScriptExecutable::destroy): 1086 (JSC::ScriptExecutable::installCode): 1087 (JSC::EvalExecutable::EvalExecutable): 1088 (JSC::ProgramExecutable::ProgramExecutable): 1089 * runtime/Executable.h: 1090 (JSC::ScriptExecutable::setDidTryToEnterInLoop): 1091 (JSC::ScriptExecutable::didTryToEnterInLoop): 1092 (JSC::ScriptExecutable::addressOfDidTryToEnterInLoop): 1093 (JSC::ScriptExecutable::ScriptExecutable): Deleted. 1094 * runtime/StructureInlines.h: 1095 (JSC::Structure::storedPrototypeObject): 1096 (JSC::Structure::storedPrototypeStructure): 1097 1098 2014-06-25 Filip Pizlo <fpizlo@apple.com> 1099 1100 [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint 1101 https://bugs.webkit.org/show_bug.cgi?id=134333 1102 1103 Reviewed by Geoffrey Garen. 1104 1105 This is engineered to provide loads of information to the profiler without incurring any 1106 costs when the profiler is disabled. It's the oldest trick in the book: the thing that 1107 fires the watchpoint doesn't actually create anything to describe the reason why it was 1108 fired; instead it creates a stack-allocated FireDetail subclass instance. Only if the 1109 FireDetail::dump() virtual method is called does anything happen. 1110 1111 Currently we use this to produce very fine-grained data for Structure watchpoints and 1112 some cases of variable watchpoints. For all other situations, the given reason is just a 1113 string constant, by using StringFireDetail. If we find a situation where that string 1114 constant is insufficient to diagnose an issue then we can change it to provide more 1115 fine-grained information. 1116 1117 * JavaScriptCore.xcodeproj/project.pbxproj: 1118 * bytecode/CodeBlock.cpp: 1119 (JSC::CodeBlock::CodeBlock): 1120 (JSC::CodeBlock::jettison): 1121 * bytecode/CodeBlock.h: 1122 * bytecode/CodeBlockJettisoningWatchpoint.cpp: 1123 (JSC::CodeBlockJettisoningWatchpoint::fireInternal): 1124 * bytecode/CodeBlockJettisoningWatchpoint.h: 1125 * bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp: Removed. 1126 * bytecode/ProfiledCodeBlockJettisoningWatchpoint.h: Removed. 1127 * bytecode/StructureStubClearingWatchpoint.cpp: 1128 (JSC::StructureStubClearingWatchpoint::fireInternal): 1129 * bytecode/StructureStubClearingWatchpoint.h: 1130 * bytecode/VariableWatchpointSet.h: 1131 (JSC::VariableWatchpointSet::invalidate): 1132 (JSC::VariableWatchpointSet::finalizeUnconditionally): 1133 * bytecode/VariableWatchpointSetInlines.h: 1134 (JSC::VariableWatchpointSet::notifyWrite): 1135 * bytecode/Watchpoint.cpp: 1136 (JSC::StringFireDetail::dump): 1137 (JSC::WatchpointSet::fireAll): 1138 (JSC::WatchpointSet::fireAllSlow): 1139 (JSC::WatchpointSet::fireAllWatchpoints): 1140 (JSC::InlineWatchpointSet::fireAll): 1141 * bytecode/Watchpoint.h: 1142 (JSC::FireDetail::FireDetail): 1143 (JSC::FireDetail::~FireDetail): 1144 (JSC::StringFireDetail::StringFireDetail): 1145 (JSC::Watchpoint::fire): 1146 (JSC::WatchpointSet::fireAll): 1147 (JSC::WatchpointSet::touch): 1148 (JSC::WatchpointSet::invalidate): 1149 (JSC::InlineWatchpointSet::fireAll): 1150 (JSC::InlineWatchpointSet::touch): 1151 * dfg/DFGCommonData.h: 1152 * dfg/DFGOperations.cpp: 1153 * interpreter/Interpreter.cpp: 1154 (JSC::Interpreter::execute): 1155 * jsc.cpp: 1156 (WTF::Masquerader::create): 1157 * profiler/ProfilerCompilation.cpp: 1158 (JSC::Profiler::Compilation::setJettisonReason): 1159 (JSC::Profiler::Compilation::toJS): 1160 * profiler/ProfilerCompilation.h: 1161 (JSC::Profiler::Compilation::setJettisonReason): Deleted. 1162 * runtime/ArrayBuffer.cpp: 1163 (JSC::ArrayBuffer::transfer): 1164 * runtime/ArrayBufferNeuteringWatchpoint.cpp: 1165 (JSC::ArrayBufferNeuteringWatchpoint::fireAll): 1166 * runtime/ArrayBufferNeuteringWatchpoint.h: 1167 * runtime/CommonIdentifiers.h: 1168 * runtime/CommonSlowPaths.cpp: 1169 (JSC::SLOW_PATH_DECL): 1170 * runtime/Identifier.cpp: 1171 (JSC::Identifier::dump): 1172 * runtime/Identifier.h: 1173 * runtime/JSFunction.cpp: 1174 (JSC::JSFunction::put): 1175 (JSC::JSFunction::defineOwnProperty): 1176 * runtime/JSGlobalObject.cpp: 1177 (JSC::JSGlobalObject::addFunction): 1178 (JSC::JSGlobalObject::haveABadTime): 1179 * runtime/JSSymbolTableObject.cpp: 1180 (JSC::VariableWriteFireDetail::dump): 1181 * runtime/JSSymbolTableObject.h: 1182 (JSC::VariableWriteFireDetail::VariableWriteFireDetail): 1183 (JSC::symbolTablePut): 1184 (JSC::symbolTablePutWithAttributes): 1185 * runtime/PropertyName.h: 1186 (JSC::PropertyName::dump): 1187 * runtime/Structure.cpp: 1188 (JSC::Structure::notifyTransitionFromThisStructure): 1189 * runtime/Structure.h: 1190 (JSC::Structure::notifyTransitionFromThisStructure): Deleted. 1191 * runtime/SymbolTable.cpp: 1192 (JSC::SymbolTableEntry::notifyWriteSlow): 1193 (JSC::SymbolTable::WatchpointCleanup::finalizeUnconditionally): 1194 * runtime/SymbolTable.h: 1195 (JSC::SymbolTableEntry::notifyWrite): 1196 * runtime/VM.cpp: 1197 (JSC::VM::addImpureProperty): 1198 1 1199 2014-08-05 Commit Queue <commit-queue@webkit.org> 2 1200 -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r171660 r172129 322 322 <ClCompile Include="..\bytecode\CodeOrigin.cpp" /> 323 323 <ClCompile Include="..\bytecode\CodeType.cpp" /> 324 <ClCompile Include="..\bytecode\ComplexGetStatus.cpp" /> 324 325 <ClCompile Include="..\bytecode\ConstantStructureCheck.cpp" /> 325 326 <ClCompile Include="..\bytecode\DeferredCompilationCallback.cpp" /> … … 403 404 <ClCompile Include="..\dfg\DFGGraph.cpp" /> 404 405 <ClCompile Include="..\dfg\DFGGraphSafepoint.cpp" /> 406 <ClCompile Include="..\dfg\DFGHeapLocation.cpp" /> 405 407 <ClCompile Include="..\dfg\DFGInPlaceAbstractState.cpp" /> 406 408 <ClCompile Include="..\dfg\DFGIntegerCheckCombiningPhase.cpp" /> … … 432 434 <ClCompile Include="..\dfg\DFGOSRExitJumpPlaceholder.cpp" /> 433 435 <ClCompile Include="..\dfg\DFGOSRExitPreparation.cpp" /> 436 <ClCompile Include="..\dfg\DFGPhantomRemovalPhase.cpp" /> 434 437 <ClCompile Include="..\dfg\DFGPhase.cpp" /> 435 438 <ClCompile Include="..\dfg\DFGPlan.cpp" /> 436 439 <ClCompile Include="..\dfg\DFGPredictionInjectionPhase.cpp" /> 437 440 <ClCompile Include="..\dfg\DFGPredictionPropagationPhase.cpp" /> 441 <ClCompile Include="..\dfg\DFGPureValue.cpp" /> 438 442 <ClCompile Include="..\dfg\DFGResurrectionForValidationPhase.cpp" /> 439 443 <ClCompile Include="..\dfg\DFGSafepoint.cpp" /> … … 909 913 <ClInclude Include="..\bytecode\CodeType.h" /> 910 914 <ClInclude Include="..\bytecode\Comment.h" /> 915 <ClInclude Include="..\bytecode\ComplexGetStatus.h" /> 911 916 <ClInclude Include="..\bytecode\ConstantStructureCheck.h" /> 912 917 <ClInclude Include="..\bytecode\DataFormat.h" /> … … 1024 1029 <ClInclude Include="..\dfg\DFGGraph.h" /> 1025 1030 <ClInclude Include="..\dfg\DFGGraphSafepoint.h" /> 1031 <ClInclude Include="..\dfg\DFGHeapLocation.h" /> 1026 1032 <ClInclude Include="..\dfg\DFGInPlaceAbstractState.h" /> 1027 1033 <ClInclude Include="..\dfg\DFGInsertionSet.h" /> … … 1059 1065 <ClInclude Include="..\dfg\DFGOSRExitJumpPlaceholder.h" /> 1060 1066 <ClInclude Include="..\dfg\DFGOSRExitPreparation.h" /> 1067 <ClInclude Include="..\dfg\DFGPhantomRemovalPhase.h" /> 1061 1068 <ClInclude Include="..\dfg\DFGPhase.h" /> 1062 1069 <ClInclude Include="..\dfg\DFGPlan.h" /> 1063 1070 <ClInclude Include="..\dfg\DFGPredictionInjectionPhase.h" /> 1064 1071 <ClInclude Include="..\dfg\DFGPredictionPropagationPhase.h" /> 1072 <ClInclude Include="..\dfg\DFGPureValue.h" /> 1065 1073 <ClInclude Include="..\dfg\DFGRegisterBank.h" /> 1066 1074 <ClInclude Include="..\dfg\DFGRegisterSet.h" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r171660 r172129 352 352 0F6B1CCA18641DF800845D97 /* ArityCheckFailReturnThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CC818641DF800845D97 /* ArityCheckFailReturnThunks.h */; settings = {ATTRIBUTES = (Private, ); }; }; 353 353 0F6E845A19030BEF00562741 /* DFGVariableAccessData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6E845919030BEF00562741 /* DFGVariableAccessData.cpp */; }; 354 0F6FC750196110A800E1D02D /* ComplexGetStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6FC74E196110A800E1D02D /* ComplexGetStatus.cpp */; }; 355 0F6FC751196110A800E1D02D /* ComplexGetStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6FC74F196110A800E1D02D /* ComplexGetStatus.h */; settings = {ATTRIBUTES = (Private, ); }; }; 354 356 0F7025A91714B0FA00382C0E /* DFGOSRExitCompilerCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7025A71714B0F800382C0E /* DFGOSRExitCompilerCommon.cpp */; }; 355 357 0F7025AA1714B0FC00382C0E /* DFGOSRExitCompilerCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 443 445 0FB14E211812570B009B6B4D /* DFGInlineCacheWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */; settings = {ATTRIBUTES = (Private, ); }; }; 444 446 0FB14E2318130955009B6B4D /* DFGInlineCacheWrapperInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; 447 0FB17660196B8F9E0091052A /* DFGHeapLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB1765C196B8F9E0091052A /* DFGHeapLocation.cpp */; }; 448 0FB17661196B8F9E0091052A /* DFGHeapLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB1765D196B8F9E0091052A /* DFGHeapLocation.h */; settings = {ATTRIBUTES = (Private, ); }; }; 449 0FB17662196B8F9E0091052A /* DFGPureValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */; }; 450 0FB17663196B8F9E0091052A /* DFGPureValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB1765F196B8F9E0091052A /* DFGPureValue.h */; settings = {ATTRIBUTES = (Private, ); }; }; 445 451 0FB438A319270B1D00E1FBC9 /* StructureSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB438A219270B1D00E1FBC9 /* StructureSet.cpp */; }; 446 452 0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 467 473 0FBE0F7616C1DB0F0082C5E8 /* DFGUnificationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE0F6F16C1DB010082C5E8 /* DFGUnificationPhase.cpp */; }; 468 474 0FBE0F7716C1DB120082C5E8 /* DFGUnificationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBE0F7016C1DB010082C5E8 /* DFGUnificationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 475 0FBFDD04196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBFDD02196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp */; }; 476 0FBFDD05196C92BF007A5BFA /* DFGPhantomRemovalPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBFDD03196C92BF007A5BFA /* DFGPhantomRemovalPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 469 477 0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC097681468A6EF00CF2442 /* DFGOSRExit.h */; settings = {ATTRIBUTES = (Private, ); }; }; 470 478 0FC0977114693AF500CF2442 /* DFGOSRExitCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0976F14693AEF00CF2442 /* DFGOSRExitCompiler.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 490 498 0FC97F33182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */; }; 491 499 0FC97F34182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; }; 492 0FC97F35182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F31182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.cpp */; };493 0FC97F36182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F32182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };494 500 0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */; }; 495 501 0FC97F3E18202119002C9B26 /* DFGInvalidationPointInjectionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F3818202119002C9B26 /* DFGInvalidationPointInjectionPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 498 504 0FC97F4118202119002C9B26 /* DFGWatchpointCollectionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F3B18202119002C9B26 /* DFGWatchpointCollectionPhase.cpp */; }; 499 505 0FC97F4218202119002C9B26 /* DFGWatchpointCollectionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F3C18202119002C9B26 /* DFGWatchpointCollectionPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 506 0FCA9113195E66A000426438 /* VariableWatchpointSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCA9112195E66A000426438 /* VariableWatchpointSet.cpp */; }; 500 507 0FCCAE4516D0CF7400D0C65B /* ParserError.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCCAE4316D0CF6E00D0C65B /* ParserError.h */; settings = {ATTRIBUTES = (Private, ); }; }; 501 508 0FCEFAAB1804C13E00472CE4 /* FTLSaveRestore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */; }; … … 2535 2542 0F6B1CC818641DF800845D97 /* ArityCheckFailReturnThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArityCheckFailReturnThunks.h; sourceTree = "<group>"; }; 2536 2543 0F6E845919030BEF00562741 /* DFGVariableAccessData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableAccessData.cpp; path = dfg/DFGVariableAccessData.cpp; sourceTree = "<group>"; }; 2544 0F6FC74E196110A800E1D02D /* ComplexGetStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ComplexGetStatus.cpp; sourceTree = "<group>"; }; 2545 0F6FC74F196110A800E1D02D /* ComplexGetStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComplexGetStatus.h; sourceTree = "<group>"; }; 2537 2546 0F7025A71714B0F800382C0E /* DFGOSRExitCompilerCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSRExitCompilerCommon.cpp; path = dfg/DFGOSRExitCompilerCommon.cpp; sourceTree = "<group>"; }; 2538 2547 0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExitCompilerCommon.h; path = dfg/DFGOSRExitCompilerCommon.h; sourceTree = "<group>"; }; … … 2624 2633 0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInlineCacheWrapper.h; path = dfg/DFGInlineCacheWrapper.h; sourceTree = "<group>"; }; 2625 2634 0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInlineCacheWrapperInlines.h; path = dfg/DFGInlineCacheWrapperInlines.h; sourceTree = "<group>"; }; 2635 0FB1765C196B8F9E0091052A /* DFGHeapLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGHeapLocation.cpp; path = dfg/DFGHeapLocation.cpp; sourceTree = "<group>"; }; 2636 0FB1765D196B8F9E0091052A /* DFGHeapLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGHeapLocation.h; path = dfg/DFGHeapLocation.h; sourceTree = "<group>"; }; 2637 0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPureValue.cpp; path = dfg/DFGPureValue.cpp; sourceTree = "<group>"; }; 2638 0FB1765F196B8F9E0091052A /* DFGPureValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPureValue.h; path = dfg/DFGPureValue.h; sourceTree = "<group>"; }; 2626 2639 0FB438A219270B1D00E1FBC9 /* StructureSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureSet.cpp; sourceTree = "<group>"; }; 2627 2640 0FB4B51016B3A964003F696B /* DFGMinifiedID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGMinifiedID.h; path = dfg/DFGMinifiedID.h; sourceTree = "<group>"; }; … … 2658 2671 0FBE0F6F16C1DB010082C5E8 /* DFGUnificationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUnificationPhase.cpp; path = dfg/DFGUnificationPhase.cpp; sourceTree = "<group>"; }; 2659 2672 0FBE0F7016C1DB010082C5E8 /* DFGUnificationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGUnificationPhase.h; path = dfg/DFGUnificationPhase.h; sourceTree = "<group>"; }; 2673 0FBFDD02196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPhantomRemovalPhase.cpp; path = dfg/DFGPhantomRemovalPhase.cpp; sourceTree = "<group>"; }; 2674 0FBFDD03196C92BF007A5BFA /* DFGPhantomRemovalPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPhantomRemovalPhase.h; path = dfg/DFGPhantomRemovalPhase.h; sourceTree = "<group>"; }; 2660 2675 0FC097681468A6EF00CF2442 /* DFGOSRExit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExit.h; path = dfg/DFGOSRExit.h; sourceTree = "<group>"; }; 2661 2676 0FC0976F14693AEF00CF2442 /* DFGOSRExitCompiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExitCompiler.h; path = dfg/DFGOSRExitCompiler.h; sourceTree = "<group>"; }; … … 2682 2697 0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlockJettisoningWatchpoint.cpp; sourceTree = "<group>"; }; 2683 2698 0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockJettisoningWatchpoint.h; sourceTree = "<group>"; }; 2684 0FC97F31182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProfiledCodeBlockJettisoningWatchpoint.cpp; sourceTree = "<group>"; };2685 0FC97F32182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProfiledCodeBlockJettisoningWatchpoint.h; sourceTree = "<group>"; };2686 2699 0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInvalidationPointInjectionPhase.cpp; path = dfg/DFGInvalidationPointInjectionPhase.cpp; sourceTree = "<group>"; }; 2687 2700 0FC97F3818202119002C9B26 /* DFGInvalidationPointInjectionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInvalidationPointInjectionPhase.h; path = dfg/DFGInvalidationPointInjectionPhase.h; sourceTree = "<group>"; }; … … 2690 2703 0FC97F3B18202119002C9B26 /* DFGWatchpointCollectionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGWatchpointCollectionPhase.cpp; path = dfg/DFGWatchpointCollectionPhase.cpp; sourceTree = "<group>"; }; 2691 2704 0FC97F3C18202119002C9B26 /* DFGWatchpointCollectionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGWatchpointCollectionPhase.h; path = dfg/DFGWatchpointCollectionPhase.h; sourceTree = "<group>"; }; 2705 0FCA9112195E66A000426438 /* VariableWatchpointSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VariableWatchpointSet.cpp; sourceTree = "<group>"; }; 2692 2706 0FCB408515C0A3C30048932B /* SlotVisitorInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlotVisitorInlines.h; sourceTree = "<group>"; }; 2693 2707 0FCCAE4316D0CF6E00D0C65B /* ParserError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParserError.h; sourceTree = "<group>"; }; … … 5130 5144 0F2FCCF218A60070001A27F8 /* DFGGraphSafepoint.cpp */, 5131 5145 0F2FCCF318A60070001A27F8 /* DFGGraphSafepoint.h */, 5146 0FB1765C196B8F9E0091052A /* DFGHeapLocation.cpp */, 5147 0FB1765D196B8F9E0091052A /* DFGHeapLocation.h */, 5132 5148 0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */, 5133 5149 0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */, … … 5196 5212 0F235BE917178E7300690C7F /* DFGOSRExitPreparation.cpp */, 5197 5213 0F235BEA17178E7300690C7F /* DFGOSRExitPreparation.h */, 5214 0FBFDD02196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp */, 5215 0FBFDD03196C92BF007A5BFA /* DFGPhantomRemovalPhase.h */, 5198 5216 0FFFC94F14EF909500C72532 /* DFGPhase.cpp */, 5199 5217 0FFFC95014EF909500C72532 /* DFGPhase.h */, … … 5204 5222 0FFFC95114EF909500C72532 /* DFGPredictionPropagationPhase.cpp */, 5205 5223 0FFFC95214EF909500C72532 /* DFGPredictionPropagationPhase.h */, 5224 0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */, 5225 0FB1765F196B8F9E0091052A /* DFGPureValue.h */, 5206 5226 86EC9DC11328DF82002B2AD7 /* DFGRegisterBank.h */, 5207 5227 0F666ECA1836B37E00D017F1 /* DFGResurrectionForValidationPhase.cpp */, … … 5404 5424 0F8F943F1667632D00D61971 /* CodeType.cpp */, 5405 5425 0F0B83A514BCF50400885B4F /* CodeType.h */, 5426 0F6FC74E196110A800E1D02D /* ComplexGetStatus.cpp */, 5427 0F6FC74F196110A800E1D02D /* ComplexGetStatus.h */, 5406 5428 0F3D0BBA194A414300FC9CF9 /* ConstantStructureCheck.cpp */, 5407 5429 0F3D0BBB194A414300FC9CF9 /* ConstantStructureCheck.h */, … … 5447 5469 0F98205D16BFE37F00240D02 /* PreciseJumpTargets.cpp */, 5448 5470 0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */, 5449 0FC97F31182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.cpp */,5450 0FC97F32182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h */,5451 5471 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */, 5452 5472 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */, … … 5478 5498 0F24E55717F74EDB00ABB217 /* ValueRecovery.cpp */, 5479 5499 0F426A451460CBAB00131F8F /* ValueRecovery.h */, 5500 0FCA9112195E66A000426438 /* VariableWatchpointSet.cpp */, 5480 5501 0F9181C618415CA50057B669 /* VariableWatchpointSet.h */, 5481 5502 FE5248F8191442D900B7FDE4 /* VariableWatchpointSetInlines.h */, … … 5483 5504 0F919D2215853CDE004A4E7D /* Watchpoint.cpp */, 5484 5505 0F919D2315853CDE004A4E7D /* Watchpoint.h */, 5506 52DAD38E195A164E00F30464 /* TypeLocation.h */, 5485 5507 ); 5486 5508 path = bytecode; … … 6127 6149 A767B5B617A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h in Headers */, 6128 6150 A704D90717A0BAA8006BA554 /* DFGMergeMode.h in Headers */, 6151 0FB17663196B8F9E0091052A /* DFGPureValue.h in Headers */, 6129 6152 0F2BDC451522801B00CD8910 /* DFGMinifiedGraph.h in Headers */, 6130 6153 0F2E892D16D02BAF009E4FD2 /* DFGMinifiedID.h in Headers */, … … 6332 6355 A532438C18568335002ED692 /* InspectorJSTypeBuilders.h in Headers */, 6333 6356 A50E4B6218809DD50068A46D /* InspectorRuntimeAgent.h in Headers */, 6357 0FBFDD05196C92BF007A5BFA /* DFGPhantomRemovalPhase.h in Headers */, 6334 6358 A55D93AC18514F7900400DED /* InspectorTypeBuilder.h in Headers */, 6335 6359 A593CF831840377100BFCE27 /* InspectorValues.h in Headers */, … … 6588 6612 868916B0155F286300CB2B9A /* PrivateName.h in Headers */, 6589 6613 BC18C4500E16F5CD00B34460 /* Profile.h in Headers */, 6590 0FC97F36182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h in Headers */,6591 6614 95CD45770E1C4FDD0085358E /* ProfileGenerator.h in Headers */, 6592 6615 BC18C4510E16F5CD00B34460 /* ProfileNode.h in Headers */, … … 6613 6636 BC18C4550E16F5CD00B34460 /* PropertySlot.h in Headers */, 6614 6637 0FB7F39C15ED8E4600F167B2 /* PropertyStorage.h in Headers */, 6638 0F6FC751196110A800E1D02D /* ComplexGetStatus.h in Headers */, 6615 6639 0F12DE101979D5FD0006FF4E /* ExceptionFuzz.h in Headers */, 6616 6640 BC18C4560E16F5CD00B34460 /* Protect.h in Headers */, … … 6670 6694 0F2B670517B6B5AB00A7AE3F /* SimpleTypedArrayController.h in Headers */, 6671 6695 14BA78F113AAB88F005B7C2C /* SlotVisitor.h in Headers */, 6696 0FB17661196B8F9E0091052A /* DFGHeapLocation.h in Headers */, 6672 6697 C2160FE715F7E95E00942DFC /* SlotVisitorInlines.h in Headers */, 6673 6698 A709F2F017A0AC0400512E98 /* SlowPathCall.h in Headers */, … … 7693 7718 C2981FDC17BAFF4400A3BC98 /* DFGDesiredWriteBarriers.cpp in Sources */, 7694 7719 0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */, 7720 0FCA9113195E66A000426438 /* VariableWatchpointSet.cpp in Sources */, 7695 7721 0FD81AD2154FB4EE00983E72 /* DFGDominators.cpp in Sources */, 7696 7722 0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */, … … 7757 7783 0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */, 7758 7784 0FD8A32917D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.cpp in Sources */, 7785 0FB17662196B8F9E0091052A /* DFGPureValue.cpp in Sources */, 7759 7786 0FD8A32B17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp in Sources */, 7760 7787 0F63944015C75F1D006A597C /* DFGTypeCheckHoistingPhase.cpp in Sources */, … … 7762 7789 0F34B14916D42010001CDA5A /* DFGUseKind.cpp in Sources */, 7763 7790 0F3B3A2B15475000003ED0FF /* DFGValidate.cpp in Sources */, 7791 0FB17660196B8F9E0091052A /* DFGHeapLocation.cpp in Sources */, 7764 7792 0F2BDC4F15228BF300CD8910 /* DFGValueSource.cpp in Sources */, 7765 7793 0FDDBFB51666EED800C55FEF /* DFGVariableAccessDataDump.cpp in Sources */, … … 8032 8060 0F98206016BFE38100240D02 /* PreciseJumpTargets.cpp in Sources */, 8033 8061 95742F650DD11F5A000917FB /* Profile.cpp in Sources */, 8034 0FC97F35182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.cpp in Sources */,8035 8062 95CD45760E1C4FDD0085358E /* ProfileGenerator.cpp in Sources */, 8036 8063 95AB83560DA43C3000BC83F3 /* ProfileNode.cpp in Sources */, … … 8092 8119 9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */, 8093 8120 0F8F2B9E17306C8D007DBDA5 /* SourceCode.cpp in Sources */, 8121 0FBFDD04196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp in Sources */, 8094 8122 0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */, 8095 8123 E49DC16B12EF293E00184A1F /* SourceProviderCache.cpp in Sources */, … … 8135 8163 0F919D2515853CE0004A4E7D /* Watchpoint.cpp in Sources */, 8136 8164 1ACF7377171CA6FB00C9BB1E /* Weak.cpp in Sources */, 8165 0F6FC750196110A800E1D02D /* ComplexGetStatus.cpp in Sources */, 8137 8166 14E84F9E14EE1ACC00D6D5D4 /* WeakBlock.cpp in Sources */, 8138 8167 14F7256514EE265E00B1652B /* WeakHandleOwner.cpp in Sources */, -
trunk/Source/JavaScriptCore/bytecode/BytecodeList.json
r171660 r172129 113 113 { "name" : "op_resolve_scope", "length" : 6 }, 114 114 { "name" : "op_get_from_scope", "length" : 8 }, 115 { "name" : "op_get_from_scope_with_profile", "length" : 9 }, 115 116 { "name" : "op_put_to_scope", "length" : 7 }, 116 117 { "name" : "op_put_to_scope_with_profile", "length" : 8 }, -
trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h
r171660 r172129 122 122 case op_init_global_const: 123 123 case op_push_name_scope: 124 case op_get_from_scope_with_profile: 124 125 case op_get_from_scope: 125 126 case op_to_primitive: … … 314 315 case op_call_varargs: 315 316 case op_construct_varargs: 317 case op_get_from_scope_with_profile: 316 318 case op_get_from_scope: 317 319 case op_call: -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r171946 r172129 40 40 #include "DFGWorklist.h" 41 41 #include "Debugger.h" 42 #include "FunctionExecutableDump.h" 42 43 #include "HighFidelityTypeProfiler.h" 43 44 #include "Interpreter.h" … … 151 152 out.print(", ", instructionCount()); 152 153 if (this->jitType() == JITCode::BaselineJIT && m_shouldAlwaysBeInlined) 153 out.print(" (S ABI)");154 out.print(" (ShouldAlwaysBeInlined)"); 154 155 if (ownerExecutable()->neverInline()) 155 156 out.print(" (NeverInline)"); 157 if (ownerExecutable()->didTryToEnterInLoop()) 158 out.print(" (DidTryToEnterInLoop)"); 156 159 if (ownerExecutable()->isStrictMode()) 157 160 out.print(" (StrictMode)"); … … 1542 1545 } 1543 1546 1547 namespace { 1548 1549 class PutToScopeFireDetail : public FireDetail { 1550 public: 1551 PutToScopeFireDetail(CodeBlock* codeBlock, const Identifier& ident) 1552 : m_codeBlock(codeBlock) 1553 , m_ident(ident) 1554 { 1555 } 1556 1557 virtual void dump(PrintStream& out) const override 1558 { 1559 out.print("Linking put_to_scope in ", FunctionExecutableDump(jsCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())), " for ", m_ident); 1560 } 1561 1562 private: 1563 CodeBlock* m_codeBlock; 1564 const Identifier& m_ident; 1565 }; 1566 1567 } // anonymous namespace 1568 1544 1569 CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other) 1545 1570 : m_globalObject(other.m_globalObject) … … 1631 1656 , m_optimizationDelayCounter(0) 1632 1657 , m_reoptimizationRetryCounter(0) 1658 , m_returnStatementTypeSet(nullptr) 1633 1659 #if ENABLE(JIT) 1634 1660 , m_capabilityLevelState(DFG::CapabilityLevelNotSet) … … 1858 1884 } 1859 1885 1886 case op_get_from_scope_with_profile: 1860 1887 case op_get_from_scope: { 1861 ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand]; 1888 int offset = (pc[0].u.opcode == op_get_from_scope_with_profile ? 2 : 1); 1889 ValueProfile* profile = &m_valueProfiles[pc[opLength - offset].u.operand]; 1862 1890 ASSERT(profile->m_bytecodeOffset == -1); 1863 1891 profile->m_bytecodeOffset = i; 1864 instructions[i + opLength - 1] = profile;1892 instructions[i + opLength - offset] = profile; 1865 1893 1866 1894 // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand … … 1875 1903 instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure); 1876 1904 instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand); 1905 1906 if (pc[0].u.opcode == op_get_from_scope_with_profile) { 1907 // The format of this instruction is: get_from_scope_with_profile dst, scope, id, ResolveModeAndType, Structure, Operand, ..., TypeLocation 1908 size_t instructionOffset = i + opLength - 1; 1909 TypeLocation* location = vm()->nextLocation(); 1910 scopeDependentProfile(op, ident, instructionOffset, location); 1911 instructions[i + 8].u.location = location; 1912 } 1877 1913 break; 1878 1914 } … … 1890 1926 else if (op.type == ClosureVar || op.type == ClosureVarWithVarInjectionChecks) { 1891 1927 if (op.watchpointSet) 1892 op.watchpointSet->invalidate( );1928 op.watchpointSet->invalidate(PutToScopeFireDetail(this, ident)); 1893 1929 } else if (op.structure) 1894 1930 instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure); … … 1897 1933 if (pc[0].u.opcode == op_put_to_scope_with_profile) { 1898 1934 // The format of this instruction is: put_to_scope_with_profile scope, id, value, ResolveModeAndType, Structure, Operand, TypeLocation* 1935 size_t instructionOffset = i + opLength - 1; 1899 1936 TypeLocation* location = vm()->nextLocation(); 1900 size_t instructionOffset = i + opLength - 1; 1901 int divot, startOffset, endOffset; 1902 unsigned line = 0, column = 0; 1903 expressionRangeForBytecodeOffset(instructionOffset, divot, startOffset, endOffset, line, column); 1904 1905 location->m_line = line; 1906 location->m_column = column; 1907 location->m_sourceID = m_ownerExecutable->sourceID(); 1908 1909 // FIXME: handle other values for op.type here, and also consider what to do when we can't statically determine the globalID 1910 SymbolTable* symbolTable = 0; 1911 if (op.type == ClosureVar) 1912 symbolTable = op.activation->symbolTable(); 1913 else if (op.type == GlobalVar) 1914 symbolTable = m_globalObject.get()->symbolTable(); 1915 1916 if (symbolTable) { 1917 ConcurrentJITLocker locker(symbolTable->m_lock); 1918 location->m_globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm()); 1919 location->m_globalTypeSet =symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm()); 1920 } else 1921 location->m_globalVariableID = HighFidelityNoGlobalIDExists; 1922 1923 vm()->highFidelityTypeProfiler()->insertNewLocation(location); 1937 scopeDependentProfile(op, ident, instructionOffset, location); 1924 1938 instructions[i + 7].u.location = location; 1925 1939 } … … 1928 1942 1929 1943 case op_profile_types_with_high_fidelity: { 1930 1944 size_t instructionOffset = i + opLength - 1; 1945 unsigned divotStart, divotEnd; 1946 bool shouldAnalyze = m_unlinkedCode->highFidelityTypeProfileExpressionInfoForBytecodeOffset(instructionOffset, divotStart, divotEnd); 1931 1947 VirtualRegister virtualRegister(pc[1].u.operand); 1932 1948 SymbolTable* symbolTable = m_symbolTable.get(); 1933 1949 TypeLocation* location = vm()->nextLocation(); 1934 size_t instructionOffset = i + opLength - 1;1935 int divot, startOffset, endOffset;1936 unsigned line = 0, column = 0;1937 expressionRangeForBytecodeOffset(instructionOffset, divot, startOffset, endOffset, line, column); 1938 1939 int hasGlobalIDFlag = pc[3].u.operand;1940 if (hasGlobalIDFlag){1950 location->m_divotStart = divotStart; 1951 location->m_divotEnd = divotEnd; 1952 location->m_sourceID = m_ownerExecutable->sourceID(); 1953 1954 ProfileTypesWithHighFidelityBytecodeFlag flag = static_cast<ProfileTypesWithHighFidelityBytecodeFlag>(pc[3].u.operand); 1955 switch (flag) { 1956 case ProfileTypesBytecodeHasGlobalID: { 1941 1957 ConcurrentJITLocker locker(symbolTable->m_lock); 1942 1958 location->m_globalVariableID = symbolTable->uniqueIDForRegister(locker, virtualRegister.offset(), *vm()); 1943 1959 location->m_globalTypeSet = symbolTable->globalTypeSetForRegister(locker, virtualRegister.offset(), *vm()); 1944 } else 1960 break; 1961 } 1962 case ProfileTypesBytecodeDoesNotHaveGlobalID: 1963 case ProfileTypesBytecodeFunctionArgument: 1964 case ProfileTypesBytecodeFunctionThisObject: { 1945 1965 location->m_globalVariableID = HighFidelityNoGlobalIDExists; 1946 1947 1948 location->m_line = line; 1949 location->m_column = column; 1950 location->m_sourceID = m_ownerExecutable->sourceID(); 1951 1952 vm()->highFidelityTypeProfiler()->insertNewLocation(location); 1966 break; 1967 } 1968 case ProfileTypesBytecodeFunctionReturnStatement: { 1969 location->m_globalTypeSet = returnStatementTypeSet(); 1970 location->m_globalVariableID = HighFidelityReturnStatement; 1971 location->m_divotForFunctionOffsetIfReturnStatement = m_sourceOffset; 1972 if (!shouldAnalyze) { 1973 // Because some return statements are added implicitly (to return undefined at the end of a function), and these nodes don't emit expression ranges, give them some range. 1974 // Currently, this divot is on the open brace of the function. 1975 location->m_divotStart = location->m_divotEnd = location->m_divotForFunctionOffsetIfReturnStatement; 1976 shouldAnalyze = true; 1977 } 1978 break; 1979 } 1980 } 1981 1982 if (shouldAnalyze) 1983 vm()->highFidelityTypeProfiler()->insertNewLocation(location); 1953 1984 instructions[i + 2].u.location = location; 1954 1985 break; 1955 1986 } 1956 1957 1987 1958 1988 case op_captured_mov: … … 2184 2214 return true; 2185 2215 #endif 2216 } 2217 2218 static bool shouldMarkTransition(DFG::WeakReferenceTransition& transition) 2219 { 2220 if (transition.m_codeOrigin && !Heap::isMarked(transition.m_codeOrigin.get())) 2221 return false; 2222 2223 if (!Heap::isMarked(transition.m_from.get())) 2224 return false; 2225 2226 return true; 2186 2227 } 2187 2228 … … 2262 2303 if (JITCode::isOptimizingJIT(jitType())) { 2263 2304 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon(); 2305 2264 2306 for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) { 2265 if ((!dfgCommon->transitions[i].m_codeOrigin 2266 || Heap::isMarked(dfgCommon->transitions[i].m_codeOrigin.get())) 2267 && Heap::isMarked(dfgCommon->transitions[i].m_from.get())) { 2307 if (shouldMarkTransition(dfgCommon->transitions[i])) { 2268 2308 // If the following three things are live, then the target of the 2269 2309 // transition is also live: 2310 // 2270 2311 // - This code block. We know it's live already because otherwise 2271 2312 // we wouldn't be scanning ourselves. 2313 // 2272 2314 // - The code origin of the transition. Transitions may arise from 2273 2315 // code that was inlined. They are not relevant if the user's 2274 2316 // object that is required for the inlinee to run is no longer 2275 2317 // live. 2318 // 2276 2319 // - The source of the transition. The transition checks if some 2277 2320 // heap location holds the source, and if so, stores the target. 2278 2321 // Hence the source must be live for the transition to be live. 2322 // 2323 // We also short-circuit the liveness if the structure is harmless 2324 // to mark (i.e. its global object and prototype are both already 2325 // live). 2326 2279 2327 visitor.append(&dfgCommon->transitions[i].m_to); 2280 2328 } else … … 2309 2357 allAreLiveSoFar = false; 2310 2358 break; 2359 } 2360 } 2361 if (allAreLiveSoFar) { 2362 for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i) { 2363 if (!Heap::isMarked(dfgCommon->weakStructureReferences[i].get())) { 2364 allAreLiveSoFar = false; 2365 break; 2366 } 2311 2367 } 2312 2368 } … … 2395 2451 break; 2396 2452 } 2453 case op_get_from_scope_with_profile: 2397 2454 case op_get_from_scope: 2398 2455 case op_put_to_scope_with_profile: … … 2626 2683 for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i) 2627 2684 visitor.append(&dfgCommon->weakReferences[i]); 2685 2686 for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i) 2687 visitor.append(&dfgCommon->weakStructureReferences[i]); 2628 2688 #endif 2629 2689 } … … 2946 3006 #endif 2947 3007 2948 void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode )3008 void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail) 2949 3009 { 2950 3010 RELEASE_ASSERT(reason != Profiler::NotJettisoned); … … 2955 3015 if (mode == CountReoptimization) 2956 3016 dataLog(" and counting reoptimization"); 2957 dataLog(" due to ", reason, ".\n"); 3017 dataLog(" due to ", reason); 3018 if (detail) 3019 dataLog(", ", *detail); 3020 dataLog(".\n"); 2958 3021 } 2959 3022 … … 2962 3025 2963 3026 if (Profiler::Compilation* compilation = jitCode()->dfgCommon()->compilation.get()) 2964 compilation->setJettisonReason(reason );3027 compilation->setJettisonReason(reason, detail); 2965 3028 2966 3029 // We want to accomplish two things here: … … 3798 3861 #endif 3799 3862 3863 void CodeBlock::scopeDependentProfile(ResolveOp op, const Identifier& ident, size_t instructionOffset, TypeLocation* location) 3864 { 3865 unsigned divotStart, divotEnd; 3866 bool shouldAnalyze = m_unlinkedCode->highFidelityTypeProfileExpressionInfoForBytecodeOffset(instructionOffset, divotStart, divotEnd); 3867 location->m_divotStart = divotStart; 3868 location->m_divotEnd = divotEnd; 3869 location->m_sourceID = m_ownerExecutable->sourceID(); 3870 3871 // FIXME: handle other values for op.type here, and also consider what to do when we can't statically determine the globalID 3872 SymbolTable* symbolTable = nullptr; 3873 if (op.type == ClosureVar) 3874 symbolTable = op.activation->symbolTable(); 3875 else if (op.type == GlobalVar) 3876 symbolTable = m_globalObject.get()->symbolTable(); 3877 3878 if (symbolTable) { 3879 ConcurrentJITLocker locker(symbolTable->m_lock); 3880 location->m_globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm()); 3881 location->m_globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm()); 3882 } else 3883 location->m_globalVariableID = HighFidelityNoGlobalIDExists; 3884 3885 if (shouldAnalyze) 3886 vm()->highFidelityTypeProfiler()->insertNewLocation(location); 3887 } 3888 3800 3889 } // namespace JSC -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r171660 r172129 65 65 #include "RegExpObject.h" 66 66 #include "StructureStubInfo.h" 67 #include "TypeSet.h" 67 68 #include "UnconditionalFinalizer.h" 68 69 #include "ValueProfile.h" … … 311 312 #endif 312 313 313 void jettison(Profiler::JettisonReason, ReoptimizationMode = DontCountReoptimization );314 void jettison(Profiler::JettisonReason, ReoptimizationMode = DontCountReoptimization, const FireDetail* = nullptr); 314 315 315 316 ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); } … … 941 942 942 943 bool isKnownToBeLiveDuringGC(); // Will only return valid results when called during GC. Assumes that you've already established that the owner executable is live. 944 RefPtr<TypeSet> returnStatementTypeSet() 945 { 946 if (!m_returnStatementTypeSet) 947 m_returnStatementTypeSet = TypeSet::create(); 948 949 return m_returnStatementTypeSet; 950 } 943 951 944 952 … … 1011 1019 m_rareData = adoptPtr(new RareData); 1012 1020 } 1021 1022 void scopeDependentProfile(ResolveOp, const Identifier&, size_t, TypeLocation*); 1013 1023 1014 1024 #if ENABLE(JIT) … … 1091 1101 std::unique_ptr<BytecodeLivenessAnalysis> m_livenessAnalysis; 1092 1102 1103 RefPtr<TypeSet> m_returnStatementTypeSet; 1104 1093 1105 struct RareData { 1094 1106 WTF_MAKE_FAST_ALLOCATED; -
trunk/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.cpp
r163844 r172129 33 33 namespace JSC { 34 34 35 void CodeBlockJettisoningWatchpoint::fireInternal( )35 void CodeBlockJettisoningWatchpoint::fireInternal(const FireDetail& detail) 36 36 { 37 37 if (DFG::shouldShowDisassembly()) 38 38 dataLog("Firing watchpoint ", RawPointer(this), " on ", *m_codeBlock, "\n"); 39 39 40 m_codeBlock->jettison(Profiler::JettisonDueToUnprofiledWatchpoint, CountReoptimization );40 m_codeBlock->jettison(Profiler::JettisonDueToUnprofiledWatchpoint, CountReoptimization, &detail); 41 41 42 42 if (isOnList()) -
trunk/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.h
r162139 r172129 46 46 47 47 protected: 48 virtual void fireInternal( ) override;48 virtual void fireInternal(const FireDetail&) override; 49 49 50 50 private: -
trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
r171746 r172129 29 29 #include "AccessorCallJITStubRoutine.h" 30 30 #include "CodeBlock.h" 31 #include "ComplexGetStatus.h" 31 32 #include "JSCInlines.h" 32 33 #include "JSScope.h" … … 84 85 85 86 unsigned attributesIgnored; 86 JSCell* specificValue;87 87 PropertyOffset offset = structure->getConcurrently( 88 *profiledBlock->vm(), uid, attributesIgnored, specificValue); 89 if (structure->isDictionary()) 90 specificValue = 0; 88 *profiledBlock->vm(), uid, attributesIgnored); 91 89 if (!isValidOffset(offset)) 92 90 return GetByIdStatus(NoInformation, false); 93 91 94 return GetByIdStatus(Simple, false, GetByIdVariant(StructureSet(structure), offset , specificValue));92 return GetByIdStatus(Simple, false, GetByIdVariant(StructureSet(structure), offset)); 95 93 } 96 94 … … 139 137 } 140 138 141 if (stubInfo->resetByGC)142 return GetByIdStatus(TakesSlowPath, true);143 144 139 // Finally figure out if we can derive an access strategy. 145 140 GetByIdStatus result; … … 155 150 return GetByIdStatus(slowPathState, true); 156 151 unsigned attributesIgnored; 157 JSCell* specificValue;158 152 GetByIdVariant variant; 159 153 variant.m_offset = structure->getConcurrently( 160 *profiledBlock->vm(), uid, attributesIgnored , specificValue);154 *profiledBlock->vm(), uid, attributesIgnored); 161 155 if (!isValidOffset(variant.m_offset)) 162 156 return GetByIdStatus(slowPathState, true); 163 157 164 if (structure->isDictionary())165 specificValue = 0;166 167 158 variant.m_structureSet.add(structure); 168 variant.m_specificValue = JSValue(specificValue);169 159 bool didAppend = result.appendVariant(variant); 170 160 ASSERT_UNUSED(didAppend, didAppend); … … 176 166 Structure* structure = list->at(listIndex).structure(); 177 167 178 // FIXME: We should assert that we never see a structure that 179 // hasImpureGetOwnPropertySlot() but for which we don't 180 // newImpurePropertyFiresWatchpoints(). We're not at a point where we can do 181 // that, yet. 182 // https://bugs.webkit.org/show_bug.cgi?id=131810 183 184 if (structure->takesSlowPathInDFGForImpureProperty()) 168 ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor( 169 profiledBlock, structure, list->at(listIndex).chain(), 170 list->at(listIndex).chainCount(), uid); 171 172 switch (complexGetStatus.kind()) { 173 case ComplexGetStatus::ShouldSkip: 174 continue; 175 176 case ComplexGetStatus::TakesSlowPath: 185 177 return GetByIdStatus(slowPathState, true); 186 187 unsigned attributesIgnored; 188 JSCell* specificValue; 189 PropertyOffset myOffset; 190 RefPtr<IntendedStructureChain> chain; 191 192 if (list->at(listIndex).chain()) { 193 chain = adoptRef(new IntendedStructureChain( 194 profiledBlock, structure, list->at(listIndex).chain(), 195 list->at(listIndex).chainCount())); 196 197 if (!chain->isStillValid()) { 198 // This won't ever run again so skip it. 199 continue; 178 179 case ComplexGetStatus::Inlineable: { 180 std::unique_ptr<CallLinkStatus> callLinkStatus; 181 switch (list->at(listIndex).type()) { 182 case GetByIdAccess::SimpleInline: 183 case GetByIdAccess::SimpleStub: { 184 break; 200 185 } 201 202 if (structure->takesSlowPathInDFGForImpureProperty()) 186 case GetByIdAccess::Getter: { 187 AccessorCallJITStubRoutine* stub = static_cast<AccessorCallJITStubRoutine*>( 188 list->at(listIndex).stubRoutine()); 189 callLinkStatus = std::make_unique<CallLinkStatus>( 190 CallLinkStatus::computeFor(locker, *stub->m_callLinkInfo, callExitSiteData)); 191 break; 192 } 193 case GetByIdAccess::CustomGetter: 194 case GetByIdAccess::WatchedStub:{ 195 // FIXME: It would be totally sweet to support this at some point in the future. 196 // https://bugs.webkit.org/show_bug.cgi?id=133052 203 197 return GetByIdStatus(slowPathState, true); 204 205 size_t chainSize = chain->size();206 for (size_t i = 0; i < chainSize; i++) {207 if (chain->at(i)->takesSlowPathInDFGForImpureProperty())208 return GetByIdStatus(slowPathState, true);209 198 } 210 211 JSObject* currentObject = chain->terminalPrototype(); 212 Structure* currentStructure = chain->last(); 213 214 ASSERT_UNUSED(currentObject, currentObject); 215 216 myOffset = currentStructure->getConcurrently( 217 *profiledBlock->vm(), uid, attributesIgnored, specificValue); 218 if (currentStructure->isDictionary()) 219 specificValue = 0; 220 } else { 221 myOffset = structure->getConcurrently( 222 *profiledBlock->vm(), uid, attributesIgnored, specificValue); 223 if (structure->isDictionary()) 224 specificValue = 0; 225 } 226 227 if (!isValidOffset(myOffset)) 228 return GetByIdStatus(slowPathState, true); 229 230 std::unique_ptr<CallLinkStatus> callLinkStatus; 231 switch (list->at(listIndex).type()) { 232 case GetByIdAccess::SimpleInline: 233 case GetByIdAccess::SimpleStub: { 199 default: 200 RELEASE_ASSERT_NOT_REACHED(); 201 } 202 203 GetByIdVariant variant( 204 StructureSet(structure), complexGetStatus.offset(), complexGetStatus.chain(), 205 std::move(callLinkStatus)); 206 207 if (!result.appendVariant(variant)) 208 return GetByIdStatus(slowPathState, true); 234 209 break; 235 } 236 case GetByIdAccess::Getter: { 237 AccessorCallJITStubRoutine* stub = static_cast<AccessorCallJITStubRoutine*>( 238 list->at(listIndex).stubRoutine()); 239 callLinkStatus = std::make_unique<CallLinkStatus>( 240 CallLinkStatus::computeFor(locker, *stub->m_callLinkInfo, callExitSiteData)); 241 break; 242 } 243 case GetByIdAccess::CustomGetter: 244 case GetByIdAccess::WatchedStub: { 245 // FIXME: It would be totally sweet to support these at some point in the future. 246 // https://bugs.webkit.org/show_bug.cgi?id=133052 247 // https://bugs.webkit.org/show_bug.cgi?id=135172 248 return GetByIdStatus(slowPathState, true); 249 } 250 default: 251 RELEASE_ASSERT_NOT_REACHED(); 252 } 253 254 GetByIdVariant variant( 255 StructureSet(structure), myOffset, specificValue, chain.get(), 256 WTF::move(callLinkStatus)); 257 258 if (!result.appendVariant(variant)) 259 return GetByIdStatus(slowPathState, true); 210 } } 260 211 } 261 212 … … 335 286 336 287 unsigned attributes; 337 JSCell* specificValue; 338 PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue); 288 PropertyOffset offset = structure->getConcurrently(vm, uid, attributes); 339 289 if (!isValidOffset(offset)) 340 290 return GetByIdStatus(TakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it. 341 291 if (attributes & Accessor) 342 292 return GetByIdStatus(MakesCalls); // We could be smarter here, like strenght-reducing this to a Call. 343 if (structure->isDictionary()) 344 specificValue = 0; 345 346 if (!result.appendVariant(GetByIdVariant(structure, offset, specificValue))) 293 294 if (!result.appendVariant(GetByIdVariant(structure, offset))) 347 295 return GetByIdStatus(TakesSlowPath); 348 296 } -
trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp
r171746 r172129 34 34 35 35 GetByIdVariant::GetByIdVariant( 36 const StructureSet& structureSet, PropertyOffset offset, JSValue specificValue,36 const StructureSet& structureSet, PropertyOffset offset, 37 37 const IntendedStructureChain* chain, std::unique_ptr<CallLinkStatus> callLinkStatus) 38 38 : m_structureSet(structureSet) 39 39 , m_alternateBase(nullptr) 40 , m_specificValue(specificValue)41 40 , m_offset(offset) 42 41 , m_callLinkStatus(WTF::move(callLinkStatus)) … … 44 43 if (!structureSet.size()) { 45 44 ASSERT(offset == invalidOffset); 46 ASSERT(!specificValue);47 45 ASSERT(!chain); 48 46 } … … 57 55 58 56 GetByIdVariant::GetByIdVariant(const GetByIdVariant& other) 57 : GetByIdVariant() 59 58 { 60 59 *this = other; … … 66 65 m_constantChecks = other.m_constantChecks; 67 66 m_alternateBase = other.m_alternateBase; 68 m_specificValue = other.m_specificValue;69 67 m_offset = other.m_offset; 70 68 if (other.m_callLinkStatus) … … 73 71 m_callLinkStatus = nullptr; 74 72 return *this; 73 } 74 75 StructureSet GetByIdVariant::baseStructure() const 76 { 77 if (!m_alternateBase) 78 return structureSet(); 79 80 Structure* structure = structureFor(m_constantChecks, m_alternateBase); 81 RELEASE_ASSERT(structure); 82 return structure; 75 83 } 76 84 … … 86 94 return false; 87 95 88 if (m_specificValue != other.m_specificValue)89 m_specificValue = JSValue();90 91 96 mergeInto(other.m_constantChecks, m_constantChecks); 92 97 m_structureSet.merge(other.m_structureSet); … … 112 117 if (m_alternateBase) 113 118 out.print(", alternateBase = ", inContext(JSValue(m_alternateBase), context)); 114 if (specificValue())115 out.print(", specificValue = ", inContext(specificValue(), context));116 119 out.print(", offset = ", offset()); 117 120 if (m_callLinkStatus) -
trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h
r171660 r172129 43 43 public: 44 44 GetByIdVariant( 45 const StructureSet& structureSet = StructureSet(), 46 PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(), 45 const StructureSet& structureSet = StructureSet(), PropertyOffset offset = invalidOffset, 47 46 const IntendedStructureChain* chain = nullptr, 48 47 std::unique_ptr<CallLinkStatus> callLinkStatus = nullptr); … … 59 58 const ConstantStructureCheckVector& constantChecks() const { return m_constantChecks; } 60 59 JSObject* alternateBase() const { return m_alternateBase; } 61 JSValue specificValue() const { return m_specificValue; }60 StructureSet baseStructure() const; 62 61 PropertyOffset offset() const { return m_offset; } 63 62 CallLinkStatus* callLinkStatus() const { return m_callLinkStatus.get(); } … … 74 73 ConstantStructureCheckVector m_constantChecks; 75 74 JSObject* m_alternateBase; 76 JSValue m_specificValue;77 75 PropertyOffset m_offset; 78 76 std::unique_ptr<CallLinkStatus> m_callLinkStatus; -
trunk/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h
r166952 r172129 54 54 PutByIdAccess() 55 55 : m_type(Invalid) 56 , m_chainCount(UINT_MAX) 56 57 { 57 58 } … … 96 97 Structure* structure, 97 98 StructureChain* chain, 99 unsigned chainCount, 98 100 PutPropertySlot::PutValueFunc customSetter, 99 101 PassRefPtr<JITStubRoutine> stubRoutine) … … 103 105 result.m_oldStructure.set(vm, owner, structure); 104 106 result.m_type = accessType; 105 if (chain) 107 if (chain) { 106 108 result.m_chain.set(vm, owner, chain); 109 result.m_chainCount = chainCount; 110 } 107 111 result.m_customSetter = customSetter; 108 112 result.m_stubRoutine = stubRoutine; … … 133 137 Structure* structure() const 134 138 { 135 ASSERT(isReplace() );139 ASSERT(isReplace() || isSetter() || isCustom()); 136 140 return m_oldStructure.get(); 137 141 } … … 147 151 ASSERT(isTransition() || isSetter() || isCustom()); 148 152 return m_chain.get(); 153 } 154 155 unsigned chainCount() const 156 { 157 ASSERT(isSetter() || isCustom()); 158 return m_chainCount; 149 159 } 150 160 … … 170 180 WriteBarrier<Structure> m_newStructure; 171 181 WriteBarrier<StructureChain> m_chain; 182 unsigned m_chainCount; 172 183 PutPropertySlot::PutValueFunc m_customSetter; 173 184 RefPtr<JITStubRoutine> m_stubRoutine; -
trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
r171660 r172129 27 27 #include "PutByIdStatus.h" 28 28 29 #include "AccessorCallJITStubRoutine.h" 29 30 #include "CodeBlock.h" 31 #include "ComplexGetStatus.h" 30 32 #include "LLIntData.h" 31 33 #include "LowLevelInterpreter.h" … … 97 99 return PutByIdStatus(NoInformation); 98 100 99 return PutByIdVariant::transition( 100 structure, newStructure, 101 chain ? adoptRef(new IntendedStructureChain(profiledBlock, structure, chain)) : 0, 102 offset); 101 RefPtr<IntendedStructureChain> intendedChain; 102 if (chain) 103 intendedChain = adoptRef(new IntendedStructureChain(profiledBlock, structure, chain)); 104 105 return PutByIdVariant::transition(structure, newStructure, intendedChain.get(), offset); 103 106 } 104 107 … … 116 119 117 120 StructureStubInfo* stubInfo = map.get(CodeOrigin(bytecodeIndex)); 118 PutByIdStatus result = computeForStubInfo(locker, profiledBlock, stubInfo, uid); 121 PutByIdStatus result = computeForStubInfo( 122 locker, profiledBlock, stubInfo, uid, 123 CallLinkStatus::computeExitSiteData(locker, profiledBlock, bytecodeIndex)); 119 124 if (!result) 120 125 return computeFromLLInt(profiledBlock, bytecodeIndex, uid); … … 128 133 129 134 #if ENABLE(JIT) 130 PutByIdStatus PutByIdStatus::computeForStubInfo(const ConcurrentJITLocker&, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, StringImpl* uid) 135 PutByIdStatus PutByIdStatus::computeForStubInfo( 136 const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, 137 StringImpl* uid, CallLinkStatus::ExitSiteData callExitSiteData) 131 138 { 132 139 if (!stubInfo || !stubInfo->seen) 133 140 return PutByIdStatus(); 134 141 135 if (stubInfo->resetByGC)136 return PutByIdStatus(TakesSlowPath);137 138 142 switch (stubInfo->accessType) { 139 143 case access_unset: … … 159 163 *profiledBlock->vm(), uid); 160 164 if (isValidOffset(offset)) { 165 RefPtr<IntendedStructureChain> chain; 166 if (stubInfo->u.putByIdTransition.chain) { 167 chain = adoptRef(new IntendedStructureChain( 168 profiledBlock, stubInfo->u.putByIdTransition.previousStructure.get(), 169 stubInfo->u.putByIdTransition.chain.get())); 170 } 161 171 return PutByIdVariant::transition( 162 172 stubInfo->u.putByIdTransition.previousStructure.get(), 163 173 stubInfo->u.putByIdTransition.structure.get(), 164 stubInfo->u.putByIdTransition.chain ? adoptRef(new IntendedStructureChain( 165 profiledBlock, stubInfo->u.putByIdTransition.previousStructure.get(), 166 stubInfo->u.putByIdTransition.chain.get())) : 0, 167 offset); 174 chain.get(), offset); 168 175 } 169 176 return PutByIdStatus(TakesSlowPath); … … 176 183 result.m_state = Simple; 177 184 185 State slowPathState = TakesSlowPath; 178 186 for (unsigned i = 0; i < list->size(); ++i) { 179 187 const PutByIdAccess& access = list->at(i); 188 189 switch (access.type()) { 190 case PutByIdAccess::Setter: 191 case PutByIdAccess::CustomSetter: 192 slowPathState = MakesCalls; 193 break; 194 default: 195 break; 196 } 197 } 198 199 for (unsigned i = 0; i < list->size(); ++i) { 200 const PutByIdAccess& access = list->at(i); 201 202 PutByIdVariant variant; 180 203 181 204 switch (access.type()) { … … 184 207 PropertyOffset offset = structure->getConcurrently(*profiledBlock->vm(), uid); 185 208 if (!isValidOffset(offset)) 186 return PutByIdStatus(TakesSlowPath); 187 if (!result.appendVariant(PutByIdVariant::replace(structure, offset))) 188 return PutByIdStatus(TakesSlowPath); 209 return PutByIdStatus(slowPathState); 210 variant = PutByIdVariant::replace(structure, offset); 189 211 break; 190 212 } … … 194 216 access.newStructure()->getConcurrently(*profiledBlock->vm(), uid); 195 217 if (!isValidOffset(offset)) 196 return PutByIdStatus( TakesSlowPath);218 return PutByIdStatus(slowPathState); 197 219 RefPtr<IntendedStructureChain> chain; 198 220 if (access.chain()) { … … 202 224 continue; 203 225 } 204 bool ok = result.appendVariant(PutByIdVariant::transition( 205 access.oldStructure(), access.newStructure(), chain.get(), offset)); 206 if (!ok) 207 return PutByIdStatus(TakesSlowPath); 226 variant = PutByIdVariant::transition( 227 access.oldStructure(), access.newStructure(), chain.get(), offset); 208 228 break; 209 229 } 210 case PutByIdAccess::Setter: 230 231 case PutByIdAccess::Setter: { 232 Structure* structure = access.structure(); 233 234 ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor( 235 profiledBlock, structure, access.chain(), access.chainCount(), uid); 236 237 switch (complexGetStatus.kind()) { 238 case ComplexGetStatus::ShouldSkip: 239 continue; 240 241 case ComplexGetStatus::TakesSlowPath: 242 return PutByIdStatus(slowPathState); 243 244 case ComplexGetStatus::Inlineable: { 245 AccessorCallJITStubRoutine* stub = static_cast<AccessorCallJITStubRoutine*>( 246 access.stubRoutine()); 247 std::unique_ptr<CallLinkStatus> callLinkStatus = 248 std::make_unique<CallLinkStatus>( 249 CallLinkStatus::computeFor( 250 locker, *stub->m_callLinkInfo, callExitSiteData)); 251 252 variant = PutByIdVariant::setter( 253 structure, complexGetStatus.offset(), complexGetStatus.chain(), 254 std::move(callLinkStatus)); 255 } } 256 break; 257 } 258 211 259 case PutByIdAccess::CustomSetter: 212 260 return PutByIdStatus(MakesCalls); 213 261 214 262 default: 215 return PutByIdStatus(TakesSlowPath); 216 } 263 return PutByIdStatus(slowPathState); 264 } 265 266 if (!result.appendVariant(variant)) 267 return PutByIdStatus(slowPathState); 217 268 } 218 269 … … 230 281 #if ENABLE(DFG_JIT) 231 282 if (dfgBlock) { 283 CallLinkStatus::ExitSiteData exitSiteData; 232 284 { 233 285 ConcurrentJITLocker locker(baselineBlock->m_lock); 234 286 if (hasExitSite(locker, baselineBlock, codeOrigin.bytecodeIndex, ExitFromFTL)) 235 287 return PutByIdStatus(TakesSlowPath); 288 exitSiteData = CallLinkStatus::computeExitSiteData( 289 locker, baselineBlock, codeOrigin.bytecodeIndex, ExitFromFTL); 236 290 } 237 291 … … 239 293 { 240 294 ConcurrentJITLocker locker(dfgBlock->m_lock); 241 result = computeForStubInfo(locker, dfgBlock, dfgMap.get(codeOrigin), uid); 295 result = computeForStubInfo( 296 locker, dfgBlock, dfgMap.get(codeOrigin), uid, exitSiteData); 242 297 } 243 298 … … 276 331 277 332 unsigned attributes; 278 JSCell* specificValue; 279 PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue); 333 PropertyOffset offset = structure->getConcurrently(vm, uid, attributes); 280 334 if (isValidOffset(offset)) { 281 335 if (attributes & CustomAccessor) … … 284 338 if (attributes & (Accessor | ReadOnly)) 285 339 return PutByIdStatus(TakesSlowPath); 286 if (specificValue) { 287 // We need the PutById slow path to verify that we're storing the right value into 288 // the specialized slot. 289 return PutByIdStatus(TakesSlowPath); 290 } 340 341 WatchpointSet* replaceSet = structure->propertyReplacementWatchpointSet(offset); 342 if (!replaceSet || replaceSet->isStillValid()) { 343 // When this executes, it'll create, and fire, this replacement watchpoint set. 344 // That means that this has probably never executed or that something fishy is 345 // going on. Also, we cannot create or fire the watchpoint set from the concurrent 346 // JIT thread, so even if we wanted to do this, we'd need to have a lazy thingy. 347 // So, better leave this alone and take slow path. 348 return PutByIdStatus(TakesSlowPath); 349 } 350 291 351 if (!result.appendVariant(PutByIdVariant::replace(structure, offset))) 292 352 return PutByIdStatus(TakesSlowPath); … … 326 386 327 387 // We only optimize if there is already a structure that the transition is cached to. 328 // Among other things, this allows us to guard against a transition with a specific 329 // value. 330 // 331 // - If we're storing a value that could be specific: this would only be a problem if 332 // the existing transition did have a specific value already, since if it didn't, 333 // then we would behave "as if" we were not storing a specific value. If it did 334 // have a specific value, then we'll know - the fact that we pass 0 for 335 // specificValue will tell us. 336 // 337 // - If we're not storing a value that could be specific: again, this would only be a 338 // problem if the existing transition did have a specific value, which we check for 339 // by passing 0 for the specificValue. 340 Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, 0, offset); 388 Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset); 341 389 if (!transition) 342 return PutByIdStatus(TakesSlowPath); // This occurs in bizarre cases only. See above. 343 ASSERT(!transition->transitionDidInvolveSpecificValue()); 390 return PutByIdStatus(TakesSlowPath); 344 391 ASSERT(isValidOffset(offset)); 345 392 346 393 bool didAppend = result.appendVariant( 347 PutByIdVariant::transition(structure, transition, chain. release(), offset));394 PutByIdVariant::transition(structure, transition, chain.get(), offset)); 348 395 if (!didAppend) 349 396 return PutByIdStatus(TakesSlowPath); … … 351 398 352 399 return result; 400 } 401 402 bool PutByIdStatus::makesCalls() const 403 { 404 if (m_state == MakesCalls) 405 return true; 406 407 if (m_state != Simple) 408 return false; 409 410 for (unsigned i = m_variants.size(); i--;) { 411 if (m_variants[i].makesCalls()) 412 return true; 413 } 414 415 return false; 353 416 } 354 417 -
trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.h
r171660 r172129 27 27 #define PutByIdStatus_h 28 28 29 #include "CallLinkStatus.h" 29 30 #include "ExitingJITType.h" 30 31 #include "PutByIdVariant.h" … … 81 82 bool isSimple() const { return m_state == Simple; } 82 83 bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; } 83 bool makesCalls() const { return m_state == MakesCalls; }84 bool makesCalls() const; 84 85 85 86 size_t numVariants() const { return m_variants.size(); } … … 95 96 #endif 96 97 #if ENABLE(JIT) 97 static PutByIdStatus computeForStubInfo(const ConcurrentJITLocker&, CodeBlock*, StructureStubInfo*, StringImpl* uid); 98 static PutByIdStatus computeForStubInfo( 99 const ConcurrentJITLocker&, CodeBlock*, StructureStubInfo*, StringImpl* uid, 100 CallLinkStatus::ExitSiteData); 98 101 #endif 99 102 static PutByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, StringImpl* uid); -
trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.cpp
r171666 r172129 27 27 #include "PutByIdVariant.h" 28 28 29 #include "CallLinkStatus.h" 30 #include "JSCInlines.h" 29 31 #include <wtf/ListDump.h> 30 32 31 33 namespace JSC { 34 35 PutByIdVariant::PutByIdVariant(const PutByIdVariant& other) 36 : PutByIdVariant() 37 { 38 *this = other; 39 } 40 41 PutByIdVariant& PutByIdVariant::operator=(const PutByIdVariant& other) 42 { 43 m_kind = other.m_kind; 44 m_oldStructure = other.m_oldStructure; 45 m_newStructure = other.m_newStructure; 46 m_constantChecks = other.m_constantChecks; 47 m_alternateBase = other.m_alternateBase; 48 m_offset = other.m_offset; 49 if (other.m_callLinkStatus) 50 m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus); 51 else 52 m_callLinkStatus = nullptr; 53 return *this; 54 } 55 56 PutByIdVariant PutByIdVariant::replace(const StructureSet& structure, PropertyOffset offset) 57 { 58 PutByIdVariant result; 59 result.m_kind = Replace; 60 result.m_oldStructure = structure; 61 result.m_offset = offset; 62 return result; 63 } 64 65 PutByIdVariant PutByIdVariant::transition( 66 const StructureSet& oldStructure, Structure* newStructure, 67 const IntendedStructureChain* structureChain, PropertyOffset offset) 68 { 69 PutByIdVariant result; 70 result.m_kind = Transition; 71 result.m_oldStructure = oldStructure; 72 result.m_newStructure = newStructure; 73 if (structureChain) 74 structureChain->gatherChecks(result.m_constantChecks); 75 result.m_offset = offset; 76 return result; 77 } 78 79 PutByIdVariant PutByIdVariant::setter( 80 const StructureSet& structure, PropertyOffset offset, 81 IntendedStructureChain* chain, std::unique_ptr<CallLinkStatus> callLinkStatus) 82 { 83 PutByIdVariant result; 84 result.m_kind = Setter; 85 result.m_oldStructure = structure; 86 if (chain) { 87 chain->gatherChecks(result.m_constantChecks); 88 result.m_alternateBase = chain->terminalPrototype(); 89 } 90 result.m_offset = offset; 91 result.m_callLinkStatus = std::move(callLinkStatus); 92 return result; 93 } 32 94 33 95 Structure* PutByIdVariant::oldStructureForTransition() const … … 47 109 bool PutByIdVariant::writesStructures() const 48 110 { 49 return kind() == Transition; 111 switch (kind()) { 112 case Transition: 113 case Setter: 114 return true; 115 default: 116 return false; 117 } 50 118 } 51 119 52 120 bool PutByIdVariant::reallocatesStorage() const 53 121 { 54 if (kind() != Transition) 55 return false; 56 57 if (oldStructureForTransition()->outOfLineCapacity() == newStructure()->outOfLineCapacity()) 58 return false; 59 60 return true; 122 switch (kind()) { 123 case Transition: 124 return oldStructureForTransition()->outOfLineCapacity() != newStructure()->outOfLineCapacity(); 125 case Setter: 126 return true; 127 default: 128 return false; 129 } 130 } 131 132 bool PutByIdVariant::makesCalls() const 133 { 134 return kind() == Setter; 135 } 136 137 StructureSet PutByIdVariant::baseStructure() const 138 { 139 ASSERT(kind() == Setter); 140 141 if (!m_alternateBase) 142 return structure(); 143 144 Structure* structure = structureFor(m_constantChecks, m_alternateBase); 145 RELEASE_ASSERT(structure); 146 return structure; 61 147 } 62 148 … … 140 226 case Replace: 141 227 out.print( 142 "<Replace: ", inContext(structure(), context), ", ", offset(), ">");228 "<Replace: ", inContext(structure(), context), ", offset = ", offset(), ">"); 143 229 return; 144 230 … … 147 233 "<Transition: ", inContext(oldStructure(), context), " -> ", 148 234 pointerDumpInContext(newStructure(), context), ", [", 149 listDumpInContext(constantChecks(), context), "], ", offset(), ">"); 235 listDumpInContext(constantChecks(), context), "], offset = ", offset(), ">"); 236 return; 237 238 case Setter: 239 out.print( 240 "<Setter: ", inContext(structure(), context), ", [", 241 listDumpInContext(constantChecks(), context), "]"); 242 if (m_alternateBase) 243 out.print(", alternateBase = ", inContext(JSValue(m_alternateBase), context)); 244 out.print(", offset = ", m_offset); 245 out.print(", call = ", *m_callLinkStatus); 246 out.print(">"); 150 247 return; 151 248 } -
trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.h
r171660 r172129 33 33 namespace JSC { 34 34 35 class CallLinkStatus; 36 35 37 class PutByIdVariant { 36 38 public: … … 38 40 NotSet, 39 41 Replace, 40 Transition 42 Transition, 43 Setter 41 44 }; 42 45 … … 44 47 : m_kind(NotSet) 45 48 , m_newStructure(nullptr) 49 , m_alternateBase(nullptr) 46 50 , m_offset(invalidOffset) 47 51 { 48 52 } 49 53 50 static PutByIdVariant replace(const StructureSet& structure, PropertyOffset offset) 51 { 52 PutByIdVariant result; 53 result.m_kind = Replace; 54 result.m_oldStructure = structure; 55 result.m_offset = offset; 56 return result; 57 } 54 PutByIdVariant(const PutByIdVariant&); 55 PutByIdVariant& operator=(const PutByIdVariant&); 56 57 static PutByIdVariant replace( 58 const StructureSet& structure, PropertyOffset offset); 58 59 59 60 static PutByIdVariant transition( 60 61 const StructureSet& oldStructure, Structure* newStructure, 61 PassRefPtr<IntendedStructureChain> structureChain, PropertyOffset offset) 62 { 63 PutByIdVariant result; 64 result.m_kind = Transition; 65 result.m_oldStructure = oldStructure; 66 result.m_newStructure = newStructure; 67 if (structureChain) 68 structureChain->gatherChecks(result.m_constantChecks); 69 result.m_offset = offset; 70 return result; 71 } 62 const IntendedStructureChain* structureChain, PropertyOffset offset); 63 64 static PutByIdVariant setter( 65 const StructureSet& structure, PropertyOffset offset, 66 IntendedStructureChain* chain, std::unique_ptr<CallLinkStatus> callLinkStatus); 72 67 73 68 Kind kind() const { return m_kind; } … … 78 73 const StructureSet& structure() const 79 74 { 80 ASSERT(kind() == Replace );75 ASSERT(kind() == Replace || kind() == Setter); 81 76 return m_oldStructure; 82 77 } … … 84 79 const StructureSet& oldStructure() const 85 80 { 86 ASSERT(kind() == Transition || kind() == Replace );81 ASSERT(kind() == Transition || kind() == Replace || kind() == Setter); 87 82 return m_oldStructure; 88 83 } … … 90 85 StructureSet& oldStructure() 91 86 { 92 ASSERT(kind() == Transition || kind() == Replace );87 ASSERT(kind() == Transition || kind() == Replace || kind() == Setter); 93 88 return m_oldStructure; 94 89 } … … 104 99 bool writesStructures() const; 105 100 bool reallocatesStorage() const; 101 bool makesCalls() const; 106 102 107 103 const ConstantStructureCheckVector& constantChecks() const … … 116 112 } 117 113 114 JSObject* alternateBase() const 115 { 116 ASSERT(kind() == Setter); 117 return m_alternateBase; 118 } 119 120 StructureSet baseStructure() const; 121 122 CallLinkStatus* callLinkStatus() const 123 { 124 ASSERT(kind() == Setter); 125 return m_callLinkStatus.get(); 126 } 127 118 128 bool attemptToMerge(const PutByIdVariant& other); 119 129 … … 128 138 Structure* m_newStructure; 129 139 ConstantStructureCheckVector m_constantChecks; 140 JSObject* m_alternateBase; 130 141 PropertyOffset m_offset; 142 std::unique_ptr<CallLinkStatus> m_callLinkStatus; 131 143 }; 132 144 -
trunk/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp
r163844 r172129 45 45 } 46 46 47 void StructureStubClearingWatchpoint::fireInternal( )47 void StructureStubClearingWatchpoint::fireInternal(const FireDetail&) 48 48 { 49 49 // This will implicitly cause my own demise: stub reset removes all watchpoints. -
trunk/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h
r164424 r172129 69 69 70 70 protected: 71 virtual void fireInternal( ) override;71 virtual void fireInternal(const FireDetail&) override; 72 72 73 73 private: -
trunk/Source/JavaScriptCore/bytecode/TypeLocation.h
r171660 r172129 33 33 enum HighFidelityGlobalIDFlags { 34 34 HighFidelityNeedsUniqueIDGeneration = -1, 35 HighFidelityNoGlobalIDExists = -2 35 HighFidelityNoGlobalIDExists = -2, 36 HighFidelityReturnStatement = -3 36 37 }; 37 38 38 39 class TypeLocation { 39 40 40 public: 41 41 TypeLocation() … … 47 47 int64_t m_globalVariableID; 48 48 intptr_t m_sourceID; 49 unsigned m_line; 50 unsigned m_column; 49 unsigned m_divotStart; 50 unsigned m_divotEnd; 51 unsigned m_divotForFunctionOffsetIfReturnStatement; 51 52 RefPtr<TypeSet> m_instructionTypeSet; 52 53 RefPtr<TypeSet> m_globalTypeSet; -
trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
r171939 r172129 401 401 } 402 402 403 bool UnlinkedCodeBlock::highFidelityTypeProfileExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot) 404 { 405 static const bool verbose = false; 406 auto iter = m_highFidelityTypeProfileInfoMap.find(bytecodeOffset); 407 if (iter == m_highFidelityTypeProfileInfoMap.end()) { 408 if (verbose) 409 dataLogF("Don't have assignment info for offset:%u\n", bytecodeOffset); 410 startDivot = UINT_MAX; 411 endDivot = UINT_MAX; 412 return false; 413 } 414 415 HighFidelityTypeProfileExpressionRange& range = iter->value; 416 startDivot = range.m_startDivot; 417 endDivot = range.m_endDivot; 418 return true; 419 } 420 421 void UnlinkedCodeBlock::addHighFidelityTypeProfileExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot) 422 { 423 HighFidelityTypeProfileExpressionRange range; 424 range.m_startDivot = startDivot; 425 range.m_endDivot = endDivot; 426 m_highFidelityTypeProfileInfoMap.set(instructionOffset, range); 427 } 428 403 429 void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) 404 430 { -
trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
r171939 r172129 273 273 int startOffset, int endOffset, unsigned line, unsigned column); 274 274 275 void addHighFidelityTypeProfileExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot); 276 275 277 bool hasExpressionInfo() { return m_expressionInfo.size(); } 276 278 … … 465 467 int& startOffset, int& endOffset, unsigned& line, unsigned& column); 466 468 469 bool highFidelityTypeProfileExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot); 470 467 471 void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn) 468 472 { … … 576 580 OwnPtr<RareData> m_rareData; 577 581 Vector<ExpressionRangeInfo> m_expressionInfo; 582 struct HighFidelityTypeProfileExpressionRange { 583 unsigned m_startDivot; 584 unsigned m_endDivot; 585 }; 586 HashMap<unsigned, HighFidelityTypeProfileExpressionRange> m_highFidelityTypeProfileInfoMap; 578 587 579 588 protected: -
trunk/Source/JavaScriptCore/bytecode/VariableWatchpointSet.h
r168443 r172129 32 32 namespace JSC { 33 33 34 class JSObject; 34 35 class SymbolTable; 36 37 class VariableWriteFireDetail : public FireDetail { 38 public: 39 VariableWriteFireDetail(JSObject* object, const PropertyName& name) 40 : m_object(object) 41 , m_name(name) 42 { 43 } 44 45 virtual void dump(PrintStream&) const override; 46 47 private: 48 JSObject* m_object; 49 const PropertyName& m_name; 50 }; 35 51 36 52 class VariableWatchpointSet : public WatchpointSet { … … 58 74 JSValue inferredValue() const { return m_inferredValue.get(); } 59 75 60 inline void notifyWrite(VM&, JSValue); 76 void notifyWrite(VM&, JSValue, const FireDetail&); 77 JS_EXPORT_PRIVATE void notifyWrite(VM&, JSValue, JSObject* baseObject, const PropertyName&); 78 void notifyWrite(VM&, JSValue, const char* reason); 61 79 62 void invalidate( )80 void invalidate(const FireDetail& detail) 63 81 { 64 82 m_inferredValue.clear(); 65 WatchpointSet::invalidate( );83 WatchpointSet::invalidate(detail); 66 84 } 67 85 68 void finalizeUnconditionally( )86 void finalizeUnconditionally(const FireDetail& detail) 69 87 { 70 88 ASSERT(!!m_inferredValue == (state() == IsWatched)); … … 77 95 if (Heap::isMarked(cell)) 78 96 return; 79 invalidate( );97 invalidate(detail); 80 98 } 81 99 -
trunk/Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h
r168443 r172129 32 32 namespace JSC { 33 33 34 inline void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value )34 inline void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value, const FireDetail& detail) 35 35 { 36 36 ASSERT(!!value); … … 45 45 if (value == m_inferredValue.get()) 46 46 return; 47 invalidate( );47 invalidate(detail); 48 48 return; 49 49 … … 55 55 ASSERT_NOT_REACHED(); 56 56 } 57 57 58 58 } // namespace JSC 59 59 -
trunk/Source/JavaScriptCore/bytecode/Watchpoint.cpp
r170876 r172129 1 1 /* 2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 31 31 32 32 namespace JSC { 33 34 void StringFireDetail::dump(PrintStream& out) const 35 { 36 out.print(m_string); 37 } 33 38 34 39 Watchpoint::~Watchpoint() … … 65 70 } 66 71 67 void WatchpointSet::fireAllSlow( )72 void WatchpointSet::fireAllSlow(const FireDetail& detail) 68 73 { 69 74 ASSERT(state() == IsWatched); 70 75 71 76 WTF::storeStoreFence(); 72 fireAllWatchpoints( );77 fireAllWatchpoints(detail); 73 78 m_state = IsInvalidated; 74 79 WTF::storeStoreFence(); 75 80 } 76 81 77 void WatchpointSet::fireAllWatchpoints() 82 void WatchpointSet::fireAllSlow(const char* reason) 83 { 84 fireAllSlow(StringFireDetail(reason)); 85 } 86 87 void WatchpointSet::fireAllWatchpoints(const FireDetail& detail) 78 88 { 79 89 while (!m_set.isEmpty()) 80 m_set.begin()->fire( );90 m_set.begin()->fire(detail); 81 91 } 82 92 … … 84 94 { 85 95 inflate()->add(watchpoint); 96 } 97 98 void InlineWatchpointSet::fireAll(const char* reason) 99 { 100 fireAll(StringFireDetail(reason)); 86 101 } 87 102 -
trunk/Source/JavaScriptCore/bytecode/Watchpoint.h
r168548 r172129 1 1 /* 2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 28 28 29 29 #include <wtf/Atomics.h> 30 #include <wtf/PrintStream.h> 30 31 #include <wtf/SentinelLinkedList.h> 31 32 #include <wtf/ThreadSafeRefCounted.h> … … 33 34 namespace JSC { 34 35 36 class FireDetail { 37 public: 38 FireDetail() 39 { 40 } 41 42 virtual ~FireDetail() 43 { 44 } 45 46 virtual void dump(PrintStream&) const = 0; 47 }; 48 49 class StringFireDetail : public FireDetail { 50 public: 51 StringFireDetail(const char* string) 52 : m_string(string) 53 { 54 } 55 56 virtual void dump(PrintStream& out) const override; 57 58 private: 59 const char* m_string; 60 }; 61 35 62 class Watchpoint : public BasicRawSentinelNode<Watchpoint> { 36 63 public: … … 41 68 virtual ~Watchpoint(); 42 69 43 void fire( ) { fireInternal(); }70 void fire(const FireDetail& detail) { fireInternal(detail); } 44 71 45 72 protected: 46 virtual void fireInternal( ) = 0;73 virtual void fireInternal(const FireDetail&) = 0; 47 74 }; 48 75 … … 103 130 } 104 131 105 void fireAll() 106 { 107 if (state() != IsWatched) 108 return; 109 fireAllSlow(); 110 } 111 112 void touch() 132 void fireAll(const FireDetail& detail) 133 { 134 if (LIKELY(state() != IsWatched)) 135 return; 136 fireAllSlow(detail); 137 } 138 139 void fireAll(const char* reason) 140 { 141 if (LIKELY(state() != IsWatched)) 142 return; 143 fireAllSlow(reason); 144 } 145 146 void touch(const FireDetail& detail) 113 147 { 114 148 if (state() == ClearWatchpoint) 115 149 startWatching(); 116 150 else 117 fireAll( );118 } 119 120 void invalidate( )151 fireAll(detail); 152 } 153 154 void invalidate(const FireDetail& detail) 121 155 { 122 156 if (state() == IsWatched) 123 fireAll( );157 fireAll(detail); 124 158 m_state = IsInvalidated; 125 159 } … … 128 162 int8_t* addressOfSetIsNotEmpty() { return &m_setIsNotEmpty; } 129 163 130 JS_EXPORT_PRIVATE void fireAllSlow(); // Call only if you've checked isWatched. 164 JS_EXPORT_PRIVATE void fireAllSlow(const FireDetail&); // Call only if you've checked isWatched. 165 JS_EXPORT_PRIVATE void fireAllSlow(const char* reason); // Ditto. 131 166 132 167 private: 133 void fireAllWatchpoints( );168 void fireAllWatchpoints(const FireDetail&); 134 169 135 170 friend class InlineWatchpointSet; … … 207 242 } 208 243 209 void fireAll( )244 void fireAll(const FireDetail& detail) 210 245 { 211 246 if (isFat()) { 212 fat()->fireAll( );247 fat()->fireAll(detail); 213 248 return; 214 249 } … … 219 254 } 220 255 221 void touch() 256 JS_EXPORT_PRIVATE void fireAll(const char* reason); 257 258 void touch(const FireDetail& detail) 222 259 { 223 260 if (isFat()) { 224 fat()->touch( );261 fat()->touch(detail); 225 262 return; 226 263 } … … 232 269 } 233 270 271 void touch(const char* reason) 272 { 273 touch(StringFireDetail(reason)); 274 } 275 234 276 private: 235 277 static const uintptr_t IsThinFlag = 1; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r171660 r172129 1006 1006 1007 1007 if (!dst->isTemporary() && isProfilingTypesWithHighFidelity()) 1008 emitProfileTypesWithHighFidelity(dst, true);1008 emitProfileTypesWithHighFidelity(dst, ProfileTypesBytecodeHasGlobalID); 1009 1009 1010 1010 return dst; … … 1117 1117 } 1118 1118 1119 void BytecodeGenerator::emitProfileTypesWithHighFidelity(RegisterID* registerToProfile, bool hasGlobalID)1119 void BytecodeGenerator::emitProfileTypesWithHighFidelity(RegisterID* registerToProfile, ProfileTypesWithHighFidelityBytecodeFlag flag) 1120 1120 { 1121 1121 emitOpcode(op_profile_types_with_high_fidelity); 1122 1122 instructions().append(registerToProfile->index()); 1123 instructions().append(0); // placeholder for TypeLocation 1124 // This is a flag indicating whether we should track this value to its globalID or not. 1125 if (hasGlobalID) 1126 instructions().append(1); 1127 else 1128 instructions().append(0); 1123 instructions().append(0); // This is a placeholder for the TypeLocation object pointer. 1124 instructions().append(flag); 1129 1125 } 1130 1126 … … 1268 1264 } 1269 1265 1266 RegisterID* BytecodeGenerator::emitGetFromScopeWithProfile(RegisterID* dst, RegisterID* scope, const Identifier& identifier, ResolveMode resolveMode) 1267 { 1268 m_codeBlock->addPropertyAccessInstruction(instructions().size()); 1269 1270 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_from_scope_with_profile); 1271 instructions().append(kill(dst)); 1272 instructions().append(scope->index()); 1273 instructions().append(addConstant(identifier)); 1274 instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand()); 1275 instructions().append(0); 1276 instructions().append(0); 1277 instructions().append(profile); 1278 instructions().append(0); // This is a placeholder for a TypeLocation pointer. 1279 return dst; 1280 } 1281 1270 1282 RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Identifier& identifier, RegisterID* value, ResolveMode resolveMode) 1271 1283 { … … 1273 1285 1274 1286 // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand 1275 if (isProfilingTypesWithHighFidelity()) 1276 emitOpcode(op_put_to_scope_with_profile); 1277 else 1278 emitOpcode(op_put_to_scope); 1287 emitOpcode(op_put_to_scope); 1279 1288 instructions().append(scope->index()); 1280 1289 instructions().append(addConstant(identifier)); … … 1283 1292 instructions().append(0); 1284 1293 instructions().append(0); 1285 if (isProfilingTypesWithHighFidelity()) 1286 instructions().append(0); 1294 return value; 1295 } 1296 1297 RegisterID* BytecodeGenerator::emitPutToScopeWithProfile(RegisterID* scope, const Identifier& identifier, RegisterID* value, ResolveMode resolveMode) 1298 { 1299 m_codeBlock->addPropertyAccessInstruction(instructions().size()); 1300 1301 emitOpcode(op_put_to_scope_with_profile); 1302 instructions().append(scope->index()); 1303 instructions().append(addConstant(identifier)); 1304 instructions().append(value->index()); 1305 instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand()); 1306 instructions().append(0); 1307 instructions().append(0); 1308 instructions().append(0); // This is a placeholder for a TypeLocation pointer. 1287 1309 return value; 1288 1310 } … … 1351 1373 instructions().append(0); 1352 1374 instructions().append(0); 1353 1354 if (isProfilingTypesWithHighFidelity())1355 emitProfileTypesWithHighFidelity(value, false);1356 1375 1357 1376 return value; … … 1451 1470 instructions().append(value->index()); 1452 1471 instructions().append(arrayProfile); 1453 1454 if (isProfilingTypesWithHighFidelity())1455 emitProfileTypesWithHighFidelity(value, false);1456 1472 1457 1473 return value; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r171660 r172129 156 156 }; 157 157 158 enum ProfileTypesWithHighFidelityBytecodeFlag { 159 ProfileTypesBytecodeHasGlobalID, 160 ProfileTypesBytecodeDoesNotHaveGlobalID, 161 ProfileTypesBytecodeFunctionArgument, 162 ProfileTypesBytecodeFunctionThisObject, 163 ProfileTypesBytecodeFunctionReturnStatement 164 }; 165 158 166 class BytecodeGenerator { 159 167 WTF_MAKE_FAST_ALLOCATED; … … 317 325 } 318 326 327 void emitHighFidelityTypeProfilingExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot) 328 { 329 unsigned start = startDivot.offset + 1; // Ranges are inclusive of their endpoints, AND 1 indexed. 330 unsigned end = endDivot.offset; // End Ranges already go one past the inclusive range, so no need to do + 1 - 1. 331 unsigned instructionOffset = instructions().size() - 1; 332 m_codeBlock->addHighFidelityTypeProfileExpressionInfo(instructionOffset, start, end); 333 } 334 319 335 ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure) 320 336 { … … 333 349 } 334 350 335 void emitProfileTypesWithHighFidelity(RegisterID* dst, bool);351 void emitProfileTypesWithHighFidelity(RegisterID* dst, ProfileTypesWithHighFidelityBytecodeFlag); 336 352 337 353 RegisterID* emitLoad(RegisterID* dst, bool); … … 400 416 RegisterID* emitResolveScope(RegisterID* dst, const Identifier&); 401 417 RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier&, ResolveMode); 418 RegisterID* emitGetFromScopeWithProfile(RegisterID* dst, RegisterID* scope, const Identifier&, ResolveMode); 402 419 RegisterID* emitPutToScope(RegisterID* scope, const Identifier&, RegisterID* value, ResolveMode); 420 RegisterID* emitPutToScopeWithProfile(RegisterID* scope, const Identifier&, RegisterID* value, ResolveMode); 403 421 404 422 PassRefPtr<Label> emitLabel(Label*); -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r171660 r172129 153 153 if (dst == generator.ignoredResult()) 154 154 return 0; 155 if (generator.isProfilingTypesWithHighFidelity()) { 156 generator.emitProfileTypesWithHighFidelity(local.get(), ProfileTypesBytecodeHasGlobalID); 157 generator.emitHighFidelityTypeProfilingExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1)); 158 } 155 159 return generator.moveToDestinationIfNeeded(dst, local.get()); 156 160 } … … 159 163 generator.emitExpressionInfo(divot, m_start, divot); 160 164 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident); 161 return generator.emitGetFromScope(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound); 165 RegisterID* ret; 166 if (generator.isProfilingTypesWithHighFidelity()) { 167 ret = generator.emitGetFromScopeWithProfile(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound); 168 generator.emitHighFidelityTypeProfilingExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1)); 169 } else 170 ret = generator.emitGetFromScope(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound); 171 return ret; 162 172 } 163 173 … … 375 385 RegisterID* property = generator.emitNode(m_subscript); 376 386 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 377 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property); 387 RegisterID* finalDest = generator.finalDestination(dst); 388 RegisterID* ret = generator.emitGetByVal(finalDest, base.get(), property); 389 if (generator.isProfilingTypesWithHighFidelity()) { 390 generator.emitProfileTypesWithHighFidelity(finalDest, ProfileTypesBytecodeDoesNotHaveGlobalID); 391 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 392 } 393 return ret; 378 394 } 379 395 … … 395 411 RegisterID* base = generator.emitNode(m_base); 396 412 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 397 return generator.emitGetById(generator.finalDestination(dst), base, m_ident); 413 RegisterID* finalDest = generator.finalDestination(dst); 414 RegisterID* ret = generator.emitGetById(finalDest, base, m_ident); 415 if (generator.isProfilingTypesWithHighFidelity()) { 416 generator.emitProfileTypesWithHighFidelity(finalDest, ProfileTypesBytecodeDoesNotHaveGlobalID); 417 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 418 } 419 return ret; 398 420 } 399 421 … … 474 496 CallArguments callArguments(generator, m_args); 475 497 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 476 return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 498 RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 499 if (generator.isProfilingTypesWithHighFidelity()) { 500 generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID); 501 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 502 } 503 return ret; 477 504 } 478 505 … … 490 517 // This passes NoExpectedFunction because we expect that if the function is in a 491 518 // local variable, then it's not one of our built-in constructors. 492 return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 519 RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 520 if (generator.isProfilingTypesWithHighFidelity()) { 521 generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID); 522 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 523 } 524 return ret; 493 525 } 494 526 … … 501 533 generator.emitResolveScope(callArguments.thisRegister(), m_ident); 502 534 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound); 503 return generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd()); 535 RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd()); 536 if (generator.isProfilingTypesWithHighFidelity()) { 537 generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID); 538 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 539 } 540 return ret; 504 541 } 505 542 … … 515 552 CallArguments callArguments(generator, m_args); 516 553 generator.emitMove(callArguments.thisRegister(), base.get()); 517 return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 554 RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 555 if (generator.isProfilingTypesWithHighFidelity()) { 556 generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID); 557 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 558 } 559 return ret; 518 560 } 519 561 … … 528 570 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd()); 529 571 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident); 530 return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 572 RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 573 if (generator.isProfilingTypesWithHighFidelity()) { 574 generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID); 575 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 576 } 577 return ret; 531 578 } 532 579 … … 597 644 } 598 645 generator.emitLabel(end.get()); 646 } 647 if (generator.isProfilingTypesWithHighFidelity()) { 648 generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID); 649 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 599 650 } 600 651 return returnValue.get(); … … 708 759 generator.emitLabel(end.get()); 709 760 } 761 if (generator.isProfilingTypesWithHighFidelity()) { 762 generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID); 763 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 764 } 710 765 return returnValue.get(); 711 766 } … … 748 803 generator.emitMove(tempDstSrc.get(), localReg); 749 804 emitIncOrDec(generator, tempDstSrc.get(), m_operator); 805 generator.emitMove(localReg, tempDstSrc.get()); 750 806 if (generator.isProfilingTypesWithHighFidelity()) 751 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 752 generator.emitMove(localReg, tempDstSrc.get()); 807 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 753 808 return tempDst.get(); 754 809 } … … 760 815 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound); 761 816 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); 762 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound); 817 if (generator.isProfilingTypesWithHighFidelity()) { 818 generator.emitPutToScopeWithProfile(scope.get(), ident, value.get(), ThrowIfNotFound); 819 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 820 } else 821 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound); 822 763 823 return oldValue.get(); 764 824 } … … 782 842 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 783 843 generator.emitPutByVal(base.get(), property.get(), value.get()); 844 if (generator.isProfilingTypesWithHighFidelity()) { 845 generator.emitProfileTypesWithHighFidelity(value.get(), ProfileTypesBytecodeDoesNotHaveGlobalID); 846 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 847 } 784 848 return generator.moveToDestinationIfNeeded(dst, oldValue); 785 849 } … … 802 866 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 803 867 generator.emitPutById(base.get(), ident, value.get()); 868 if (generator.isProfilingTypesWithHighFidelity()) { 869 generator.emitProfileTypesWithHighFidelity(value.get(), ProfileTypesBytecodeDoesNotHaveGlobalID); 870 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 871 } 804 872 return generator.moveToDestinationIfNeeded(dst, oldValue); 805 873 } … … 922 990 generator.emitMove(tempDst.get(), localReg); 923 991 emitIncOrDec(generator, tempDst.get(), m_operator); 992 generator.emitMove(localReg, tempDst.get()); 924 993 if (generator.isProfilingTypesWithHighFidelity()) 925 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 926 generator.emitMove(localReg, tempDst.get()); 994 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 927 995 return generator.moveToDestinationIfNeeded(dst, tempDst.get()); 928 996 } … … 935 1003 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound); 936 1004 emitIncOrDec(generator, value.get(), m_operator); 937 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound); 1005 if (generator.isProfilingTypesWithHighFidelity()) { 1006 generator.emitPutToScopeWithProfile(scope.get(), ident, value.get(), ThrowIfNotFound); 1007 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 1008 } else 1009 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound); 938 1010 return generator.moveToDestinationIfNeeded(dst, value.get()); 939 1011 } … … 955 1027 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 956 1028 generator.emitPutByVal(base.get(), property.get(), value); 1029 if (generator.isProfilingTypesWithHighFidelity()) { 1030 generator.emitProfileTypesWithHighFidelity(value, ProfileTypesBytecodeDoesNotHaveGlobalID); 1031 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 1032 } 957 1033 return generator.moveToDestinationIfNeeded(dst, propDst.get()); 958 1034 } … … 973 1049 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 974 1050 generator.emitPutById(base.get(), ident, value); 1051 if (generator.isProfilingTypesWithHighFidelity()) { 1052 generator.emitProfileTypesWithHighFidelity(value, ProfileTypesBytecodeDoesNotHaveGlobalID); 1053 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 1054 } 975 1055 return generator.moveToDestinationIfNeeded(dst, propDst.get()); 976 1056 } … … 1425 1505 generator.emitMove(result.get(), local.get()); 1426 1506 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1507 generator.emitMove(local.get(), result.get()); 1427 1508 if (generator.isProfilingTypesWithHighFidelity()) 1428 generator.emitExpressionInfo(newDivot, divotStart(), newDivot); 1429 generator.emitMove(local.get(), result.get()); 1509 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 1430 1510 return generator.moveToDestinationIfNeeded(dst, result.get()); 1431 1511 } … … 1439 1519 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound); 1440 1520 RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this); 1441 return generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound); 1521 RegisterID* ret; 1522 if (generator.isProfilingTypesWithHighFidelity()) { 1523 ret = generator.emitPutToScopeWithProfile(scope.get(), m_ident, result.get(), ThrowIfNotFound); 1524 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 1525 } else 1526 ret = generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound); 1527 return ret; 1442 1528 } 1443 1529 … … 1454 1540 RefPtr<RegisterID> tempDst = generator.tempDestination(dst); 1455 1541 generator.emitNode(tempDst.get(), m_right); 1542 generator.emitMove(local.get(), tempDst.get()); 1456 1543 if (generator.isProfilingTypesWithHighFidelity()) 1457 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1458 generator.emitMove(local.get(), tempDst.get()); 1544 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 1459 1545 return generator.moveToDestinationIfNeeded(dst, tempDst.get()); 1460 1546 } … … 1470 1556 RefPtr<RegisterID> result = generator.emitNode(dst, m_right); 1471 1557 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1472 return generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 1558 RegisterID* ret; 1559 if (generator.isProfilingTypesWithHighFidelity()) { 1560 ret = generator.emitPutToScopeWithProfile(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 1561 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 1562 } else 1563 ret = generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 1564 return ret; 1473 1565 } 1474 1566 … … 1483 1575 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result); 1484 1576 generator.emitPutById(base.get(), m_ident, forwardResult); 1577 if (generator.isProfilingTypesWithHighFidelity()) { 1578 generator.emitProfileTypesWithHighFidelity(forwardResult, ProfileTypesBytecodeDoesNotHaveGlobalID); 1579 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 1580 } 1485 1581 return generator.moveToDestinationIfNeeded(dst, forwardResult); 1486 1582 } … … 1497 1593 1498 1594 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1499 return generator.emitPutById(base.get(), m_ident, updatedValue); 1595 RegisterID* ret = generator.emitPutById(base.get(), m_ident, updatedValue); 1596 if (generator.isProfilingTypesWithHighFidelity()) { 1597 generator.emitProfileTypesWithHighFidelity(updatedValue, ProfileTypesBytecodeDoesNotHaveGlobalID); 1598 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 1599 } 1600 return ret; 1500 1601 } 1501 1602 … … 1519 1620 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result); 1520 1621 generator.emitPutByVal(base.get(), property.get(), forwardResult); 1622 if (generator.isProfilingTypesWithHighFidelity()) { 1623 generator.emitProfileTypesWithHighFidelity(forwardResult, ProfileTypesBytecodeDoesNotHaveGlobalID); 1624 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 1625 } 1521 1626 return generator.moveToDestinationIfNeeded(dst, forwardResult); 1522 1627 } … … 1535 1640 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1536 1641 generator.emitPutByVal(base.get(), property.get(), updatedValue); 1642 if (generator.isProfilingTypesWithHighFidelity()) { 1643 generator.emitProfileTypesWithHighFidelity(updatedValue, ProfileTypesBytecodeDoesNotHaveGlobalID); 1644 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 1645 } 1537 1646 1538 1647 return updatedValue; … … 2023 2132 2024 2133 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined()); 2134 if (generator.isProfilingTypesWithHighFidelity()) { 2135 generator.emitProfileTypesWithHighFidelity(returnRegister.get(), ProfileTypesBytecodeFunctionReturnStatement); 2136 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd()); 2137 } 2025 2138 if (generator.scopeDepth()) { 2026 2139 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get()); … … 2350 2463 void FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 2351 2464 { 2465 if (generator.isProfilingTypesWithHighFidelity()) { 2466 JSTextPosition start(-1, m_startStartOffset, -1); // This divot is at the open brace of the function. 2467 JSTextPosition end(-1, m_startStartOffset + 1, -1); 2468 generator.emitProfileTypesWithHighFidelity(generator.thisRegister(), ProfileTypesBytecodeFunctionThisObject); 2469 generator.emitHighFidelityTypeProfilingExpressionInfo(start, end); 2470 for (size_t i = 0; i < m_parameters->size(); i++) { 2471 // FIXME: Handle Destructuring assignments into arguments. 2472 if (!m_parameters->at(i)->isBindingNode()) 2473 continue; 2474 BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i)); 2475 RegisterID reg(CallFrame::argumentOffset(i)); 2476 generator.emitProfileTypesWithHighFidelity(®, ProfileTypesBytecodeFunctionArgument); 2477 generator.emitHighFidelityTypeProfilingExpressionInfo(parameter->divotStart(), parameter->divotEnd()); 2478 } 2479 } 2480 2352 2481 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset()); 2353 2482 emitStatementsBytecode(generator, generator.ignoredResult()); … … 2366 2495 if (!returnNode) { 2367 2496 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined()); 2497 if (generator.isProfilingTypesWithHighFidelity()) 2498 generator.emitProfileTypesWithHighFidelity(r0, ProfileTypesBytecodeFunctionReturnStatement); // Do not emit expression info for this profile because it's not in the user's source code. 2368 2499 ASSERT(startOffset() >= lineStartOffset()); 2369 2500 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset()); -
trunk/Source/JavaScriptCore/debugger/Debugger.h
r170677 r172129 34 34 namespace JSC { 35 35 36 class CodeBlock; 36 37 class ExecState; 37 38 class JSGlobalObject; -
trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
r165676 r172129 31 31 32 32 #include "CodeBlock.h" 33 #include "DebuggerScope.h" 33 34 #include "Interpreter.h" 34 35 #include "JSActivation.h" … … 37 38 #include "Parser.h" 38 39 #include "StackVisitor.h" 40 #include "StrongInlines.h" 39 41 40 42 namespace JSC { … … 107 109 } 108 110 109 JSScope* DebuggerCallFrame::scope() const 110 { 111 ASSERT(isValid()); 112 if (!isValid()) 113 return 0; 114 115 CodeBlock* codeBlock = m_callFrame->codeBlock(); 116 if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) { 117 JSActivation* activation = JSActivation::create(*codeBlock->vm(), m_callFrame, codeBlock); 118 m_callFrame->setActivation(activation); 119 m_callFrame->setScope(activation); 120 } 121 122 return m_callFrame->scope(); 111 DebuggerScope* DebuggerCallFrame::scope() 112 { 113 ASSERT(isValid()); 114 if (!isValid()) 115 return 0; 116 117 if (!m_scope) { 118 VM& vm = m_callFrame->vm(); 119 CodeBlock* codeBlock = m_callFrame->codeBlock(); 120 if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) { 121 ASSERT(!m_callFrame->scope()->isWithScope()); 122 JSActivation* activation = JSActivation::create(vm, m_callFrame, codeBlock); 123 m_callFrame->setActivation(activation); 124 m_callFrame->setScope(activation); 125 } 126 127 m_scope.set(vm, DebuggerScope::create(vm, m_callFrame->scope())); 128 } 129 return m_scope.get(); 123 130 } 124 131 … … 163 170 164 171 JSValue thisValue = thisValueForCallFrame(callFrame); 165 JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope() );172 JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope()); 166 173 if (vm.exception()) { 167 174 exception = vm.exception(); … … 175 182 { 176 183 m_callFrame = nullptr; 184 if (m_scope) { 185 m_scope->invalidateChain(); 186 m_scope.clear(); 187 } 177 188 RefPtr<DebuggerCallFrame> frame = m_caller.release(); 178 189 while (frame) { -
trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h
r165676 r172129 30 30 #define DebuggerCallFrame_h 31 31 32 #include "CallFrame.h"33 32 #include "DebuggerPrimitives.h" 33 #include "Strong.h" 34 34 #include <wtf/PassRefPtr.h> 35 35 #include <wtf/RefCounted.h> … … 37 37 38 38 namespace JSC { 39 40 class DebuggerScope; 41 class ExecState; 42 typedef ExecState CallFrame; 39 43 40 44 class DebuggerCallFrame : public RefCounted<DebuggerCallFrame> { … … 59 63 60 64 JS_EXPORT_PRIVATE JSGlobalObject* vmEntryGlobalObject() const; 61 JS_EXPORT_PRIVATE JSScope* scope() const;65 JS_EXPORT_PRIVATE DebuggerScope* scope(); 62 66 JS_EXPORT_PRIVATE String functionName() const; 63 67 JS_EXPORT_PRIVATE Type type() const; … … 79 83 RefPtr<DebuggerCallFrame> m_caller; 80 84 TextPosition m_position; 85 // The DebuggerCallFrameScope is responsible for calling invalidate() which, 86 // in turn, will clear this strong ref. 87 Strong<DebuggerScope> m_scope; 81 88 }; 82 89 -
trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp
r171939 r172129 29 29 #include "JSActivation.h" 30 30 #include "JSCInlines.h" 31 #include "JSWithScope.h" 31 32 32 33 namespace JSC { … … 36 37 const ClassInfo DebuggerScope::s_info = { "DebuggerScope", &Base::s_info, 0, CREATE_METHOD_TABLE(DebuggerScope) }; 37 38 38 DebuggerScope::DebuggerScope(VM& vm )39 : JSNonFinalObject(vm, vm.debuggerScopeStructure.get())39 DebuggerScope::DebuggerScope(VM& vm, JSScope* scope) 40 : JSNonFinalObject(vm, scope->globalObject()->debuggerScopeStructure()) 40 41 { 42 ASSERT(scope); 43 m_scope.set(vm, this, scope); 41 44 } 42 45 43 void DebuggerScope::finishCreation(VM& vm , JSObject* activation)46 void DebuggerScope::finishCreation(VM& vm) 44 47 { 45 48 Base::finishCreation(vm); 46 ASSERT(activation);47 ASSERT(activation->isActivationObject());48 m_activation.set(vm, this, jsCast<JSActivation*>(activation));49 49 } 50 50 … … 54 54 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 55 55 JSObject::visitChildren(thisObject, visitor); 56 visitor.append(&thisObject->m_activation); 56 visitor.append(&thisObject->m_scope); 57 visitor.append(&thisObject->m_next); 57 58 } 58 59 59 60 String DebuggerScope::className(const JSObject* object) 60 61 { 61 const DebuggerScope* thisObject = jsCast<const DebuggerScope*>(object); 62 return thisObject->m_activation->methodTable()->className(thisObject->m_activation.get()); 62 const DebuggerScope* scope = jsCast<const DebuggerScope*>(object); 63 ASSERT(scope->isValid()); 64 if (!scope->isValid()) 65 return String(); 66 JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); 67 return thisObject->methodTable()->className(thisObject); 63 68 } 64 69 65 70 bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) 66 71 { 67 DebuggerScope* thisObject = jsCast<DebuggerScope*>(object); 68 return thisObject->m_activation->methodTable()->getOwnPropertySlot(thisObject->m_activation.get(), exec, propertyName, slot); 72 DebuggerScope* scope = jsCast<DebuggerScope*>(object); 73 ASSERT(scope->isValid()); 74 if (!scope->isValid()) 75 return false; 76 JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); 77 return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot); 69 78 } 70 79 71 80 void DebuggerScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) 72 81 { 73 DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell); 74 thisObject->m_activation->methodTable()->put(thisObject->m_activation.get(), exec, propertyName, value, slot); 82 DebuggerScope* scope = jsCast<DebuggerScope*>(cell); 83 ASSERT(scope->isValid()); 84 if (!scope->isValid()) 85 return; 86 JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); 87 thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot); 75 88 } 76 89 77 90 bool DebuggerScope::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) 78 91 { 79 DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell); 80 return thisObject->m_activation->methodTable()->deleteProperty(thisObject->m_activation.get(), exec, propertyName); 92 DebuggerScope* scope = jsCast<DebuggerScope*>(cell); 93 ASSERT(scope->isValid()); 94 if (!scope->isValid()) 95 return false; 96 JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); 97 return thisObject->methodTable()->deleteProperty(thisObject, exec, propertyName); 81 98 } 82 99 83 100 void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) 84 101 { 85 DebuggerScope* thisObject = jsCast<DebuggerScope*>(object); 86 thisObject->m_activation->methodTable()->getPropertyNames(thisObject->m_activation.get(), exec, propertyNames, mode); 102 DebuggerScope* scope = jsCast<DebuggerScope*>(object); 103 ASSERT(scope->isValid()); 104 if (!scope->isValid()) 105 return; 106 JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); 107 thisObject->methodTable()->getPropertyNames(thisObject, exec, propertyNames, mode); 87 108 } 88 109 89 110 bool DebuggerScope::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) 90 111 { 91 DebuggerScope* thisObject = jsCast<DebuggerScope*>(object); 92 return thisObject->m_activation->methodTable()->defineOwnProperty(thisObject->m_activation.get(), exec, propertyName, descriptor, shouldThrow); 112 DebuggerScope* scope = jsCast<DebuggerScope*>(object); 113 ASSERT(scope->isValid()); 114 if (!scope->isValid()) 115 return false; 116 JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); 117 return thisObject->methodTable()->defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); 118 } 119 120 DebuggerScope* DebuggerScope::next() 121 { 122 ASSERT(isValid()); 123 if (!m_next && m_scope->next()) { 124 VM& vm = *m_scope->vm(); 125 DebuggerScope* nextScope = create(vm, m_scope->next()); 126 m_next.set(vm, this, nextScope); 127 } 128 return m_next.get(); 129 } 130 131 void DebuggerScope::invalidateChain() 132 { 133 DebuggerScope* scope = this; 134 while (scope) { 135 ASSERT(scope->isValid()); 136 DebuggerScope* nextScope = scope->m_next.get(); 137 scope->m_next.clear(); 138 scope->m_scope.clear(); 139 scope = nextScope; 140 } 141 } 142 143 bool DebuggerScope::isWithScope() const 144 { 145 return m_scope->isWithScope(); 146 } 147 148 bool DebuggerScope::isGlobalScope() const 149 { 150 return m_scope->isGlobalObject(); 151 } 152 153 bool DebuggerScope::isFunctionScope() const 154 { 155 // In the current debugger implementation, every function will create an 156 // activation object. Hence, an activation object implies a function scope. 157 return m_scope->isActivationObject(); 93 158 } 94 159 -
trunk/Source/JavaScriptCore/debugger/DebuggerScope.h
r171939 r172129 31 31 namespace JSC { 32 32 33 class DebuggerCallFrame; 34 class JSScope; 35 33 36 class DebuggerScope : public JSNonFinalObject { 34 37 public: 35 38 typedef JSNonFinalObject Base; 36 39 37 static DebuggerScope* create(VM& vm, JS Object* object)40 static DebuggerScope* create(VM& vm, JSScope* scope) 38 41 { 39 DebuggerScope* activation = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm);40 activation->finishCreation(vm, object);41 return activation;42 DebuggerScope* debuggerScope = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm, scope); 43 debuggerScope->finishCreation(vm); 44 return debuggerScope; 42 45 } 43 46 … … 57 60 } 58 61 59 protected: 62 class Iterator { 63 public: 64 Iterator(DebuggerScope* node) 65 : m_node(node) 66 { 67 } 68 69 DebuggerScope* get() { return m_node; } 70 Iterator& operator++() { m_node = m_node->next(); return *this; } 71 // postfix ++ intentionally omitted 72 73 bool operator==(const Iterator& other) const { return m_node == other.m_node; } 74 bool operator!=(const Iterator& other) const { return m_node != other.m_node; } 75 76 private: 77 DebuggerScope* m_node; 78 }; 79 80 Iterator begin(); 81 Iterator end(); 82 DebuggerScope* next(); 83 84 void invalidateChain(); 85 bool isValid() const { return !!m_scope; } 86 87 bool isWithScope() const; 88 bool isGlobalScope() const; 89 bool isFunctionScope() const; 90 91 private: 92 JS_EXPORT_PRIVATE DebuggerScope(VM&, JSScope*); 93 JS_EXPORT_PRIVATE void finishCreation(VM&); 94 95 JSScope* jsScope() const { return m_scope.get(); } 96 60 97 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags; 61 98 62 JS_EXPORT_PRIVATE void finishCreation(VM&, JSObject* activation); 99 WriteBarrier<JSScope> m_scope; 100 WriteBarrier<DebuggerScope> m_next; 63 101 64 private: 65 JS_EXPORT_PRIVATE DebuggerScope(VM&); 66 WriteBarrier<JSActivation> m_activation; 102 friend class DebuggerCallFrame; 67 103 }; 104 105 inline DebuggerScope::Iterator DebuggerScope::begin() 106 { 107 return Iterator(this); 108 } 109 110 inline DebuggerScope::Iterator DebuggerScope::end() 111 { 112 return Iterator(0); 113 } 68 114 69 115 } // namespace JSC -
trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h
r171380 r172129 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 43 43 macro(InvalidAbstractHeap) \ 44 44 macro(World) \ 45 macro(Arguments_numArguments) \46 macro(Arguments_overrideLength) \47 45 macro(Arguments_registers) \ 48 macro(Arguments_slowArguments) \49 macro(ArrayBuffer_data) \50 macro(Butterfly_arrayBuffer) \51 46 macro(Butterfly_publicLength) \ 52 47 macro(Butterfly_vectorLength) \ 53 48 macro(GetterSetter_getter) \ 54 49 macro(GetterSetter_setter) \ 55 macro(JSArrayBufferView_length) \56 macro(JSArrayBufferView_mode) \57 macro(JSArrayBufferView_vector) \58 50 macro(JSCell_structureID) \ 59 51 macro(JSCell_indexingType) \ 60 52 macro(JSCell_typeInfoFlags) \ 61 53 macro(JSCell_typeInfoType) \ 62 macro(JSFunction_executable) \63 macro(JSFunction_scopeChain) \64 54 macro(JSObject_butterfly) \ 65 55 macro(JSVariableObject_registers) \ … … 68 58 macro(IndexedDoubleProperties) \ 69 59 macro(IndexedContiguousProperties) \ 60 macro(IndexedArrayStorageProperties) \ 70 61 macro(ArrayStorageProperties) \ 71 62 macro(Variables) \ … … 77 68 /* Use this for writes only, to indicate that this may fire watchpoints. Usually this is never directly written but instead we test to see if a node clobbers this; it just so happens that you have to write world to clobber it. */\ 78 69 macro(Watchpoint_fire) \ 79 /* Use th isfor reads only, just to indicate that if the world got clobbered, then this operation will not work. */\70 /* Use these for reads only, just to indicate that if the world got clobbered, then this operation will not work. */\ 80 71 macro(MiscFields) \ 81 72 /* Use this for writes only, just to indicate that hoisting the node is invalid. This works because we don't hoist anything that has any side effects at all. */\ … … 208 199 } 209 200 210 bool isDisjoint(const AbstractHeap& other) 201 bool isDisjoint(const AbstractHeap& other) const 211 202 { 212 203 ASSERT(kind() != InvalidAbstractHeap); … … 221 212 } 222 213 223 bool overlaps(const AbstractHeap& other) 214 bool overlaps(const AbstractHeap& other) const 224 215 { 225 216 return !isDisjoint(other); -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r171660 r172129 31 31 #include "DFGAbstractInterpreter.h" 32 32 #include "GetByIdStatus.h" 33 #include "GetterSetter.h" 33 34 #include "Operations.h" 34 35 #include "PutByIdStatus.h" … … 1355 1356 1356 1357 case GetCallee: 1357 case GetGetter:1358 case GetSetter:1359 1358 forNode(node).setType(SpecFunction); 1360 1359 break; 1360 1361 case GetGetter: { 1362 JSValue base = forNode(node->child1()).m_value; 1363 if (base) { 1364 if (JSObject* getter = jsCast<GetterSetter*>(base)->getterConcurrently()) { 1365 setConstant(node, *m_graph.freeze(getter)); 1366 break; 1367 } 1368 } 1369 1370 forNode(node).setType(SpecObject); 1371 break; 1372 } 1373 1374 case GetSetter: { 1375 JSValue base = forNode(node->child1()).m_value; 1376 if (base) { 1377 if (JSObject* setter = jsCast<GetterSetter*>(base)->setterConcurrently()) { 1378 setConstant(node, *m_graph.freeze(setter)); 1379 break; 1380 } 1381 } 1382 1383 forNode(node).setType(SpecObject); 1384 break; 1385 } 1361 1386 1362 1387 case GetScope: // FIXME: We could get rid of these if we know that the JSFunction is a constant. https://bugs.webkit.org/show_bug.cgi?id=106202 … … 1406 1431 AbstractValue result; 1407 1432 for (unsigned i = status.numVariants(); i--;) { 1408 if (!status[i].specificValue()) { 1433 DFG_ASSERT(m_graph, node, !status[i].alternateBase()); 1434 JSValue constantResult = 1435 m_graph.tryGetConstantProperty(value, status[i].offset()); 1436 if (!constantResult) { 1409 1437 result.makeHeapTop(); 1410 1438 break; … … 1413 1441 AbstractValue thisResult; 1414 1442 thisResult.set( 1415 m_graph, *m_graph.freeze( status[i].specificValue()),1443 m_graph, *m_graph.freeze(constantResult), 1416 1444 m_state.structureClobberState()); 1417 1445 result.merge(thisResult); … … 1588 1616 1589 1617 case GetByOffset: { 1618 StorageAccessData data = m_graph.m_storageAccessData[node->storageAccessDataIndex()]; 1619 JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset); 1620 if (result) { 1621 setConstant(node, *m_graph.freeze(result)); 1622 break; 1623 } 1624 1590 1625 forNode(node).makeHeapTop(); 1591 1626 break; … … 1593 1628 1594 1629 case GetGetterSetterByOffset: { 1630 StorageAccessData data = m_graph.m_storageAccessData[node->storageAccessDataIndex()]; 1631 JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset); 1632 if (result && jsDynamicCast<GetterSetter*>(result)) { 1633 setConstant(node, *m_graph.freeze(result)); 1634 break; 1635 } 1636 1595 1637 forNode(node).set(m_graph, m_graph.m_vm.getterSetterStructure.get()); 1596 1638 break; … … 1621 1663 continue; 1622 1664 baseSet.merge(set); 1623 if (!variant.specificValue()) { 1665 1666 JSValue baseForLoad; 1667 if (variant.alternateBase()) 1668 baseForLoad = variant.alternateBase(); 1669 else 1670 baseForLoad = base.m_value; 1671 JSValue constantResult = 1672 m_graph.tryGetConstantProperty( 1673 baseForLoad, variant.baseStructure(), variant.offset()); 1674 if (!constantResult) { 1624 1675 result.makeHeapTop(); 1625 1676 continue; … … 1628 1679 thisResult.set( 1629 1680 m_graph, 1630 *m_graph.freeze( variant.specificValue()),1681 *m_graph.freeze(constantResult), 1631 1682 m_state.structureClobberState()); 1632 1683 result.merge(thisResult); -
trunk/Source/JavaScriptCore/dfg/DFGAdjacencyList.h
r171613 r172129 53 53 } 54 54 55 AdjacencyList(Kind kind, Edge child1, Edge child2 , Edge child3)55 AdjacencyList(Kind kind, Edge child1, Edge child2 = Edge(), Edge child3 = Edge()) 56 56 { 57 57 ASSERT_UNUSED(kind, kind == Fixed); … … 133 133 setChild(Size - 1, Edge()); 134 134 } 135 135 136 136 unsigned firstChild() const 137 137 { … … 152 152 } 153 153 154 AdjacencyList sanitized() const 155 { 156 return AdjacencyList(Fixed, child1().sanitized(), child2().sanitized(), child3().sanitized()); 157 } 158 159 unsigned hash() const 160 { 161 unsigned result = 0; 162 if (!child1()) 163 return result; 164 165 result += child1().hash(); 166 167 if (!child2()) 168 return result; 169 170 result *= 3; 171 result += child2().hash(); 172 173 if (!child3()) 174 return result; 175 176 result *= 3; 177 result += child3().hash(); 178 179 return result; 180 } 181 182 bool operator==(const AdjacencyList& other) const 183 { 184 return child1() == other.child1() 185 && child2() == other.child2() 186 && child3() == other.child3(); 187 } 188 154 189 private: 155 190 Edge m_words[Size]; -
trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.h
r171613 r172129 172 172 ~SSAData(); 173 173 }; 174 OwnPtr<SSAData> ssa;175 174 std::unique_ptr<SSAData> ssa; 175 176 176 private: 177 177 friend class InsertionSet; -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r171660 r172129 172 172 void handleCall( 173 173 int result, NodeType op, InlineCallFrame::Kind, unsigned instructionSize, 174 Node* callTarget, int argCount, int registerOffset, CallLinkStatus, 175 SpeculatedType prediction); 176 void handleCall( 177 int result, NodeType op, InlineCallFrame::Kind, unsigned instructionSize, 174 178 Node* callTarget, int argCount, int registerOffset, CallLinkStatus); 175 179 void handleCall(int result, NodeType op, CodeSpecializationKind, unsigned instructionSize, int callee, int argCount, int registerOffset); … … 184 188 bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, CodeSpecializationKind); 185 189 Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, Node* value); 186 Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, NodeType op = GetByOffset);190 Node* handleGetByOffset(SpeculatedType, Node* base, const StructureSet&, unsigned identifierNumber, PropertyOffset, NodeType op = GetByOffset); 187 191 void handleGetById( 188 192 int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber, … … 641 645 } 642 646 643 Node* addCall (int result, NodeType op, Node* callee, int argCount, int registerOffset)644 {645 SpeculatedType prediction = getPrediction();646 647 Node* addCallWithoutSettingResult( 648 NodeType op, Node* callee, int argCount, int registerOffset, 649 SpeculatedType prediction) 650 { 647 651 addVarArgChild(callee); 648 652 size_t parameterSlots = JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + argCount; … … 654 658 addVarArgChild(get(virtualRegisterForArgument(i, registerOffset))); 655 659 656 Node* call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction)); 657 set(VirtualRegister(result), call); 660 return addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction)); 661 } 662 663 Node* addCall( 664 int result, NodeType op, Node* callee, int argCount, int registerOffset, 665 SpeculatedType prediction) 666 { 667 Node* call = addCallWithoutSettingResult( 668 op, callee, argCount, registerOffset, prediction); 669 VirtualRegister resultReg(result); 670 if (resultReg.isValid()) 671 set(VirtualRegister(result), call); 658 672 return call; 659 673 } … … 995 1009 CallLinkStatus callLinkStatus) 996 1010 { 1011 handleCall( 1012 result, op, kind, instructionSize, callTarget, argumentCountIncludingThis, 1013 registerOffset, callLinkStatus, getPrediction()); 1014 } 1015 1016 void ByteCodeParser::handleCall( 1017 int result, NodeType op, InlineCallFrame::Kind kind, unsigned instructionSize, 1018 Node* callTarget, int argumentCountIncludingThis, int registerOffset, 1019 CallLinkStatus callLinkStatus, SpeculatedType prediction) 1020 { 997 1021 ASSERT(registerOffset <= 0); 998 1022 CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind); … … 1005 1029 // that we cannot optimize them. 1006 1030 1007 addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset );1031 addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset, prediction); 1008 1032 return; 1009 1033 } 1010 1034 1011 1035 unsigned nextOffset = m_currentIndex + instructionSize; 1012 SpeculatedType prediction = getPrediction();1013 1036 1014 1037 if (InternalFunction* function = callLinkStatus.internalFunction()) { … … 1022 1045 1023 1046 // Can only handle this using the generic call handler. 1024 addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset );1047 addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset, prediction); 1025 1048 return; 1026 1049 } … … 1059 1082 } 1060 1083 } 1061 Node* call = addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset );1084 Node* call = addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset, prediction); 1062 1085 1063 1086 if (knownFunction) … … 1206 1229 size_t argumentPositionStart = m_graph.m_argumentPositions.size(); 1207 1230 1231 VirtualRegister resultReg(resultOperand); 1232 if (resultReg.isValid()) 1233 resultReg = m_inlineStackTop->remapOperand(resultReg); 1234 1208 1235 InlineStackEntry inlineStackEntry( 1209 this, codeBlock, codeBlock, m_graph.lastBlock(), callLinkStatus.function(), 1210 m_inlineStackTop->remapOperand(VirtualRegister(resultOperand)), 1236 this, codeBlock, codeBlock, m_graph.lastBlock(), callLinkStatus.function(), resultReg, 1211 1237 (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind); 1212 1238 … … 1674 1700 } 1675 1701 1676 Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset, NodeType op)1702 Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, const StructureSet& structureSet, unsigned identifierNumber, PropertyOffset offset, NodeType op) 1677 1703 { 1704 if (base->hasConstant()) { 1705 if (JSValue constant = m_graph.tryGetConstantProperty(base->asJSValue(), structureSet, offset)) { 1706 addToGraph(Phantom, base); 1707 return weakJSConstant(constant); 1708 } 1709 } 1710 1678 1711 Node* propertyStorage; 1679 1712 if (isInlineOffset(offset)) … … 1770 1803 // ensure that the base of the original get_by_id is kept alive until we're done with 1771 1804 // all of the speculations. We only insert the Phantom if there had been a CheckStructure 1772 // on something other than the base following the CheckStructure on base, or if the 1773 // access was compiled to a WeakJSConstant specific value, in which case we might not 1774 // have any explicit use of the base at all. 1775 if (variant.specificValue() || originalBase != base) 1805 // on something other than the base following the CheckStructure on base. 1806 if (originalBase != base) 1776 1807 addToGraph(Phantom, originalBase); 1777 1808 1778 Node* loadedValue; 1779 if (variant.specificValue()) 1780 loadedValue = weakJSConstant(variant.specificValue()); 1781 else { 1782 loadedValue = handleGetByOffset( 1783 prediction, base, identifierNumber, variant.offset(), 1784 variant.callLinkStatus() ? GetGetterSetterByOffset : GetByOffset); 1785 } 1809 Node* loadedValue = handleGetByOffset( 1810 variant.callLinkStatus() ? SpecCellOther : prediction, 1811 base, variant.baseStructure(), identifierNumber, variant.offset(), 1812 variant.callLinkStatus() ? GetGetterSetterByOffset : GetByOffset); 1786 1813 1787 1814 if (!variant.callLinkStatus()) { … … 1825 1852 handleCall( 1826 1853 destinationOperand, Call, InlineCallFrame::GetterCall, OPCODE_LENGTH(op_get_by_id), 1827 getter, numberOfParameters - 1, registerOffset, *variant.callLinkStatus() );1854 getter, numberOfParameters - 1, registerOffset, *variant.callLinkStatus(), prediction); 1828 1855 } 1829 1856 … … 1876 1903 const PutByIdVariant& variant = putByIdStatus[0]; 1877 1904 1878 if (variant.kind() == PutByIdVariant::Replace) { 1905 switch (variant.kind()) { 1906 case PutByIdVariant::Replace: { 1879 1907 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structure())), base); 1880 1908 handlePutByOffset(base, identifierNumber, variant.offset(), value); … … 1884 1912 } 1885 1913 1886 if (variant.kind() != PutByIdVariant::Transition) { 1914 case PutByIdVariant::Transition: { 1915 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base); 1916 emitChecks(variant.constantChecks()); 1917 1918 ASSERT(variant.oldStructureForTransition()->transitionWatchpointSetHasBeenInvalidated()); 1919 1920 Node* propertyStorage; 1921 Transition* transition = m_graph.m_transitions.add( 1922 variant.oldStructureForTransition(), variant.newStructure()); 1923 1924 if (variant.reallocatesStorage()) { 1925 1926 // If we're growing the property storage then it must be because we're 1927 // storing into the out-of-line storage. 1928 ASSERT(!isInlineOffset(variant.offset())); 1929 1930 if (!variant.oldStructureForTransition()->outOfLineCapacity()) { 1931 propertyStorage = addToGraph( 1932 AllocatePropertyStorage, OpInfo(transition), base); 1933 } else { 1934 propertyStorage = addToGraph( 1935 ReallocatePropertyStorage, OpInfo(transition), 1936 base, addToGraph(GetButterfly, base)); 1937 } 1938 } else { 1939 if (isInlineOffset(variant.offset())) 1940 propertyStorage = base; 1941 else 1942 propertyStorage = addToGraph(GetButterfly, base); 1943 } 1944 1945 addToGraph(PutStructure, OpInfo(transition), base); 1946 1947 addToGraph( 1948 PutByOffset, 1949 OpInfo(m_graph.m_storageAccessData.size()), 1950 propertyStorage, 1951 base, 1952 value); 1953 1954 StorageAccessData storageAccessData; 1955 storageAccessData.offset = variant.offset(); 1956 storageAccessData.identifierNumber = identifierNumber; 1957 m_graph.m_storageAccessData.append(storageAccessData); 1958 1959 if (m_graph.compilation()) 1960 m_graph.compilation()->noticeInlinedPutById(); 1961 return; 1962 } 1963 1964 case PutByIdVariant::Setter: { 1965 Node* originalBase = base; 1966 1967 addToGraph( 1968 CheckStructure, OpInfo(m_graph.addStructureSet(variant.structure())), base); 1969 1970 emitChecks(variant.constantChecks()); 1971 1972 if (variant.alternateBase()) 1973 base = weakJSConstant(variant.alternateBase()); 1974 1975 Node* loadedValue = handleGetByOffset( 1976 SpecCellOther, base, variant.baseStructure(), identifierNumber, variant.offset(), 1977 GetGetterSetterByOffset); 1978 1979 Node* setter = addToGraph(GetSetter, loadedValue); 1980 1981 // Make a call. We don't try to get fancy with using the smallest operand number because 1982 // the stack layout phase should compress the stack anyway. 1983 1984 unsigned numberOfParameters = 0; 1985 numberOfParameters++; // The 'this' argument. 1986 numberOfParameters++; // The new value. 1987 numberOfParameters++; // True return PC. 1988 1989 // Start with a register offset that corresponds to the last in-use register. 1990 int registerOffset = virtualRegisterForLocal( 1991 m_inlineStackTop->m_profiledBlock->m_numCalleeRegisters - 1).offset(); 1992 registerOffset -= numberOfParameters; 1993 registerOffset -= JSStack::CallFrameHeaderSize; 1994 1995 // Get the alignment right. 1996 registerOffset = -WTF::roundUpToMultipleOf( 1997 stackAlignmentRegisters(), 1998 -registerOffset); 1999 2000 ensureLocals( 2001 m_inlineStackTop->remapOperand( 2002 VirtualRegister(registerOffset)).toLocal()); 2003 2004 int nextRegister = registerOffset + JSStack::CallFrameHeaderSize; 2005 set(VirtualRegister(nextRegister++), originalBase, ImmediateNakedSet); 2006 set(VirtualRegister(nextRegister++), value, ImmediateNakedSet); 2007 2008 handleCall( 2009 VirtualRegister().offset(), Call, InlineCallFrame::SetterCall, 2010 OPCODE_LENGTH(op_put_by_id), setter, numberOfParameters - 1, registerOffset, 2011 *variant.callLinkStatus(), SpecOther); 2012 return; 2013 } 2014 2015 default: { 1887 2016 emitPutById(base, identifierNumber, value, putByIdStatus, isDirect); 1888 2017 return; 1889 } 1890 1891 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base); 1892 emitChecks(variant.constantChecks()); 1893 1894 ASSERT(variant.oldStructureForTransition()->transitionWatchpointSetHasBeenInvalidated()); 1895 1896 Node* propertyStorage; 1897 Transition* transition = m_graph.m_transitions.add( 1898 variant.oldStructureForTransition(), variant.newStructure()); 1899 1900 if (variant.reallocatesStorage()) { 1901 1902 // If we're growing the property storage then it must be because we're 1903 // storing into the out-of-line storage. 1904 ASSERT(!isInlineOffset(variant.offset())); 1905 1906 if (!variant.oldStructureForTransition()->outOfLineCapacity()) { 1907 propertyStorage = addToGraph( 1908 AllocatePropertyStorage, OpInfo(transition), base); 1909 } else { 1910 propertyStorage = addToGraph( 1911 ReallocatePropertyStorage, OpInfo(transition), 1912 base, addToGraph(GetButterfly, base)); 1913 } 1914 } else { 1915 if (isInlineOffset(variant.offset())) 1916 propertyStorage = base; 1917 else 1918 propertyStorage = addToGraph(GetButterfly, base); 1919 } 1920 1921 addToGraph(PutStructure, OpInfo(transition), base); 1922 1923 addToGraph( 1924 PutByOffset, 1925 OpInfo(m_graph.m_storageAccessData.size()), 1926 propertyStorage, 1927 base, 1928 value); 1929 1930 StorageAccessData storageAccessData; 1931 storageAccessData.offset = variant.offset(); 1932 storageAccessData.identifierNumber = identifierNumber; 1933 m_graph.m_storageAccessData.append(storageAccessData); 1934 1935 if (m_graph.compilation()) 1936 m_graph.compilation()->noticeInlinedPutById(); 2018 } } 1937 2019 } 1938 2020 … … 2716 2798 flushForReturn(); 2717 2799 if (inlineCallFrame()) { 2718 ASSERT(m_inlineStackTop->m_returnValue.isValid());2719 setDirect(m_inlineStackTop->m_returnValue, get(VirtualRegister(currentInstruction[1].u.operand)), ImmediateSetWithFlush);2800 if (m_inlineStackTop->m_returnValue.isValid()) 2801 setDirect(m_inlineStackTop->m_returnValue, get(VirtualRegister(currentInstruction[1].u.operand)), ImmediateSetWithFlush); 2720 2802 m_inlineStackTop->m_didReturn = true; 2721 2803 if (m_inlineStackTop->m_unlinkedBlocks.isEmpty()) { … … 2895 2977 Node* base = cellConstantWithStructureCheck(globalObject, status[0].structureSet().onlyStructure()); 2896 2978 addToGraph(Phantom, get(VirtualRegister(scope))); 2897 if (JSValue specificValue = status[0].specificValue()) 2898 set(VirtualRegister(dst), weakJSConstant(specificValue.asCell())); 2899 else 2900 set(VirtualRegister(dst), handleGetByOffset(prediction, base, identifierNumber, operand)); 2979 set(VirtualRegister(dst), handleGetByOffset(prediction, base, status[0].structureSet(), identifierNumber, operand)); 2901 2980 break; 2902 2981 } … … 2906 2985 SymbolTableEntry entry = globalObject->symbolTable()->get(uid); 2907 2986 VariableWatchpointSet* watchpointSet = entry.watchpointSet(); 2908 JSValue specificValue =2987 JSValue inferredValue = 2909 2988 watchpointSet ? watchpointSet->inferredValue() : JSValue(); 2910 if (! specificValue) {2989 if (!inferredValue) { 2911 2990 SpeculatedType prediction = getPrediction(); 2912 2991 set(VirtualRegister(dst), addToGraph(GetGlobalVar, OpInfo(operand), OpInfo(prediction))); … … 2915 2994 2916 2995 addToGraph(VariableWatchpoint, OpInfo(watchpointSet)); 2917 set(VirtualRegister(dst), weakJSConstant( specificValue));2996 set(VirtualRegister(dst), weakJSConstant(inferredValue)); 2918 2997 break; 2919 2998 } -
trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
r165995 r172129 202 202 if (otherNode->op() == GetLocal) { 203 203 // Replace all references to this GetLocal with otherNode. 204 node-> misc.replacement = otherNode;204 node->replacement = otherNode; 205 205 return; 206 206 } 207 207 208 208 ASSERT(otherNode->op() == SetLocal); 209 node-> misc.replacement = otherNode->child1().node();209 node->replacement = otherNode->child1().node(); 210 210 return; 211 211 } -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r171613 r172129 30 30 31 31 #include "DFGAbstractHeap.h" 32 #include "DFGClobberSet.h" 32 33 #include "DFGClobberize.h" 33 34 #include "DFGEdgeUsesStructure.h" … … 40 41 namespace JSC { namespace DFG { 41 42 42 class CSEPhase : public Phase { 43 // This file contains two CSE implementations: local and global. LocalCSE typically runs when we're 44 // in DFG mode, i.e. we want to compile quickly. LocalCSE contains a lot of optimizations for 45 // compile time. GlobalCSE, on the other hand, is fairly straight-forward. It will find more 46 // optimization opportunities by virtue of being global. 47 48 namespace { 49 50 const bool verbose = false; 51 52 class ClobberFilter { 43 53 public: 44 CSEPhase(Graph& graph) 45 : Phase(graph, "common subexpression elimination") 54 ClobberFilter(AbstractHeap heap) 55 : m_heap(heap) 56 { 57 } 58 59 bool operator()(const ImpureMap::KeyValuePairType& pair) const 60 { 61 return m_heap.overlaps(pair.key.heap()); 62 } 63 64 private: 65 AbstractHeap m_heap; 66 }; 67 68 inline void clobber(ImpureMap& map, AbstractHeap heap) 69 { 70 ClobberFilter filter(heap); 71 map.removeIf(filter); 72 } 73 74 class LocalCSEPhase : public Phase { 75 public: 76 LocalCSEPhase(Graph& graph) 77 : Phase(graph, "local common subexpression elimination") 78 , m_smallBlock(graph) 79 , m_largeBlock(graph) 46 80 { 47 81 } … … 49 83 bool run() 50 84 { 51 ASSERT(m_graph.m_fixpointState != BeforeFixpoint); 52 53 m_changed = false; 85 ASSERT(m_graph.m_fixpointState == FixpointNotConverged); 86 ASSERT(m_graph.m_form == ThreadedCPS || m_graph.m_form == LoadStore); 87 88 bool changed = false; 54 89 55 90 m_graph.clearReplacements(); … … 60 95 continue; 61 96 62 // All Phis need to already be marked as relevant to OSR. 63 if (!ASSERT_DISABLED) { 64 for (unsigned i = 0; i < block->phis.size(); ++i) 65 ASSERT(block->phis[i]->flags() & NodeRelevantToOSR); 66 } 67 68 for (unsigned i = block->size(); i--;) { 69 Node* node = block->at(i); 97 if (block->size() <= SmallMaps::capacity) 98 changed |= m_smallBlock.run(block); 99 else 100 changed |= m_largeBlock.run(block); 101 } 102 103 return changed; 104 } 105 106 private: 107 class SmallMaps { 108 public: 109 // This permits SmallMaps to be used for blocks that have up to 100 nodes. In practice, 110 // fewer than half of the nodes in a block have pure defs, and even fewer have impure defs. 111 // Thus, a capacity limit of 100 probably means that somewhere around ~40 things may end up 112 // in one of these "small" list-based maps. That number still seems largeish, except that 113 // the overhead of HashMaps can be quite high currently: clearing them, or even removing 114 // enough things from them, deletes (or resizes) their backing store eagerly. Hence 115 // HashMaps induce a lot of malloc traffic. 116 static const unsigned capacity = 100; 117 118 SmallMaps() 119 : m_pureLength(0) 120 , m_impureLength(0) 121 { 122 } 123 124 void clear() 125 { 126 m_pureLength = 0; 127 m_impureLength = 0; 128 } 129 130 void write(AbstractHeap heap) 131 { 132 for (unsigned i = 0; i < m_impureLength; ++i) { 133 if (heap.overlaps(m_impureMap[i].key.heap())) 134 m_impureMap[i--] = m_impureMap[--m_impureLength]; 135 } 136 } 137 138 Node* addPure(PureValue value, Node* node) 139 { 140 for (unsigned i = m_pureLength; i--;) { 141 if (m_pureMap[i].key == value) 142 return m_pureMap[i].value; 143 } 144 145 ASSERT(m_pureLength < capacity); 146 m_pureMap[m_pureLength++] = WTF::KeyValuePair<PureValue, Node*>(value, node); 147 return nullptr; 148 } 149 150 Node* findReplacement(HeapLocation location) 151 { 152 for (unsigned i = m_impureLength; i--;) { 153 if (m_impureMap[i].key == location) 154 return m_impureMap[i].value; 155 } 156 return nullptr; 157 } 158 159 Node* addImpure(HeapLocation location, Node* node) 160 { 161 if (Node* result = findReplacement(location)) 162 return result; 163 ASSERT(m_impureLength < capacity); 164 m_impureMap[m_impureLength++] = WTF::KeyValuePair<HeapLocation, Node*>(location, node); 165 return nullptr; 166 } 167 168 private: 169 WTF::KeyValuePair<PureValue, Node*> m_pureMap[capacity]; 170 WTF::KeyValuePair<HeapLocation, Node*> m_impureMap[capacity]; 171 unsigned m_pureLength; 172 unsigned m_impureLength; 173 }; 174 175 class LargeMaps { 176 public: 177 LargeMaps() 178 { 179 } 180 181 void clear() 182 { 183 m_pureMap.clear(); 184 m_impureMap.clear(); 185 } 186 187 void write(AbstractHeap heap) 188 { 189 clobber(m_impureMap, heap); 190 } 191 192 Node* addPure(PureValue value, Node* node) 193 { 194 auto result = m_pureMap.add(value, node); 195 if (result.isNewEntry) 196 return nullptr; 197 return result.iterator->value; 198 } 199 200 Node* findReplacement(HeapLocation location) 201 { 202 return m_impureMap.get(location); 203 } 204 205 Node* addImpure(HeapLocation location, Node* node) 206 { 207 auto result = m_impureMap.add(location, node); 208 if (result.isNewEntry) 209 return nullptr; 210 return result.iterator->value; 211 } 212 213 private: 214 HashMap<PureValue, Node*> m_pureMap; 215 HashMap<HeapLocation, Node*> m_impureMap; 216 }; 217 218 template<typename Maps> 219 class BlockCSE { 220 public: 221 BlockCSE(Graph& graph) 222 : m_graph(graph) 223 { 224 } 225 226 bool run(BasicBlock* block) 227 { 228 m_maps.clear(); 229 m_changed = false; 230 231 for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { 232 m_node = block->at(nodeIndex); 233 m_graph.performSubstitution(m_node); 234 235 if (m_node->op() == Identity) { 236 m_node->convertToCheck(); 237 m_node->replacement = m_node->child1().node(); 238 m_changed = true; 239 } else { 240 // This rule only makes sense for local CSE, since in SSA form we have already 241 // factored the bounds check out of the PutByVal. It's kind of gross, but we 242 // still have reason to believe that PutByValAlias is a good optimization and 243 // that it's better to do it with a single node rather than separating out the 244 // CheckInBounds. 245 if (m_node->op() == PutByVal || m_node->op() == PutByValDirect) { 246 HeapLocation heap; 247 248 Node* base = m_graph.varArgChild(m_node, 0).node(); 249 Node* index = m_graph.varArgChild(m_node, 1).node(); 250 251 ArrayMode mode = m_node->arrayMode(); 252 switch (mode.type()) { 253 case Array::Int32: 254 if (!mode.isInBounds()) 255 break; 256 heap = HeapLocation( 257 IndexedPropertyLoc, IndexedInt32Properties, base, index); 258 break; 259 260 case Array::Double: 261 if (!mode.isInBounds()) 262 break; 263 heap = HeapLocation( 264 IndexedPropertyLoc, IndexedDoubleProperties, base, index); 265 break; 266 267 case Array::Contiguous: 268 if (!mode.isInBounds()) 269 break; 270 heap = HeapLocation( 271 IndexedPropertyLoc, IndexedContiguousProperties, base, index); 272 break; 273 274 case Array::Int8Array: 275 case Array::Int16Array: 276 case Array::Int32Array: 277 case Array::Uint8Array: 278 case Array::Uint8ClampedArray: 279 case Array::Uint16Array: 280 case Array::Uint32Array: 281 case Array::Float32Array: 282 case Array::Float64Array: 283 if (!mode.isInBounds()) 284 break; 285 heap = HeapLocation( 286 IndexedPropertyLoc, TypedArrayProperties, base, index); 287 break; 288 289 default: 290 break; 291 } 292 293 if (!!heap && m_maps.findReplacement(heap)) 294 m_node->setOp(PutByValAlias); 295 } 296 297 clobberize(m_graph, m_node, *this); 298 } 299 } 300 301 return m_changed; 302 } 303 304 void read(AbstractHeap) { } 305 306 void write(AbstractHeap heap) 307 { 308 m_maps.write(heap); 309 } 310 311 void def(PureValue value) 312 { 313 Node* match = m_maps.addPure(value, m_node); 314 if (!match) 315 return; 316 317 m_node->replaceWith(match); 318 m_changed = true; 319 } 320 321 void def(HeapLocation location, Node* value) 322 { 323 Node* match = m_maps.addImpure(location, value); 324 if (!match) 325 return; 326 327 if (m_node->op() == GetLocal) { 328 // For uncaptured locals, usually the CPS rethreading phase does this. But it's OK 329 // for us to mess with locals - regardless of their capturedness - so long as: 330 // 331 // - We dethread the graph. Any changes we make may invalidate the assumptions of 332 // our CPS form, particularly if this GetLocal is linked to the variablesAtTail. 333 // 334 // - We don't introduce a Phantom for the child of the GetLocal. This wouldn't be 335 // totally wrong but it would pessimize the code. Just because there is a 336 // GetLocal doesn't mean that the child was live. Simply rerouting the all uses 337 // of this GetLocal will preserve the live-at-exit information just fine. 338 // 339 // We accomplish the latter by just clearing the child; then the Phantom that we 340 // introduce won't have children and so it will eventually just be deleted. 341 342 m_node->child1() = Edge(); 343 m_graph.dethread(); 344 } 345 346 m_node->replaceWith(match); 347 m_changed = true; 348 } 349 350 private: 351 Graph& m_graph; 352 353 bool m_changed; 354 Node* m_node; 355 356 Maps m_maps; 357 }; 358 359 BlockCSE<SmallMaps> m_smallBlock; 360 BlockCSE<LargeMaps> m_largeBlock; 361 }; 362 363 class GlobalCSEPhase : public Phase { 364 public: 365 GlobalCSEPhase(Graph& graph) 366 : Phase(graph, "global common subexpression elimination") 367 { 368 } 369 370 bool run() 371 { 372 ASSERT(m_graph.m_fixpointState == FixpointNotConverged); 373 ASSERT(m_graph.m_form == SSA); 374 375 m_graph.initializeNodeOwners(); 376 m_graph.m_dominators.computeIfNecessary(m_graph); 377 378 m_graph.getBlocksInPreOrder(m_preOrder); 379 380 m_impureDataMap.resize(m_graph.numBlocks()); 381 382 // First figure out what gets clobbered by blocks. Node that this uses the preOrder list 383 // for convenience only. 384 for (unsigned i = m_preOrder.size(); i--;) { 385 m_block = m_preOrder[i]; 386 m_impureData = &m_impureDataMap[m_block->index]; 387 for (unsigned nodeIndex = m_block->size(); nodeIndex--;) 388 addWrites(m_graph, m_block->at(nodeIndex), m_impureData->writes); 389 } 390 391 // Based on my experience doing this before, what follows might have to be made iterative. 392 // Right now it doesn't have to be iterative because everything is dominator-bsed. But when 393 // validation is enabled, we check if iterating would find new CSE opportunities. 394 395 bool changed = iterate(); 396 397 // Iterating a second time should not find new CSE opportunities, unless we have a bug. 398 if (validationEnabled()) { 399 reset(); 400 DFG_ASSERT(m_graph, nullptr, !iterate()); 401 } 402 403 return changed; 404 } 405 406 void reset() 407 { 408 m_pureValues.clear(); 409 410 for (unsigned i = m_impureDataMap.size(); i--;) { 411 m_impureDataMap[i].availableAtTail.clear(); 412 m_impureDataMap[i].didVisit = false; 413 } 414 } 415 416 bool iterate() 417 { 418 if (verbose) 419 dataLog("Performing iteration.\n"); 420 421 m_changed = false; 422 m_graph.clearReplacements(); 423 424 for (unsigned i = 0; i < m_preOrder.size(); ++i) { 425 m_block = m_preOrder[i]; 426 m_impureData = &m_impureDataMap[m_block->index]; 427 m_writesSoFar.clear(); 428 429 if (verbose) 430 dataLog("Processing block ", *m_block, ":\n"); 431 432 for (unsigned nodeIndex = 0; nodeIndex < m_block->size(); ++nodeIndex) { 433 m_node = m_block->at(nodeIndex); 434 if (verbose) 435 dataLog(" Looking at node ", m_node, ":\n"); 70 436 71 switch (node->op()) { 72 case SetLocal: 73 case GetLocal: // FIXME: The GetLocal case is only necessary until we do https://bugs.webkit.org/show_bug.cgi?id=106707. 74 node->mergeFlags(NodeRelevantToOSR); 75 break; 76 default: 77 node->clearFlags(NodeRelevantToOSR); 78 break; 437 m_graph.performSubstitution(m_node); 438 439 if (m_node->op() == Identity) { 440 m_node->convertToCheck(); 441 m_node->replacement = m_node->child1().node(); 442 m_changed = true; 443 } else 444 clobberize(m_graph, m_node, *this); 445 } 446 447 m_impureData->didVisit = true; 448 } 449 450 return m_changed; 451 } 452 453 void read(AbstractHeap) { } 454 455 void write(AbstractHeap heap) 456 { 457 clobber(m_impureData->availableAtTail, heap); 458 m_writesSoFar.add(heap); 459 if (verbose) 460 dataLog(" Clobbered, new tail map: ", mapDump(m_impureData->availableAtTail), "\n"); 461 } 462 463 void def(PureValue value) 464 { 465 // With pure values we do not have to worry about the possibility of some control flow path 466 // clobbering the value. So, we just search for all of the like values that have been 467 // computed. We pick one that is in a block that dominates ours. Note that this means that 468 // a PureValue will map to a list of nodes, since there may be many places in the control 469 // flow graph that compute a value but only one of them that dominates us. we may build up 470 // a large list of nodes that compute some value in the case of gnarly control flow. This 471 // is probably OK. 472 473 auto result = m_pureValues.add(value, Vector<Node*>()); 474 if (result.isNewEntry) { 475 result.iterator->value.append(m_node); 476 return; 477 } 478 479 for (unsigned i = result.iterator->value.size(); i--;) { 480 Node* candidate = result.iterator->value[i]; 481 if (m_graph.m_dominators.dominates(candidate->owner, m_block)) { 482 m_node->replaceWith(candidate); 483 m_changed = true; 484 return; 485 } 486 } 487 488 result.iterator->value.append(m_node); 489 } 490 491 Node* findReplacement(HeapLocation location) 492 { 493 // At this instant, our "availableAtTail" reflects the set of things that are available in 494 // this block so far. We check this map to find block-local CSE opportunities before doing 495 // a global search. 496 Node* match = m_impureData->availableAtTail.get(location); 497 if (match) { 498 if (verbose) 499 dataLog(" Found local match: ", match, "\n"); 500 return match; 501 } 502 503 // If it's not available at this point in the block, and at some prior point in the block 504 // we have clobbered this heap location, then there is no point in doing a global search. 505 if (m_writesSoFar.overlaps(location.heap())) { 506 if (verbose) 507 dataLog(" Not looking globally because of local clobber: ", m_writesSoFar, "\n"); 508 return nullptr; 509 } 510 511 // This perfoms a backward search over the control flow graph to find some possible 512 // non-local def() that matches our heap location. Such a match is only valid if there does 513 // not exist any path from that def() to our block that contains a write() that overlaps 514 // our heap. This algorithm looks for both of these things (the matching def and the 515 // overlapping writes) in one backwards DFS pass. 516 // 517 // This starts by looking at the starting block's predecessors, and then it continues along 518 // their predecessors. As soon as this finds a possible def() - one that defines the heap 519 // location we want while dominating our starting block - it assumes that this one must be 520 // the match. It then lets the DFS over predecessors complete, but it doesn't add the 521 // def()'s predecessors; this ensures that any blocks we visit thereafter are on some path 522 // from the def() to us. As soon as the DFG finds a write() that overlaps the location's 523 // heap, it stops, assuming that there is no possible match. Note that the write() case may 524 // trigger before we find a def(), or after. Either way, the write() case causes this 525 // function to immediately return nullptr. 526 // 527 // If the write() is found before we find the def(), then we know that any def() we would 528 // find would have a path to us that trips over the write() and hence becomes invalid. This 529 // is just a direct outcome of us looking for a def() that dominates us. Given a block A 530 // that dominates block B - so that A is the one that would have the def() and B is our 531 // starting block - we know that any other block must either be on the path from A to B, or 532 // it must be on a path from the root to A, but not both. So, if we haven't found A yet but 533 // we already have found a block C that has a write(), then C must be on some path from A 534 // to B, which means that A's def() is invalid for our purposes. Hence, before we find the 535 // def(), stopping on write() is the right thing to do. 536 // 537 // Stopping on write() is also the right thing to do after we find the def(). After we find 538 // the def(), we don't add that block's predecessors to the search worklist. That means 539 // that henceforth the only blocks we will see in the search are blocks on the path from 540 // the def() to us. If any such block has a write() that clobbers our heap then we should 541 // give up. 542 // 543 // Hence this graph search algorithm ends up being deceptively simple: any overlapping 544 // write() causes us to immediately return nullptr, and a matching def() means that we just 545 // record it and neglect to visit its precessors. 546 547 Vector<BasicBlock*, 8> worklist; 548 Vector<BasicBlock*, 8> seenList; 549 BitVector seen; 550 551 for (unsigned i = m_block->predecessors.size(); i--;) { 552 BasicBlock* predecessor = m_block->predecessors[i]; 553 if (!seen.get(predecessor->index)) { 554 worklist.append(predecessor); 555 seen.set(predecessor->index); 556 } 557 } 558 559 while (!worklist.isEmpty()) { 560 BasicBlock* block = worklist.takeLast(); 561 seenList.append(block); 562 563 if (verbose) 564 dataLog(" Searching in block ", *block, "\n"); 565 ImpureBlockData& data = m_impureDataMap[block->index]; 566 567 // We require strict domination because this would only see things in our own block if 568 // they came *after* our position in the block. Clearly, while our block dominates 569 // itself, the things in the block after us don't dominate us. 570 if (m_graph.m_dominators.dominates(block, m_block) && block != m_block) { 571 if (verbose) 572 dataLog(" It strictly dominates.\n"); 573 DFG_ASSERT(m_graph, m_node, data.didVisit); 574 DFG_ASSERT(m_graph, m_node, !match); 575 if (verbose) 576 dataLog(" Availability map: ", mapDump(data.availableAtTail), "\n"); 577 match = data.availableAtTail.get(location); 578 if (verbose) 579 dataLog(" Availability: ", match, "\n"); 580 if (match) { 581 // Don't examine the predecessors of a match. At this point we just want to 582 // establish that other blocks on the path from here to there don't clobber 583 // the location we're interested in. 584 continue; 79 585 } 80 586 } 81 } 82 83 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { 84 BasicBlock* block = m_graph.block(blockIndex); 85 if (!block) 86 continue; 87 88 for (unsigned i = block->size(); i--;) { 89 Node* node = block->at(i); 90 if (!node->containsMovHint()) 91 continue; 92 93 ASSERT(node->op() != ZombieHint); 94 node->child1()->mergeFlags(NodeRelevantToOSR); 95 } 96 } 97 98 if (m_graph.m_form == SSA) { 99 Vector<BasicBlock*> depthFirst; 100 m_graph.getBlocksInDepthFirstOrder(depthFirst); 101 for (unsigned i = 0; i < depthFirst.size(); ++i) 102 performBlockCSE(depthFirst[i]); 103 } else { 104 for (unsigned blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) 105 performBlockCSE(m_graph.block(blockIndex)); 106 } 107 108 return m_changed; 109 } 110 111 private: 112 113 unsigned endIndexForPureCSE() 114 { 115 unsigned result = m_lastSeen[m_currentNode->op()]; 116 if (result == UINT_MAX) 117 result = 0; 118 else 119 result++; 120 ASSERT(result <= m_indexInBlock); 121 return result; 122 } 123 124 Node* pureCSE(Node* node) 125 { 126 Edge child1 = node->child1().sanitized(); 127 Edge child2 = node->child2().sanitized(); 128 Edge child3 = node->child3().sanitized(); 129 130 for (unsigned i = endIndexForPureCSE(); i--;) { 131 Node* otherNode = m_currentBlock->at(i); 132 if (otherNode == child1 || otherNode == child2 || otherNode == child3) 133 break; 134 135 if (node->op() != otherNode->op()) 136 continue; 137 138 Edge otherChild = otherNode->child1().sanitized(); 139 if (!otherChild) 140 return otherNode; 141 if (otherChild != child1) 142 continue; 143 144 otherChild = otherNode->child2().sanitized(); 145 if (!otherChild) 146 return otherNode; 147 if (otherChild != child2) 148 continue; 149 150 otherChild = otherNode->child3().sanitized(); 151 if (!otherChild) 152 return otherNode; 153 if (otherChild != child3) 154 continue; 155 156 return otherNode; 157 } 158 return 0; 159 } 160 161 Node* constantCSE(Node* node) 162 { 163 for (unsigned i = endIndexForPureCSE(); i--;) { 164 Node* otherNode = m_currentBlock->at(i); 165 if (otherNode->op() != node->op()) 166 continue; 167 168 if (otherNode->constant() != node->constant()) 169 continue; 170 171 return otherNode; 172 } 173 return 0; 174 } 175 176 Node* constantStoragePointerCSE(Node* node) 177 { 178 for (unsigned i = endIndexForPureCSE(); i--;) { 179 Node* otherNode = m_currentBlock->at(i); 180 if (otherNode->op() != ConstantStoragePointer) 181 continue; 182 183 if (otherNode->storagePointer() != node->storagePointer()) 184 continue; 185 186 return otherNode; 187 } 188 return 0; 189 } 190 191 Node* getCalleeLoadElimination() 192 { 193 for (unsigned i = m_indexInBlock; i--;) { 194 Node* node = m_currentBlock->at(i); 195 switch (node->op()) { 196 case GetCallee: 197 return node; 198 default: 199 break; 200 } 201 } 202 return 0; 203 } 204 205 Node* getArrayLengthElimination(Node* array) 206 { 207 for (unsigned i = m_indexInBlock; i--;) { 208 Node* node = m_currentBlock->at(i); 209 switch (node->op()) { 210 case GetArrayLength: 211 if (node->child1() == array) 212 return node; 213 break; 214 215 case PutByValDirect: 216 case PutByVal: 217 if (!m_graph.byValIsPure(node)) 218 return 0; 219 if (node->arrayMode().mayStoreToHole()) 220 return 0; 221 break; 222 223 default: 224 if (m_graph.clobbersWorld(node)) 225 return 0; 226 } 227 } 228 return 0; 229 } 230 231 Node* globalVarLoadElimination(WriteBarrier<Unknown>* registerPointer) 232 { 233 for (unsigned i = m_indexInBlock; i--;) { 234 Node* node = m_currentBlock->at(i); 235 switch (node->op()) { 236 case GetGlobalVar: 237 if (node->registerPointer() == registerPointer) 238 return node; 239 break; 240 case PutGlobalVar: 241 if (node->registerPointer() == registerPointer) 242 return node->child1().node(); 243 break; 244 default: 245 break; 246 } 247 if (m_graph.clobbersWorld(node)) 248 break; 249 } 250 return 0; 251 } 252 253 Node* scopedVarLoadElimination(Node* registers, int varNumber) 254 { 255 for (unsigned i = m_indexInBlock; i--;) { 256 Node* node = m_currentBlock->at(i); 257 switch (node->op()) { 258 case GetClosureVar: { 259 if (node->child1() == registers && node->varNumber() == varNumber) 260 return node; 261 break; 262 } 263 case PutClosureVar: { 264 if (node->varNumber() != varNumber) 265 break; 266 if (node->child2() == registers) 267 return node->child3().node(); 268 return 0; 269 } 270 case SetLocal: { 271 VariableAccessData* variableAccessData = node->variableAccessData(); 272 if (variableAccessData->isCaptured() 273 && variableAccessData->local() == static_cast<VirtualRegister>(varNumber)) 274 return 0; 275 break; 276 } 277 default: 278 break; 279 } 280 if (m_graph.clobbersWorld(node)) 281 break; 282 } 283 return 0; 284 } 285 286 bool varInjectionWatchpointElimination() 287 { 288 for (unsigned i = m_indexInBlock; i--;) { 289 Node* node = m_currentBlock->at(i); 290 if (node->op() == VarInjectionWatchpoint) 291 return true; 292 if (m_graph.clobbersWorld(node)) 293 break; 294 } 295 return false; 296 } 297 298 Node* getByValLoadElimination(Node* child1, Node* child2, ArrayMode arrayMode) 299 { 300 for (unsigned i = m_indexInBlock; i--;) { 301 Node* node = m_currentBlock->at(i); 302 if (node == child1 || node == child2) 303 break; 304 305 switch (node->op()) { 306 case GetByVal: 307 if (!m_graph.byValIsPure(node)) 308 return 0; 309 if (node->child1() == child1 310 && node->child2() == child2 311 && node->arrayMode().type() == arrayMode.type()) 312 return node; 313 break; 314 315 case PutByValDirect: 316 case PutByVal: 317 case PutByValAlias: { 318 if (!m_graph.byValIsPure(node)) 319 return 0; 320 // Typed arrays 321 if (arrayMode.typedArrayType() != NotTypedArray) 322 return 0; 323 if (m_graph.varArgChild(node, 0) == child1 324 && m_graph.varArgChild(node, 1) == child2 325 && node->arrayMode().type() == arrayMode.type()) 326 return m_graph.varArgChild(node, 2).node(); 327 // We must assume that the PutByVal will clobber the location we're getting from. 328 // FIXME: We can do better; if we know that the PutByVal is accessing an array of a 329 // different type than the GetByVal, then we know that they won't clobber each other. 330 // ... except of course for typed arrays, where all typed arrays clobber all other 331 // typed arrays! An Int32Array can alias a Float64Array for example, and so on. 332 return 0; 333 } 334 default: 335 if (m_graph.clobbersWorld(node)) 336 return 0; 337 break; 338 } 339 } 340 return 0; 341 } 342 343 bool checkFunctionElimination(FrozenValue* function, Node* child1) 344 { 345 for (unsigned i = endIndexForPureCSE(); i--;) { 346 Node* node = m_currentBlock->at(i); 347 if (node == child1) 348 break; 349 350 if (node->op() == CheckFunction && node->child1() == child1 && node->function() == function) 351 return true; 352 } 353 return false; 354 } 355 356 bool checkExecutableElimination(ExecutableBase* executable, Node* child1) 357 { 358 for (unsigned i = endIndexForPureCSE(); i--;) { 359 Node* node = m_currentBlock->at(i); 360 if (node == child1) 361 break; 362 363 if (node->op() == CheckExecutable && node->child1() == child1 && node->executable() == executable) 364 return true; 365 } 366 return false; 367 } 368 369 bool checkStructureElimination(const StructureSet& structureSet, Node* child1) 370 { 371 for (unsigned i = m_indexInBlock; i--;) { 372 Node* node = m_currentBlock->at(i); 373 if (node == child1) 374 break; 375 376 switch (node->op()) { 377 case CheckStructure: 378 if (node->child1() == child1 379 && structureSet.isSupersetOf(node->structureSet())) 380 return true; 381 break; 382 383 case PutStructure: 384 if (node->child1() == child1 385 && structureSet.contains(node->transition()->next)) 386 return true; 387 if (structureSet.contains(node->transition()->previous)) 388 return false; 389 break; 390 391 case PutByOffset: 392 // Setting a property cannot change the structure. 393 break; 394 395 case MultiPutByOffset: 396 if (node->multiPutByOffsetData().writesStructures()) 397 return false; 398 break; 399 400 case PutByValDirect: 401 case PutByVal: 402 case PutByValAlias: 403 if (m_graph.byValIsPure(node)) { 404 // If PutByVal speculates that it's accessing an array with an 405 // integer index, then it's impossible for it to cause a structure 406 // change. 407 break; 587 588 if (verbose) 589 dataLog(" Dealing with write set ", data.writes, "\n"); 590 if (data.writes.overlaps(location.heap())) { 591 if (verbose) 592 dataLog(" Clobbered.\n"); 593 return nullptr; 594 } 595 596 for (unsigned i = block->predecessors.size(); i--;) { 597 BasicBlock* predecessor = block->predecessors[i]; 598 if (!seen.get(predecessor->index)) { 599 worklist.append(predecessor); 600 seen.set(predecessor->index); 408 601 } 409 return false; 410 411 case Arrayify: 412 case ArrayifyToStructure: 413 // We could check if the arrayification could affect our structures. 414 // But that seems like it would take Effort. 415 return false; 416 417 default: 418 if (m_graph.clobbersWorld(node)) 419 return false; 420 break; 421 } 422 } 423 return false; 424 } 425 426 bool structureTransitionWatchpointElimination(Structure* structure, Node* child1) 427 { 428 for (unsigned i = m_indexInBlock; i--;) { 429 Node* node = m_currentBlock->at(i); 430 if (node == child1) 431 break; 432 433 switch (node->op()) { 434 case CheckStructure: 435 if (node->child1() == child1 436 && node->structureSet().isSubsetOf(StructureSet(structure))) 437 return true; 438 break; 439 440 case PutStructure: 441 ASSERT(node->transition()->previous != structure); 442 break; 443 444 case PutByOffset: 445 // Setting a property cannot change the structure. 446 break; 447 448 case MultiPutByOffset: 449 if (node->multiPutByOffsetData().writesStructures()) 450 return false; 451 break; 452 453 case PutByValDirect: 454 case PutByVal: 455 case PutByValAlias: 456 if (m_graph.byValIsPure(node)) { 457 // If PutByVal speculates that it's accessing an array with an 458 // integer index, then it's impossible for it to cause a structure 459 // change. 460 break; 461 } 462 return false; 463 464 case Arrayify: 465 case ArrayifyToStructure: 466 // We could check if the arrayification could affect our structures. 467 // But that seems like it would take Effort. 468 return false; 469 470 default: 471 if (m_graph.clobbersWorld(node)) 472 return false; 473 break; 474 } 475 } 476 return false; 477 } 478 479 Node* getByOffsetLoadElimination(unsigned identifierNumber, Node* base) 480 { 481 for (unsigned i = m_indexInBlock; i--;) { 482 Node* node = m_currentBlock->at(i); 483 if (node == base) 484 break; 485 486 switch (node->op()) { 487 case GetByOffset: 488 if (node->child2() == base 489 && m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber) 490 return node; 491 break; 492 493 case MultiGetByOffset: 494 if (node->child1() == base 495 && node->multiGetByOffsetData().identifierNumber == identifierNumber) 496 return node; 497 break; 498 499 case PutByOffset: 500 if (m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber) { 501 if (node->child2() == base) // Must be same property storage. 502 return node->child3().node(); 503 return 0; 504 } 505 break; 506 507 case MultiPutByOffset: 508 if (node->multiPutByOffsetData().identifierNumber == identifierNumber) { 509 if (node->child1() == base) 510 return node->child2().node(); 511 return 0; 512 } 513 break; 514 515 case PutByValDirect: 516 case PutByVal: 517 case PutByValAlias: 518 if (m_graph.byValIsPure(node)) { 519 // If PutByVal speculates that it's accessing an array with an 520 // integer index, then it's impossible for it to cause a structure 521 // change. 522 break; 523 } 524 return 0; 525 526 default: 527 if (m_graph.clobbersWorld(node)) 528 return 0; 529 break; 530 } 531 } 532 return 0; 533 } 534 535 Node* getGetterSetterByOffsetLoadElimination(unsigned identifierNumber, Node* base) 536 { 537 for (unsigned i = m_indexInBlock; i--;) { 538 Node* node = m_currentBlock->at(i); 539 if (node == base) 540 break; 541 542 switch (node->op()) { 543 case GetGetterSetterByOffset: 544 if (node->child2() == base 545 && m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber) 546 return node; 547 break; 548 549 case PutByValDirect: 550 case PutByVal: 551 case PutByValAlias: 552 if (m_graph.byValIsPure(node)) { 553 // If PutByVal speculates that it's accessing an array with an 554 // integer index, then it's impossible for it to cause a structure 555 // change. 556 break; 557 } 558 return 0; 559 560 default: 561 if (m_graph.clobbersWorld(node)) 562 return 0; 563 break; 564 } 565 } 566 return 0; 567 } 568 569 Node* getPropertyStorageLoadElimination(Node* child1) 570 { 571 for (unsigned i = m_indexInBlock; i--;) { 572 Node* node = m_currentBlock->at(i); 573 if (node == child1) 574 break; 575 576 switch (node->op()) { 577 case GetButterfly: 578 if (node->child1() == child1) 579 return node; 580 break; 581 582 case AllocatePropertyStorage: 583 case ReallocatePropertyStorage: 584 // If we can cheaply prove this is a change to our object's storage, we 585 // can optimize and use its result. 586 if (node->child1() == child1) 587 return node; 588 // Otherwise, we currently can't prove that this doesn't change our object's 589 // storage, so we conservatively assume that it may change the storage 590 // pointer of any object, including ours. 591 return 0; 592 593 case PutByValDirect: 594 case PutByVal: 595 case PutByValAlias: 596 if (m_graph.byValIsPure(node)) { 597 // If PutByVal speculates that it's accessing an array with an 598 // integer index, then it's impossible for it to cause a structure 599 // change. 600 break; 601 } 602 return 0; 603 604 case Arrayify: 605 case ArrayifyToStructure: 606 // We could check if the arrayification could affect our butterfly. 607 // But that seems like it would take Effort. 608 return 0; 609 610 case MultiPutByOffset: 611 if (node->multiPutByOffsetData().reallocatesStorage()) 612 return 0; 613 break; 614 615 default: 616 if (m_graph.clobbersWorld(node)) 617 return 0; 618 break; 619 } 620 } 621 return 0; 622 } 623 624 bool checkArrayElimination(Node* child1, ArrayMode arrayMode) 625 { 626 for (unsigned i = m_indexInBlock; i--;) { 627 Node* node = m_currentBlock->at(i); 628 if (node == child1) 629 break; 630 631 switch (node->op()) { 632 case CheckArray: 633 if (node->child1() == child1 && node->arrayMode() == arrayMode) 634 return true; 635 break; 636 637 case Arrayify: 638 case ArrayifyToStructure: 639 // We could check if the arrayification could affect our array. 640 // But that seems like it would take Effort. 641 return false; 642 643 default: 644 if (m_graph.clobbersWorld(node)) 645 return false; 646 break; 647 } 648 } 649 return false; 650 } 651 652 Node* getIndexedPropertyStorageLoadElimination(Node* child1, ArrayMode arrayMode) 653 { 654 for (unsigned i = m_indexInBlock; i--;) { 655 Node* node = m_currentBlock->at(i); 656 if (node == child1) 657 break; 658 659 switch (node->op()) { 660 case GetIndexedPropertyStorage: { 661 if (node->child1() == child1 && node->arrayMode() == arrayMode) 662 return node; 663 break; 664 } 665 666 default: 667 if (m_graph.clobbersWorld(node)) 668 return 0; 669 break; 670 } 671 } 672 return 0; 673 } 674 675 Node* getInternalFieldLoadElimination(NodeType op, Node* child1) 676 { 677 for (unsigned i = m_indexInBlock; i--;) { 678 Node* node = m_currentBlock->at(i); 679 if (node == child1) 680 break; 681 682 if (node->op() == op && node->child1() == child1) 683 return node; 684 685 if (m_graph.clobbersWorld(node)) 686 return 0; 687 } 688 return 0; 689 } 690 691 Node* getMyScopeLoadElimination() 692 { 693 for (unsigned i = m_indexInBlock; i--;) { 694 Node* node = m_currentBlock->at(i); 695 switch (node->op()) { 696 case CreateActivation: 697 // This may cause us to return a different scope. 698 return 0; 699 case GetMyScope: 700 return node; 701 default: 702 break; 703 } 704 } 705 return 0; 706 } 707 708 Node* getLocalLoadElimination(VirtualRegister local, Node*& relevantLocalOp, bool careAboutClobbering) 709 { 710 relevantLocalOp = 0; 711 712 for (unsigned i = m_indexInBlock; i--;) { 713 Node* node = m_currentBlock->at(i); 714 switch (node->op()) { 715 case GetLocal: 716 if (node->local() == local) { 717 relevantLocalOp = node; 718 return node; 719 } 720 break; 721 722 case GetLocalUnlinked: 723 if (node->unlinkedLocal() == local) { 724 relevantLocalOp = node; 725 return node; 726 } 727 break; 728 729 case SetLocal: 730 if (node->local() == local) { 731 relevantLocalOp = node; 732 return node->child1().node(); 733 } 734 break; 735 736 case GetClosureVar: 737 case PutClosureVar: 738 if (static_cast<VirtualRegister>(node->varNumber()) == local) 739 return 0; 740 break; 741 742 default: 743 if (careAboutClobbering && m_graph.clobbersWorld(node)) 744 return 0; 745 break; 746 } 747 } 748 return 0; 749 } 750 751 Node* uncapturedSetLocalStoreElimination(VirtualRegister local) 752 { 753 for (unsigned i = m_indexInBlock; i--;) { 754 Node* node = m_currentBlock->at(i); 755 switch (node->op()) { 756 case GetLocal: 757 case Flush: 758 if (node->local() == local) 759 return nullptr; 760 break; 761 762 case GetLocalUnlinked: 763 if (node->unlinkedLocal() == local) 764 return nullptr; 765 break; 766 767 case SetLocal: { 768 if (node->local() != local) 769 break; 770 return node; 771 } 772 773 case GetClosureVar: 774 case PutClosureVar: 775 if (static_cast<VirtualRegister>(node->varNumber()) == local) 776 return nullptr; 777 break; 778 779 case GetMyScope: 780 case SkipTopScope: 781 if (node->origin.semantic.inlineCallFrame) 782 break; 783 if (m_graph.uncheckedActivationRegister() == local) 784 return nullptr; 785 break; 786 787 case CheckArgumentsNotCreated: 788 case GetMyArgumentsLength: 789 case GetMyArgumentsLengthSafe: 790 if (m_graph.uncheckedArgumentsRegisterFor(node->origin.semantic) == local) 791 return nullptr; 792 break; 793 794 case GetMyArgumentByVal: 795 case GetMyArgumentByValSafe: 796 return nullptr; 797 798 case GetByVal: 799 // If this is accessing arguments then it's potentially accessing locals. 800 if (node->arrayMode().type() == Array::Arguments) 801 return nullptr; 802 break; 803 804 case CreateArguments: 805 case TearOffActivation: 806 case TearOffArguments: 807 // If an activation is being torn off then it means that captured variables 808 // are live. We could be clever here and check if the local qualifies as an 809 // argument register. But that seems like it would buy us very little since 810 // any kind of tear offs are rare to begin with. 811 return nullptr; 812 813 default: 814 break; 815 } 816 if (m_graph.clobbersWorld(node)) 817 return nullptr; 818 } 819 return nullptr; 820 } 821 822 Node* capturedSetLocalStoreElimination(VirtualRegister local) 823 { 824 for (unsigned i = m_indexInBlock; i--;) { 825 Node* node = m_currentBlock->at(i); 826 switch (node->op()) { 827 case GetLocal: 828 case Flush: 829 if (node->local() == local) 830 return nullptr; 831 break; 832 833 case GetLocalUnlinked: 834 if (node->unlinkedLocal() == local) 835 return nullptr; 836 break; 837 838 case SetLocal: { 839 if (node->local() != local) 840 break; 841 return node; 842 } 843 844 case Phantom: 845 case Check: 846 case HardPhantom: 847 case MovHint: 848 case JSConstant: 849 case DoubleConstant: 850 case Int52Constant: 851 break; 852 853 default: 854 return nullptr; 855 } 856 } 857 return nullptr; 858 } 859 860 Node* setLocalStoreElimination(VariableAccessData* variableAccessData) 861 { 862 if (variableAccessData->isCaptured()) 863 return capturedSetLocalStoreElimination(variableAccessData->local()); 864 return uncapturedSetLocalStoreElimination(variableAccessData->local()); 865 } 866 867 bool invalidationPointElimination() 868 { 869 for (unsigned i = m_indexInBlock; i--;) { 870 Node* node = m_currentBlock->at(i); 871 if (node->op() == InvalidationPoint) 872 return true; 873 if (writesOverlap(m_graph, node, Watchpoint_fire)) 874 break; 875 } 876 return false; 877 } 878 879 void eliminateIrrelevantPhantomChildren(Node* node) 880 { 881 ASSERT(node->op() == Phantom); 882 for (unsigned i = 0; i < AdjacencyList::Size; ++i) { 883 Edge edge = node->children.child(i); 884 if (!edge) 885 continue; 886 if (edge.useKind() != UntypedUse) 887 continue; // Keep the type check. 888 if (edge->flags() & NodeRelevantToOSR) 889 continue; 890 891 node->children.removeEdge(i--); 892 m_changed = true; 893 } 894 } 895 896 bool setReplacement(Node* replacement) 897 { 898 if (!replacement) 899 return false; 900 901 if (!ASSERT_DISABLED 902 && canonicalResultRepresentation(m_currentNode->result()) != canonicalResultRepresentation(replacement->result())) { 903 startCrashing(); 904 dataLog("CSE attempting to replace a node with a mismatched result: ", m_currentNode, " with ", replacement, "\n"); 905 dataLog("\n"); 906 m_graph.dump(); 907 RELEASE_ASSERT_NOT_REACHED(); 908 } 909 910 m_currentNode->convertToPhantom(); 911 eliminateIrrelevantPhantomChildren(m_currentNode); 912 913 // At this point we will eliminate all references to this node. 914 m_currentNode->misc.replacement = replacement; 915 602 } 603 } 604 605 if (!match) 606 return nullptr; 607 608 // Cache the results for next time. We cache them both for this block and for all of our 609 // predecessors, since even though we've already visited our predecessors, our predecessors 610 // probably have successors other than us. 611 // FIXME: Consider caching failed searches as well, when match is null. It's not clear that 612 // the reduction in compile time would warrant the increase in complexity, though. 613 // https://bugs.webkit.org/show_bug.cgi?id=134876 614 for (BasicBlock* block : seenList) 615 m_impureDataMap[block->index].availableAtTail.add(location, match); 616 m_impureData->availableAtTail.add(location, match); 617 618 return match; 619 } 620 621 void def(HeapLocation location, Node* value) 622 { 623 if (verbose) 624 dataLog(" Got heap location def: ", location, " -> ", value, "\n"); 625 626 Node* match = findReplacement(location); 627 628 if (verbose) 629 dataLog(" Got match: ", match, "\n"); 630 631 if (!match) { 632 if (verbose) 633 dataLog(" Adding at-tail mapping: ", location, " -> ", value, "\n"); 634 auto result = m_impureData->availableAtTail.add(location, value); 635 ASSERT_UNUSED(result, result.isNewEntry); 636 return; 637 } 638 639 m_node->replaceWith(match); 916 640 m_changed = true; 917 918 return true; 919 } 920 921 void eliminate() 922 { 923 ASSERT(m_currentNode->mustGenerate()); 924 m_currentNode->convertToPhantom(); 925 eliminateIrrelevantPhantomChildren(m_currentNode); 926 927 m_changed = true; 928 } 929 930 void eliminate(Node* node, NodeType phantomType = Phantom) 931 { 932 if (!node) 933 return; 934 ASSERT(node->mustGenerate()); 935 node->setOpAndDefaultFlags(phantomType); 936 if (phantomType == Phantom) 937 eliminateIrrelevantPhantomChildren(node); 938 939 m_changed = true; 940 } 941 942 void performNodeCSE(Node* node) 943 { 944 m_graph.performSubstitution(node); 945 946 switch (node->op()) { 947 948 case Identity: 949 setReplacement(node->child1().node()); 950 break; 951 952 // Handle the pure nodes. These nodes never have any side-effects. 953 case BitAnd: 954 case BitOr: 955 case BitXor: 956 case BitRShift: 957 case BitLShift: 958 case BitURShift: 959 case ArithAbs: 960 case ArithMin: 961 case ArithMax: 962 case ArithSqrt: 963 case ArithFRound: 964 case ArithSin: 965 case ArithCos: 966 case StringCharAt: 967 case StringCharCodeAt: 968 case IsUndefined: 969 case IsBoolean: 970 case IsNumber: 971 case IsString: 972 case IsObject: 973 case IsFunction: 974 case LogicalNot: 975 case SkipTopScope: 976 case SkipScope: 977 case GetClosureRegisters: 978 case GetScope: 979 case TypeOf: 980 case CompareEqConstant: 981 case ValueToInt32: 982 case MakeRope: 983 case DoubleRep: 984 case ValueRep: 985 case Int52Rep: 986 case BooleanToNumber: 987 setReplacement(pureCSE(node)); 988 break; 989 990 case ArithAdd: 991 case ArithSub: 992 case ArithNegate: 993 case ArithMul: 994 case ArithDiv: 995 case ArithMod: 996 case UInt32ToNumber: 997 case DoubleAsInt32: { 998 Node* candidate = pureCSE(node); 999 if (!candidate) 1000 break; 1001 if (!subsumes(candidate->arithMode(), node->arithMode())) { 1002 if (!subsumes(node->arithMode(), candidate->arithMode())) 1003 break; 1004 candidate->setArithMode(node->arithMode()); 1005 } 1006 setReplacement(candidate); 1007 break; 1008 } 1009 1010 case GetCallee: 1011 setReplacement(getCalleeLoadElimination()); 1012 break; 1013 1014 case GetLocal: { 1015 VariableAccessData* variableAccessData = node->variableAccessData(); 1016 if (!variableAccessData->isCaptured()) 1017 break; 1018 Node* relevantLocalOp; 1019 Node* possibleReplacement = getLocalLoadElimination(variableAccessData->local(), relevantLocalOp, variableAccessData->isCaptured()); 1020 if (!relevantLocalOp) 1021 break; 1022 if (relevantLocalOp->op() != GetLocalUnlinked 1023 && relevantLocalOp->variableAccessData() != variableAccessData) 1024 break; 1025 Node* phi = node->child1().node(); 1026 if (!setReplacement(possibleReplacement)) 1027 break; 1028 1029 m_graph.dethread(); 1030 1031 // If we replace a GetLocal with a GetLocalUnlinked, then turn the GetLocalUnlinked 1032 // into a GetLocal. 1033 if (relevantLocalOp->op() == GetLocalUnlinked) 1034 relevantLocalOp->convertToGetLocal(variableAccessData, phi); 1035 1036 m_changed = true; 1037 break; 1038 } 1039 1040 case GetLocalUnlinked: { 1041 Node* relevantLocalOpIgnored; 1042 setReplacement(getLocalLoadElimination(node->unlinkedLocal(), relevantLocalOpIgnored, true)); 1043 break; 1044 } 1045 1046 case JSConstant: 1047 case DoubleConstant: 1048 case Int52Constant: 1049 // This is strange, but necessary. Some phases will convert nodes to constants, 1050 // which may result in duplicated constants. We use CSE to clean this up. 1051 setReplacement(constantCSE(node)); 1052 break; 1053 1054 case ConstantStoragePointer: 1055 setReplacement(constantStoragePointerCSE(node)); 1056 break; 1057 1058 case GetArrayLength: 1059 setReplacement(getArrayLengthElimination(node->child1().node())); 1060 break; 1061 1062 case GetMyScope: 1063 setReplacement(getMyScopeLoadElimination()); 1064 break; 1065 1066 // Handle nodes that are conditionally pure: these are pure, and can 1067 // be CSE'd, so long as the prediction is the one we want. 1068 case CompareLess: 1069 case CompareLessEq: 1070 case CompareGreater: 1071 case CompareGreaterEq: 1072 case CompareEq: { 1073 if (m_graph.isPredictedNumerical(node)) { 1074 Node* replacement = pureCSE(node); 1075 if (replacement && m_graph.isPredictedNumerical(replacement)) 1076 setReplacement(replacement); 1077 } 1078 break; 1079 } 1080 1081 // Finally handle heap accesses. These are not quite pure, but we can still 1082 // optimize them provided that some subtle conditions are met. 1083 case GetGlobalVar: 1084 setReplacement(globalVarLoadElimination(node->registerPointer())); 1085 break; 1086 1087 case GetClosureVar: { 1088 setReplacement(scopedVarLoadElimination(node->child1().node(), node->varNumber())); 1089 break; 1090 } 1091 1092 case VarInjectionWatchpoint: 1093 if (varInjectionWatchpointElimination()) 1094 eliminate(); 1095 break; 1096 1097 case GetByVal: 1098 if (m_graph.byValIsPure(node)) 1099 setReplacement(getByValLoadElimination(node->child1().node(), node->child2().node(), node->arrayMode())); 1100 break; 1101 1102 case PutByValDirect: 1103 case PutByVal: { 1104 Edge child1 = m_graph.varArgChild(node, 0); 1105 Edge child2 = m_graph.varArgChild(node, 1); 1106 if (node->arrayMode().canCSEStorage()) { 1107 Node* replacement = getByValLoadElimination(child1.node(), child2.node(), node->arrayMode()); 1108 if (!replacement) 1109 break; 1110 node->setOp(PutByValAlias); 1111 } 1112 break; 1113 } 1114 1115 case CheckStructure: 1116 if (checkStructureElimination(node->structureSet(), node->child1().node())) 1117 eliminate(); 1118 break; 1119 1120 case CheckFunction: 1121 if (checkFunctionElimination(node->function(), node->child1().node())) 1122 eliminate(); 1123 break; 1124 1125 case CheckExecutable: 1126 if (checkExecutableElimination(node->executable(), node->child1().node())) 1127 eliminate(); 1128 break; 1129 1130 case CheckArray: 1131 if (checkArrayElimination(node->child1().node(), node->arrayMode())) 1132 eliminate(); 1133 break; 1134 1135 case GetIndexedPropertyStorage: { 1136 setReplacement(getIndexedPropertyStorageLoadElimination(node->child1().node(), node->arrayMode())); 1137 break; 1138 } 1139 1140 case GetTypedArrayByteOffset: 1141 case GetGetter: 1142 case GetSetter: { 1143 setReplacement(getInternalFieldLoadElimination(node->op(), node->child1().node())); 1144 break; 1145 } 1146 1147 case GetButterfly: 1148 setReplacement(getPropertyStorageLoadElimination(node->child1().node())); 1149 break; 1150 1151 case GetByOffset: 1152 setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child2().node())); 1153 break; 1154 1155 case GetGetterSetterByOffset: 1156 setReplacement(getGetterSetterByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child2().node())); 1157 break; 1158 1159 case MultiGetByOffset: 1160 setReplacement(getByOffsetLoadElimination(node->multiGetByOffsetData().identifierNumber, node->child1().node())); 1161 break; 1162 1163 case InvalidationPoint: 1164 if (invalidationPointElimination()) 1165 eliminate(); 1166 break; 1167 1168 case Phantom: 1169 // FIXME: we ought to remove Phantom's that have no children. 1170 // NB. It would be incorrect to do this for HardPhantom. In fact, the whole point 1171 // of HardPhantom is that we *don't* do this for HardPhantoms, since they signify 1172 // a more strict kind of liveness than the Phantom bytecode liveness. 1173 eliminateIrrelevantPhantomChildren(node); 1174 break; 1175 1176 case Flush: 1177 // This is needed for arguments simplification to work. We need to eliminate the 1178 // redundancy between op_enter's undefined-all-the-things and the subsequent 1179 // op_init_lazy_reg. 1180 1181 ASSERT(m_graph.m_form != SSA); 1182 1183 if (Node* setLocal = setLocalStoreElimination(node->variableAccessData())) { 1184 node->convertToPhantom(); 1185 Node* dataNode = setLocal->child1().node(); 1186 ASSERT(dataNode->hasResult()); 1187 node->child1() = dataNode->defaultEdge(); 1188 m_graph.dethread(); 1189 m_changed = true; 1190 } 1191 break; 1192 1193 default: 1194 // do nothing. 1195 break; 1196 } 1197 1198 m_lastSeen[node->op()] = m_indexInBlock; 1199 } 1200 1201 void performBlockCSE(BasicBlock* block) 1202 { 1203 if (!block) 1204 return; 1205 if (!block->isReachable) 1206 return; 1207 1208 m_currentBlock = block; 1209 for (unsigned i = 0; i < LastNodeType; ++i) 1210 m_lastSeen[i] = UINT_MAX; 1211 1212 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) { 1213 m_currentNode = block->at(m_indexInBlock); 1214 performNodeCSE(m_currentNode); 1215 } 1216 } 1217 1218 BasicBlock* m_currentBlock; 1219 Node* m_currentNode; 1220 unsigned m_indexInBlock; 1221 std::array<unsigned, LastNodeType> m_lastSeen; 1222 bool m_changed; // Only tracks changes that have a substantive effect on other optimizations. 641 } 642 643 struct ImpureBlockData { 644 ImpureBlockData() 645 : didVisit(false) 646 { 647 } 648 649 ClobberSet writes; 650 ImpureMap availableAtTail; 651 bool didVisit; 652 }; 653 654 Vector<BasicBlock*> m_preOrder; 655 656 PureMultiMap m_pureValues; 657 Vector<ImpureBlockData> m_impureDataMap; 658 659 BasicBlock* m_block; 660 Node* m_node; 661 ImpureBlockData* m_impureData; 662 ClobberSet m_writesSoFar; 663 664 bool m_changed; 1223 665 }; 1224 666 1225 bool performCSE(Graph& graph) 667 } // anonymous namespace 668 669 bool performLocalCSE(Graph& graph) 1226 670 { 1227 SamplingRegion samplingRegion("DFG CSE Phase");1228 return runPhase< CSEPhase>(graph);671 SamplingRegion samplingRegion("DFG LocalCSE Phase"); 672 return runPhase<LocalCSEPhase>(graph); 1229 673 } 1230 674 675 bool performGlobalCSE(Graph& graph) 676 { 677 SamplingRegion samplingRegion("DFG GlobalCSE Phase"); 678 return runPhase<GlobalCSEPhase>(graph); 679 } 680 1231 681 } } // namespace JSC::DFG 1232 682 1233 683 #endif // ENABLE(DFG_JIT) 1234 1235 -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.h
r171613 r172129 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 35 35 class Graph; 36 36 37 // Block-local common subexpression elimination. This is an optional phase, but 38 // it is rather profitable. It has fairly accurate heap modeling and will match 39 // a wide range of subexpression similarities. It's known to produce big wins 40 // on a few benchmarks, and is relatively cheap to run. 41 bool performCSE(Graph&); 37 // Block-local common subexpression elimination. It uses clobberize() for heap 38 // modeling, which is quite precise. This phase is known to produce big wins on 39 // a few benchmarks, and is relatively cheap to run. 40 // 41 // Note that this phase also gets rid of Identity nodes, which means that it's 42 // currently not an optional phase. Basically, DFG IR doesn't have use-lists, 43 // so there is no instantaneous replaceAllUsesWith operation. Instead, you turn 44 // a node into an Identity and wait for CSE to clean it up. 45 bool performLocalCSE(Graph&); 46 47 // Same, but global. Only works for SSA. This will find common subexpressions 48 // both in the same block and in any block that dominates the current block. It 49 // has no limits on how far it will look for load-elimination opportunities. 50 bool performGlobalCSE(Graph&); 42 51 43 52 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
r168178 r172129 46 46 } 47 47 48 bool isSupportedForInlining(CodeBlock* codeBlock) 49 { 50 return !codeBlock->ownerExecutable()->needsActivation() 51 && codeBlock->ownerExecutable()->isInliningCandidate(); 52 } 53 48 54 bool mightCompileEval(CodeBlock* codeBlock) 49 55 { … … 70 76 { 71 77 return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount() 72 && !codeBlock->ownerExecutable()->needsActivation() 73 && codeBlock->ownerExecutable()->isInliningCandidate(); 78 && isSupportedForInlining(codeBlock); 74 79 } 75 80 bool mightInlineFunctionForClosureCall(CodeBlock* codeBlock) 76 81 { 77 82 return codeBlock->instructionCount() <= Options::maximumFunctionForClosureCallInlineCandidateInstructionCount() 78 && !codeBlock->ownerExecutable()->needsActivation() 79 && codeBlock->ownerExecutable()->isInliningCandidate(); 83 && isSupportedForInlining(codeBlock); 80 84 } 81 85 bool mightInlineFunctionForConstruct(CodeBlock* codeBlock) 82 86 { 83 87 return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount() 84 && !codeBlock->ownerExecutable()->needsActivation() 85 && codeBlock->ownerExecutable()->isInliningCandidate(); 88 && isSupportedForInlining(codeBlock); 86 89 } 87 90 -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.h
r170011 r172129 40 40 // check opcodes. 41 41 bool isSupported(CodeBlock*); 42 bool isSupportedForInlining(CodeBlock*); 42 43 bool mightCompileEval(CodeBlock*); 43 44 bool mightCompileProgram(CodeBlock*); -
trunk/Source/JavaScriptCore/dfg/DFGClobberSet.cpp
r164229 r172129 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 123 123 { 124 124 ClobberSetAdd addRead(readSet); 125 NoOpClobberize addWrite;126 clobberize(graph, node, addRead, addWrite);125 NoOpClobberize noOp; 126 clobberize(graph, node, addRead, noOp, noOp); 127 127 } 128 128 129 129 void addWrites(Graph& graph, Node* node, ClobberSet& writeSet) 130 130 { 131 NoOpClobberize addRead;131 NoOpClobberize noOp; 132 132 ClobberSetAdd addWrite(writeSet); 133 clobberize(graph, node, addRead, addWrite);133 clobberize(graph, node, noOp, addWrite, noOp); 134 134 } 135 135 … … 138 138 ClobberSetAdd addRead(readSet); 139 139 ClobberSetAdd addWrite(writeSet); 140 clobberize(graph, node, addRead, addWrite); 140 NoOpClobberize noOp; 141 clobberize(graph, node, addRead, addWrite, noOp); 141 142 } 142 143 … … 144 145 { 145 146 ClobberSetOverlaps addRead(readSet); 146 NoOpClobberize addWrite;147 clobberize(graph, node, addRead, addWrite);147 NoOpClobberize noOp; 148 clobberize(graph, node, addRead, noOp, noOp); 148 149 return addRead.result(); 149 150 } … … 151 152 bool writesOverlap(Graph& graph, Node* node, ClobberSet& writeSet) 152 153 { 153 NoOpClobberize addRead;154 NoOpClobberize noOp; 154 155 ClobberSetOverlaps addWrite(writeSet); 155 clobberize(graph, node, addRead, addWrite);156 clobberize(graph, node, noOp, addWrite, noOp); 156 157 return addWrite.result(); 157 158 } -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.cpp
r164229 r172129 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 35 35 bool doesWrites(Graph& graph, Node* node) 36 36 { 37 NoOpClobberize addRead;37 NoOpClobberize noOp; 38 38 CheckClobberize addWrite; 39 clobberize(graph, node, addRead, addWrite);39 clobberize(graph, node, noOp, addWrite, noOp); 40 40 return addWrite.result(); 41 } 42 43 bool accessesOverlap(Graph& graph, Node* node, AbstractHeap heap) 44 { 45 NoOpClobberize noOp; 46 AbstractHeapOverlaps addAccess(heap); 47 clobberize(graph, node, addAccess, addAccess, noOp); 48 return addAccess.result(); 41 49 } 42 50 43 51 bool writesOverlap(Graph& graph, Node* node, AbstractHeap heap) 44 52 { 45 NoOpClobberize addRead;53 NoOpClobberize noOp; 46 54 AbstractHeapOverlaps addWrite(heap); 47 clobberize(graph, node, addRead, addWrite);55 clobberize(graph, node, noOp, addWrite, noOp); 48 56 return addWrite.result(); 49 57 } -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r171660 r172129 32 32 #include "DFGEdgeUsesStructure.h" 33 33 #include "DFGGraph.h" 34 #include "DFGHeapLocation.h" 35 #include "DFGPureValue.h" 34 36 35 37 namespace JSC { namespace DFG { 36 38 37 template<typename ReadFunctor, typename WriteFunctor >38 void clobberize(Graph& graph, Node* node, ReadFunctor& read, WriteFunctor& write )39 template<typename ReadFunctor, typename WriteFunctor, typename DefFunctor> 40 void clobberize(Graph& graph, Node* node, ReadFunctor& read, WriteFunctor& write, DefFunctor& def) 39 41 { 40 42 // Some notes: … … 70 72 // small hacking. 71 73 74 // While read() and write() are fairly self-explanatory - they track what sorts of things the 75 // node may read or write - the def() functor is more tricky. It tells you the heap locations 76 // (not just abstract heaps) that are defined by a node. A heap location comprises an abstract 77 // heap, some nodes, and a LocationKind. Briefly, a location defined by a node is a location 78 // whose value can be deduced from looking at the node itself. The locations returned must obey 79 // the following properties: 80 // 81 // - If someone wants to CSE a load from the heap, then a HeapLocation object should be 82 // sufficient to find a single matching node. 83 // 84 // - The abstract heap is the only abstract heap that could be clobbered to invalidate any such 85 // CSE attempt. I.e. if clobberize() reports that on every path between some node and a node 86 // that defines a HeapLocation that it wanted, there were no writes to any abstract heap that 87 // overlap the location's heap, then we have a sound match. Effectively, the semantics of 88 // write() and def() are intertwined such that for them to be sound they must agree on what 89 // is CSEable. 90 // 91 // read(), write(), and def() for heap locations is enough to do GCSE on effectful things. To 92 // keep things simple, this code will also def() pure things. def() must be overloaded to also 93 // accept PureValue. This way, a client of clobberize() can implement GCSE entirely using the 94 // information that clobberize() passes to write() and def(). Other clients of clobberize() can 95 // just ignore def() by using a NoOpClobberize functor. 96 72 97 if (edgesUseStructure(graph, node)) 73 98 read(JSCell_structureID); … … 77 102 case DoubleConstant: 78 103 case Int52Constant: 104 def(PureValue(node, node->constant())); 105 return; 106 79 107 case Identity: 80 108 case Phantom: 81 109 case HardPhantom: 110 case Check: 111 case ExtractOSREntryLocal: 112 return; 113 82 114 case BitAnd: 83 115 case BitOr: … … 86 118 case BitRShift: 87 119 case BitURShift: 88 case ValueToInt32:89 case ArithAdd:90 case ArithSub:91 case ArithNegate:92 case ArithMul:93 120 case ArithIMul: 94 case ArithDiv:95 case ArithMod:96 121 case ArithAbs: 97 122 case ArithMin: … … 103 128 case GetScope: 104 129 case SkipScope: 105 case CheckFunction:106 130 case StringCharCodeAt: 107 131 case StringFromCharCode: … … 113 137 case IsString: 114 138 case LogicalNot: 115 case ExtractOSREntryLocal:116 139 case CheckInBounds: 117 case ConstantStoragePointer:118 case UInt32ToNumber:119 case DoubleAsInt32:120 case Check:121 140 case DoubleRep: 122 141 case ValueRep: … … 125 144 case FiatInt52: 126 145 case MakeRope: 127 return; 128 146 case ValueToInt32: 147 def(PureValue(node)); 148 return; 149 150 case ArithAdd: 151 case ArithSub: 152 case ArithNegate: 153 case ArithMul: 154 case ArithDiv: 155 case ArithMod: 156 case DoubleAsInt32: 157 case UInt32ToNumber: 158 def(PureValue(node, node->arithMode())); 159 return; 160 161 case CheckFunction: 162 def(PureValue(CheckFunction, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->function())); 163 return; 164 165 case CheckExecutable: 166 def(PureValue(node, node->executable())); 167 return; 168 169 case ConstantStoragePointer: 170 def(PureValue(node, node->storagePointer())); 171 return; 172 129 173 case MovHint: 130 174 case ZombieHint: 131 175 case Upsilon: 132 176 case Phi: 133 case Flush:134 177 case PhantomLocal: 135 178 case SetArgument: … … 146 189 case CheckTierUpAndOSREnter: 147 190 case LoopHint: 148 case InvalidationPoint:149 191 case Breakpoint: 150 192 case ProfileWillCall: … … 155 197 return; 156 198 199 case InvalidationPoint: 200 write(SideState); 201 def(HeapLocation(InvalidationPointLoc, Watchpoint_fire), node); 202 return; 203 204 case Flush: 205 read(AbstractHeap(Variables, node->local())); 206 write(SideState); 207 return; 208 157 209 case VariableWatchpoint: 158 210 case TypedArrayWatchpoint: … … 167 219 168 220 case CreateActivation: 169 case CreateArguments:170 221 read(HeapObjectCount); 171 222 write(HeapObjectCount); … … 174 225 return; 175 226 227 case CreateArguments: 228 read(Variables); 229 read(HeapObjectCount); 230 write(HeapObjectCount); 231 write(SideState); 232 write(Watchpoint_fire); 233 return; 234 176 235 case FunctionReentryWatchpoint: 177 236 read(Watchpoint_fire); … … 186 245 187 246 case VarInjectionWatchpoint: 247 read(MiscFields); 248 def(HeapLocation(VarInjectionWatchpointLoc, MiscFields), node); 249 return; 250 188 251 case AllocationProfileWatchpoint: 252 read(MiscFields); 253 def(HeapLocation(AllocationProfileWatchpointLoc, MiscFields), node); 254 return; 255 189 256 case IsObject: 257 read(MiscFields); 258 def(HeapLocation(IsObjectLoc, MiscFields, node->child1()), node); 259 return; 260 190 261 case IsFunction: 262 read(MiscFields); 263 def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), node); 264 return; 265 191 266 case TypeOf: 192 267 read(MiscFields); 193 return; 194 268 def(HeapLocation(TypeOfLoc, MiscFields, node->child1()), node); 269 return; 270 195 271 case GetById: 196 272 case GetByIdFlush: … … 215 291 case GetGetter: 216 292 read(GetterSetter_getter); 293 def(HeapLocation(GetterLoc, GetterSetter_getter, node->child1()), node); 217 294 return; 218 295 219 296 case GetSetter: 220 297 read(GetterSetter_setter); 298 def(HeapLocation(SetterLoc, GetterSetter_setter, node->child1()), node); 221 299 return; 222 300 223 301 case GetCallee: 224 302 read(AbstractHeap(Variables, JSStack::Callee)); 303 def(HeapLocation(VariableLoc, AbstractHeap(Variables, JSStack::Callee)), node); 225 304 return; 226 305 … … 228 307 case GetArgument: 229 308 read(AbstractHeap(Variables, node->local())); 309 def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->local())), node); 230 310 return; 231 311 232 312 case SetLocal: 233 313 write(AbstractHeap(Variables, node->local())); 314 def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->local())), node->child1().node()); 234 315 return; 235 316 236 317 case GetLocalUnlinked: 237 318 read(AbstractHeap(Variables, node->unlinkedLocal())); 319 def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->unlinkedLocal())), node); 238 320 return; 239 321 … … 265 347 } 266 348 // This appears to read nothing because it's only reading immutable data. 349 def(PureValue(node, mode.asWord())); 267 350 return; 268 351 … … 270 353 read(Arguments_registers); 271 354 read(Variables); 355 def(HeapLocation(IndexedPropertyLoc, Variables, node->child1(), node->child2()), node); 272 356 return; 273 357 … … 275 359 if (mode.isInBounds()) { 276 360 read(Butterfly_publicLength); 277 read(Butterfly_vectorLength);278 361 read(IndexedInt32Properties); 362 def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), node); 279 363 return; 280 364 } … … 286 370 if (mode.isInBounds()) { 287 371 read(Butterfly_publicLength); 288 read(Butterfly_vectorLength);289 372 read(IndexedDoubleProperties); 373 def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), node); 290 374 return; 291 375 } … … 297 381 if (mode.isInBounds()) { 298 382 read(Butterfly_publicLength); 299 read(Butterfly_vectorLength);300 383 read(IndexedContiguousProperties); 384 def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), node); 301 385 return; 302 386 } … … 307 391 case Array::ArrayStorage: 308 392 case Array::SlowPutArrayStorage: 309 // Give up on life for now. 393 if (mode.isInBounds()) { 394 read(Butterfly_vectorLength); 395 read(IndexedArrayStorageProperties); 396 return; 397 } 310 398 read(World); 311 399 write(World); … … 322 410 case Array::Float64Array: 323 411 read(TypedArrayProperties); 324 read( JSArrayBufferView_vector);325 read(JSArrayBufferView_length);412 read(MiscFields); 413 def(HeapLocation(IndexedPropertyLoc, TypedArrayProperties, node->child1(), node->child2()), node); 326 414 return; 327 415 } … … 334 422 case PutByValAlias: { 335 423 ArrayMode mode = node->arrayMode(); 424 Node* base = graph.varArgChild(node, 0).node(); 425 Node* index = graph.varArgChild(node, 1).node(); 426 Node* value = graph.varArgChild(node, 2).node(); 336 427 switch (mode.modeForPut().type()) { 337 428 case Array::SelectUsingPredictions: … … 355 446 case Array::Arguments: 356 447 read(Arguments_registers); 357 read(Arguments_numArguments); 358 read(Arguments_slowArguments); 448 read(MiscFields); 359 449 write(Variables); 450 def(HeapLocation(IndexedPropertyLoc, Variables, base, index), value); 360 451 return; 361 452 … … 370 461 read(IndexedInt32Properties); 371 462 write(IndexedInt32Properties); 463 if (node->arrayMode().mayStoreToHole()) 464 write(Butterfly_publicLength); 465 def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, base, index), value); 372 466 return; 373 467 … … 382 476 read(IndexedDoubleProperties); 383 477 write(IndexedDoubleProperties); 478 if (node->arrayMode().mayStoreToHole()) 479 write(Butterfly_publicLength); 480 def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, base, index), value); 384 481 return; 385 482 … … 394 491 read(IndexedContiguousProperties); 395 492 write(IndexedContiguousProperties); 493 if (node->arrayMode().mayStoreToHole()) 494 write(Butterfly_publicLength); 495 def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, base, index), value); 396 496 return; 397 497 … … 412 512 case Array::Float32Array: 413 513 case Array::Float64Array: 414 read(JSArrayBufferView_vector); 415 read(JSArrayBufferView_length); 514 read(MiscFields); 416 515 write(TypedArrayProperties); 516 // FIXME: We can't def() anything here because these operations truncate their inputs. 517 // https://bugs.webkit.org/show_bug.cgi?id=134737 417 518 return; 418 519 } … … 422 523 423 524 case CheckStructure: 424 case InstanceOf:425 525 read(JSCell_structureID); 426 526 return; … … 434 534 case CheckHasInstance: 435 535 read(JSCell_typeInfoFlags); 436 return; 437 438 case CheckExecutable: 439 read(JSFunction_executable); 440 return; 441 536 def(HeapLocation(CheckHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), node); 537 return; 538 539 case InstanceOf: 540 read(JSCell_structureID); 541 def(HeapLocation(InstanceOfLoc, JSCell_structureID, node->child1(), node->child2()), node); 542 return; 543 442 544 case PutStructure: 443 545 write(JSCell_structureID); … … 449 551 case AllocatePropertyStorage: 450 552 write(JSObject_butterfly); 553 def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node); 451 554 return; 452 555 … … 454 557 read(JSObject_butterfly); 455 558 write(JSObject_butterfly); 559 def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node); 456 560 return; 457 561 458 562 case GetButterfly: 459 563 read(JSObject_butterfly); 564 def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node); 460 565 return; 461 566 … … 472 577 473 578 case GetIndexedPropertyStorage: 474 if (node->arrayMode().type() == Array::String) 475 return; 476 read(JSArrayBufferView_vector); 579 if (node->arrayMode().type() == Array::String) { 580 def(PureValue(node, node->arrayMode().asWord())); 581 return; 582 } 583 read(MiscFields); 584 def(HeapLocation(IndexedPropertyStorageLoc, MiscFields, node->child1()), node); 477 585 return; 478 586 479 587 case GetTypedArrayByteOffset: 480 read(JSArrayBufferView_vector); 481 read(JSArrayBufferView_mode); 482 read(Butterfly_arrayBuffer); 483 read(ArrayBuffer_data); 588 read(MiscFields); 589 def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), node); 484 590 return; 485 591 486 592 case GetByOffset: 487 case GetGetterSetterByOffset: 488 read(AbstractHeap(NamedProperties, graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber)); 489 return; 490 491 case MultiGetByOffset: 593 case GetGetterSetterByOffset: { 594 unsigned identifierNumber = 595 graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber; 596 AbstractHeap heap(NamedProperties, identifierNumber); 597 read(heap); 598 def(HeapLocation(NamedPropertyLoc, heap, node->child2()), node); 599 return; 600 } 601 602 case MultiGetByOffset: { 492 603 read(JSCell_structureID); 493 604 read(JSObject_butterfly); 494 read(AbstractHeap(NamedProperties, node->multiGetByOffsetData().identifierNumber)); 495 return; 496 497 case MultiPutByOffset: 605 AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber); 606 read(heap); 607 def(HeapLocation(NamedPropertyLoc, heap, node->child1()), node); 608 return; 609 } 610 611 case MultiPutByOffset: { 498 612 read(JSCell_structureID); 499 613 read(JSObject_butterfly); 500 write(AbstractHeap(NamedProperties, node->multiPutByOffsetData().identifierNumber)); 614 AbstractHeap heap(NamedProperties, node->multiPutByOffsetData().identifierNumber); 615 write(heap); 501 616 if (node->multiPutByOffsetData().writesStructures()) 502 617 write(JSCell_structureID); 503 618 if (node->multiPutByOffsetData().reallocatesStorage()) 504 619 write(JSObject_butterfly); 505 return; 506 507 case PutByOffset: 508 write(AbstractHeap(NamedProperties, graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber)); 509 return; 620 def(HeapLocation(NamedPropertyLoc, heap, node->child1()), node->child2().node()); 621 return; 622 } 623 624 case PutByOffset: { 625 unsigned identifierNumber = 626 graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber; 627 AbstractHeap heap(NamedProperties, identifierNumber); 628 write(heap); 629 def(HeapLocation(NamedPropertyLoc, heap, node->child2()), node->child3().node()); 630 return; 631 } 510 632 511 633 case GetArrayLength: { … … 518 640 case Array::SlowPutArrayStorage: 519 641 read(Butterfly_publicLength); 642 def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node->child1()), node); 520 643 return; 521 644 522 645 case Array::String: 646 def(PureValue(node, mode.asWord())); 523 647 return; 524 648 525 649 case Array::Arguments: 526 read( Arguments_overrideLength);527 read(Arguments_numArguments);650 read(MiscFields); 651 def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), node); 528 652 return; 529 653 530 654 default: 531 read(JSArrayBufferView_length); 655 ASSERT(mode.typedArrayType() != NotTypedArray); 656 read(MiscFields); 657 def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), node); 532 658 return; 533 659 } … … 535 661 536 662 case GetMyScope: 537 read(AbstractHeap(Variables, JSStack::ScopeChain)); 663 if (graph.m_codeBlock->needsActivation()) { 664 read(AbstractHeap(Variables, JSStack::ScopeChain)); 665 def(HeapLocation(VariableLoc, AbstractHeap(Variables, JSStack::ScopeChain)), node); 666 } else 667 def(PureValue(node)); 538 668 return; 539 669 540 670 case SkipTopScope: 541 671 read(AbstractHeap(Variables, graph.activationRegister())); 672 def(HeapLocation(SkipTopScopeLoc, AbstractHeap(Variables, graph.activationRegister()), node->child1()), node); 542 673 return; 543 674 544 675 case GetClosureRegisters: 545 676 read(JSVariableObject_registers); 546 return; 547 677 def(HeapLocation(ClosureRegistersLoc, JSVariableObject_registers, node->child1()), node); 678 return; 679 548 680 case GetClosureVar: 549 681 read(AbstractHeap(Variables, node->varNumber())); 682 def(HeapLocation(ClosureVariableLoc, AbstractHeap(Variables, node->varNumber()), node->child1()), node); 550 683 return; 551 684 552 685 case PutClosureVar: 553 686 write(AbstractHeap(Variables, node->varNumber())); 687 def(HeapLocation(ClosureVariableLoc, AbstractHeap(Variables, node->varNumber()), node->child2()), node->child3().node()); 554 688 return; 555 689 556 690 case GetGlobalVar: 557 691 read(AbstractHeap(Absolute, node->registerPointer())); 692 def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->registerPointer())), node); 558 693 return; 559 694 560 695 case PutGlobalVar: 561 696 write(AbstractHeap(Absolute, node->registerPointer())); 562 return;563 564 case NewObject: 697 def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->registerPointer())), node->child1().node()); 698 return; 699 565 700 case NewArray: 566 701 case NewArrayWithSize: 567 702 case NewArrayBuffer: 703 case NewTypedArray: 704 // FIXME: Enable CSE for these nodes. We can't do this right now because there is no way 705 // for us to claim an index node and a value node. We could make this work if we lowered 706 // these nodes or if we had a more flexible way of def()'ing. 707 // https://bugs.webkit.org/show_bug.cgi?id=134737 708 read(HeapObjectCount); 709 write(HeapObjectCount); 710 return; 711 712 case NewObject: 568 713 case NewRegexp: 569 714 case NewStringObject: 715 read(HeapObjectCount); 716 write(HeapObjectCount); 717 return; 718 570 719 case NewFunctionNoCheck: 571 720 case NewFunction: … … 574 723 write(HeapObjectCount); 575 724 return; 576 577 case NewTypedArray: 578 read(HeapObjectCount); 579 write(HeapObjectCount); 580 switch (node->child1().useKind()) { 581 case Int32Use: 582 return; 583 case UntypedUse: 584 read(World); 585 write(World); 586 return; 587 default: 588 RELEASE_ASSERT_NOT_REACHED(); 589 return; 590 } 591 725 592 726 case RegExpExec: 593 727 case RegExpTest: … … 602 736 return; 603 737 } 738 def(PureValue(node)); 604 739 return; 605 740 … … 609 744 case CompareGreater: 610 745 case CompareGreaterEq: 611 if (!node->isBinaryUseKind(UntypedUse)) 612 return; 746 if (!node->isBinaryUseKind(UntypedUse)) { 747 def(PureValue(node)); 748 return; 749 } 613 750 read(World); 614 751 write(World); … … 619 756 case StringObjectUse: 620 757 case StringOrStringObjectUse: 758 // These don't def a pure value, unfortunately. I'll avoid load-eliminating these for 759 // now. 621 760 return; 622 761 … … 633 772 634 773 case TearOffActivation: 774 read(Variables); 635 775 write(JSVariableObject_registers); 636 776 return; 637 777 638 778 case TearOffArguments: 779 read(Variables); 639 780 write(Arguments_registers); 640 781 return; … … 643 784 read(AbstractHeap(Variables, graph.argumentsRegisterFor(node->origin.semantic))); 644 785 read(AbstractHeap(Variables, JSStack::ArgumentCount)); 786 // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we 787 // have for PureValue. 788 // https://bugs.webkit.org/show_bug.cgi?id=134797 645 789 return; 646 790 647 791 case GetMyArgumentByVal: 648 792 read(Variables); 793 // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we 794 // have for PureValue. 795 // https://bugs.webkit.org/show_bug.cgi?id=134797 649 796 return; 650 797 … … 676 823 public: 677 824 NoOpClobberize() { } 678 void operator()(AbstractHeap) { } 825 template<typename... T> 826 void operator()(T...) { } 679 827 }; 680 828 … … 686 834 } 687 835 688 void operator()(AbstractHeap) { m_result = true; } 836 template<typename... T> 837 void operator()(T...) { m_result = true; } 689 838 690 839 bool result() const { return m_result; } … … 718 867 }; 719 868 869 bool accessesOverlap(Graph&, Node*, AbstractHeap); 720 870 bool writesOverlap(Graph&, Node*, AbstractHeap); 721 871 872 // We would have used bind() for these, but because of the overlaoding that we are doing, 873 // it's quite a bit of clearer to just write this out the traditional way. 874 875 template<typename T> 876 class ReadMethodClobberize { 877 public: 878 ReadMethodClobberize(T& value) 879 : m_value(value) 880 { 881 } 882 883 void operator()(AbstractHeap heap) 884 { 885 m_value.read(heap); 886 } 887 private: 888 T& m_value; 889 }; 890 891 template<typename T> 892 class WriteMethodClobberize { 893 public: 894 WriteMethodClobberize(T& value) 895 : m_value(value) 896 { 897 } 898 899 void operator()(AbstractHeap heap) 900 { 901 m_value.write(heap); 902 } 903 private: 904 T& m_value; 905 }; 906 907 template<typename T> 908 class DefMethodClobberize { 909 public: 910 DefMethodClobberize(T& value) 911 : m_value(value) 912 { 913 } 914 915 void operator()(PureValue value) 916 { 917 m_value.def(value); 918 } 919 920 void operator()(HeapLocation location, Node* node) 921 { 922 m_value.def(location, node); 923 } 924 925 private: 926 T& m_value; 927 }; 928 929 template<typename Adaptor> 930 void clobberize(Graph& graph, Node* node, Adaptor& adaptor) 931 { 932 ReadMethodClobberize<Adaptor> read(adaptor); 933 WriteMethodClobberize<Adaptor> write(adaptor); 934 DefMethodClobberize<Adaptor> def(adaptor); 935 clobberize(graph, node, read, write, def); 936 } 937 722 938 } } // namespace JSC::DFG 723 939 -
trunk/Source/JavaScriptCore/dfg/DFGCommonData.h
r169040 r172129 33 33 #include "InlineCallFrameSet.h" 34 34 #include "JSCell.h" 35 #include "ProfiledCodeBlockJettisoningWatchpoint.h"36 35 #include "ProfilerCompilation.h" 37 36 #include "SymbolTable.h" … … 96 95 Vector<WeakReferenceTransition> transitions; 97 96 Vector<WriteBarrier<JSCell>> weakReferences; 97 Vector<WriteBarrier<Structure>> weakStructureReferences; 98 98 SegmentedVector<CodeBlockJettisoningWatchpoint, 1, 0> watchpoints; 99 SegmentedVector<ProfiledCodeBlockJettisoningWatchpoint, 1, 0> profiledWatchpoints;100 99 Vector<JumpReplacement> jumpReplacements; 101 100 -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r171660 r172129 415 415 addBaseCheck(indexInBlock, node, baseValue, variant.structureSet()); 416 416 417 if (variant.specificValue()) { 418 m_graph.convertToConstant(node, m_graph.freeze(variant.specificValue())); 417 JSValue baseForLoad; 418 if (variant.alternateBase()) 419 baseForLoad = variant.alternateBase(); 420 else 421 baseForLoad = baseValue.m_value; 422 if (JSValue value = m_graph.tryGetConstantProperty(baseForLoad, variant.baseStructure(), variant.offset())) { 423 m_graph.convertToConstant(node, m_graph.freeze(value)); 419 424 return; 420 425 } -
trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp
r170769 r172129 108 108 if (m_graph.m_form == SSA) { 109 109 Vector<BasicBlock*> depthFirst; 110 m_graph.getBlocksIn DepthFirstOrder(depthFirst);110 m_graph.getBlocksInPreOrder(depthFirst); 111 111 for (unsigned i = 0; i < depthFirst.size(); ++i) 112 112 fixupBlock(depthFirst[i]); … … 194 194 switch (node->op()) { 195 195 case MovHint: { 196 // Check if the child is dead. MovHint's child would only be a Phantom 197 // if we had just killed it.198 if (node->child1()->op() == Phantom ) {196 // Check if the child is dead. MovHint's child would only be a Phantom or 197 // Check if we had just killed it. 198 if (node->child1()->op() == Phantom || node->child1()->op() == Check) { 199 199 node->setOpAndDefaultFlags(ZombieHint); 200 200 node->child1() = Edge(); … … 221 221 } 222 222 223 node->convertToPhantom Unchecked();223 node->convertToPhantom(); 224 224 node->children.reset(); 225 225 node->setRefCount(1); -
trunk/Source/JavaScriptCore/dfg/DFGDesiredWeakReferences.cpp
r167897 r172129 58 58 for (unsigned i = 0; i < m_references.size(); i++) { 59 59 JSCell* target = m_references[i]; 60 common->weakReferences.append(WriteBarrier<JSCell>(vm, m_codeBlock->ownerExecutable(), target)); 60 if (Structure* structure = jsDynamicCast<Structure*>(target)) { 61 common->weakStructureReferences.append( 62 WriteBarrier<Structure>(vm, m_codeBlock->ownerExecutable(), structure)); 63 } else { 64 common->weakReferences.append( 65 WriteBarrier<JSCell>(vm, m_codeBlock->ownerExecutable(), target)); 66 } 61 67 } 62 68 } -
trunk/Source/JavaScriptCore/dfg/DFGEdgeDominates.h
r164424 r172129 46 46 void operator()(Node*, Edge edge) 47 47 { 48 bool result = m_graph.m_dominators.dominates(edge.node()-> misc.owner, m_block);48 bool result = m_graph.m_dominators.dominates(edge.node()->owner, m_block); 49 49 if (verbose) { 50 50 dataLog( 51 "Checking if ", edge, " in ", *edge.node()-> misc.owner,51 "Checking if ", edge, " in ", *edge.node()->owner, 52 52 " dominates ", *m_block, ": ", result, "\n"); 53 53 } -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r171689 r172129 1297 1297 } 1298 1298 1299 bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, StringImpl* uid) 1299 bool isStringPrototypeMethodSane( 1300 JSObject* stringPrototype, Structure* stringPrototypeStructure, StringImpl* uid) 1300 1301 { 1301 1302 unsigned attributesUnused; 1302 JSCell* specificValue; 1303 PropertyOffset offset = stringPrototypeStructure->getConcurrently( 1304 vm(), uid, attributesUnused, specificValue); 1303 PropertyOffset offset = 1304 stringPrototypeStructure->getConcurrently(vm(), uid, attributesUnused); 1305 1305 if (!isValidOffset(offset)) 1306 1306 return false; 1307 1307 1308 if (!specificValue) 1308 JSValue value = m_graph.tryGetConstantProperty( 1309 stringPrototype, stringPrototypeStructure, offset); 1310 if (!value) 1309 1311 return false; 1310 1312 1311 if (!specificValue->inherits(JSFunction::info())) 1313 JSFunction* function = jsDynamicCast<JSFunction*>(value); 1314 if (!function) 1312 1315 return false; 1313 1316 1314 JSFunction* function = jsCast<JSFunction*>(specificValue);1315 1317 if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic) 1316 1318 return false; … … 1341 1343 // between the two, just because that seems like it would get confusing. So we 1342 1344 // just require both methods to be sane. 1343 if (!isStringPrototypeMethodSane(stringPrototype Structure, vm().propertyNames->valueOf.impl()))1345 if (!isStringPrototypeMethodSane(stringPrototypeObject, stringPrototypeStructure, vm().propertyNames->valueOf.impl())) 1344 1346 return false; 1345 if (!isStringPrototypeMethodSane(stringPrototype Structure, vm().propertyNames->toString.impl()))1347 if (!isStringPrototypeMethodSane(stringPrototypeObject, stringPrototypeStructure, vm().propertyNames->toString.impl())) 1346 1348 return false; 1347 1349 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r171660 r172129 640 640 } 641 641 642 void Graph::addForDepthFirstSort(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, HashSet<BasicBlock*>& seen, BasicBlock* block) 643 { 644 if (seen.contains(block)) 642 // Utilities for pre- and post-order traversals. 643 namespace { 644 645 inline void addForPreOrder(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, BitVector& seen, BasicBlock* block) 646 { 647 if (seen.get(block->index)) 645 648 return; 646 649 647 650 result.append(block); 648 651 worklist.append(block); 649 seen.add(block); 650 } 651 652 void Graph::getBlocksInDepthFirstOrder(Vector<BasicBlock*>& result) 652 seen.set(block->index); 653 } 654 655 enum PostOrderTaskKind { 656 PostOrderFirstVisit, 657 PostOrderAddToResult 658 }; 659 660 struct PostOrderTask { 661 PostOrderTask(BasicBlock* block = nullptr, PostOrderTaskKind kind = PostOrderFirstVisit) 662 : m_block(block) 663 , m_kind(kind) 664 { 665 } 666 667 BasicBlock* m_block; 668 PostOrderTaskKind m_kind; 669 }; 670 671 inline void addForPostOrder(Vector<PostOrderTask, 16>& worklist, BitVector& seen, BasicBlock* block) 672 { 673 if (seen.get(block->index)) 674 return; 675 676 worklist.append(PostOrderTask(block, PostOrderFirstVisit)); 677 seen.set(block->index); 678 } 679 680 } // anonymous namespace 681 682 void Graph::getBlocksInPreOrder(Vector<BasicBlock*>& result) 653 683 { 654 684 Vector<BasicBlock*, 16> worklist; 655 HashSet<BasicBlock*>seen;656 addFor DepthFirstSort(result, worklist, seen, block(0));685 BitVector seen; 686 addForPreOrder(result, worklist, seen, block(0)); 657 687 while (!worklist.isEmpty()) { 658 688 BasicBlock* block = worklist.takeLast(); 659 689 for (unsigned i = block->numSuccessors(); i--;) 660 addForDepthFirstSort(result, worklist, seen, block->successor(i)); 690 addForPreOrder(result, worklist, seen, block->successor(i)); 691 } 692 } 693 694 void Graph::getBlocksInPostOrder(Vector<BasicBlock*>& result) 695 { 696 Vector<PostOrderTask, 16> worklist; 697 BitVector seen; 698 addForPostOrder(worklist, seen, block(0)); 699 while (!worklist.isEmpty()) { 700 PostOrderTask task = worklist.takeLast(); 701 switch (task.m_kind) { 702 case PostOrderFirstVisit: 703 worklist.append(PostOrderTask(task.m_block, PostOrderAddToResult)); 704 for (unsigned i = task.m_block->numSuccessors(); i--;) 705 addForPostOrder(worklist, seen, task.m_block->successor(i)); 706 break; 707 case PostOrderAddToResult: 708 result.append(task.m_block); 709 break; 710 } 661 711 } 662 712 } … … 669 719 continue; 670 720 for (unsigned phiIndex = block->phis.size(); phiIndex--;) 671 block->phis[phiIndex]-> misc.replacement = 0;721 block->phis[phiIndex]->replacement = 0; 672 722 for (unsigned nodeIndex = block->size(); nodeIndex--;) 673 block->at(nodeIndex)-> misc.replacement = 0;723 block->at(nodeIndex)->replacement = 0; 674 724 } 675 725 } … … 682 732 continue; 683 733 for (unsigned phiIndex = block->phis.size(); phiIndex--;) 684 block->phis[phiIndex]-> misc.owner = block;734 block->phis[phiIndex]->owner = block; 685 735 for (unsigned nodeIndex = block->size(); nodeIndex--;) 686 block->at(nodeIndex)-> misc.owner = block;736 block->at(nodeIndex)->owner = block; 687 737 } 688 738 } … … 788 838 { 789 839 return std::max(frameRegisterCount(), requiredRegisterCountForExit()); 840 } 841 842 JSValue Graph::tryGetConstantProperty( 843 JSValue base, const StructureSet& structureSet, PropertyOffset offset) 844 { 845 if (!base || !base.isObject()) 846 return JSValue(); 847 848 JSObject* object = asObject(base); 849 850 for (unsigned i = structureSet.size(); i--;) { 851 Structure* structure = structureSet[i]; 852 WatchpointSet* set = structure->propertyReplacementWatchpointSet(offset); 853 if (!set || !set->isStillValid()) 854 return JSValue(); 855 856 ASSERT(structure->isValidOffset(offset)); 857 ASSERT(!structure->isUncacheableDictionary()); 858 859 watchpoints().addLazily(set); 860 } 861 862 // What follows may require some extra thought. We need this load to load a valid JSValue. If 863 // our profiling makes sense and we're still on track to generate code that won't be 864 // invalidated, then we have nothing to worry about. We do, however, have to worry about 865 // loading - and then using - an invalid JSValue in the case that unbeknownst to us our code 866 // is doomed. 867 // 868 // One argument in favor of this code is that it should definitely work because the butterfly 869 // is always set before the structure. However, we don't currently have a fence between those 870 // stores. It's not clear if this matters, however. We don't ever shrink the property storage. 871 // So, for this to fail, you'd need an access on a constant object pointer such that the inline 872 // caches told us that the object had a structure that it did not *yet* have, and then later, 873 // the object transitioned to that structure that the inline caches had alraedy seen. And then 874 // the processor reordered the stores. Seems unlikely and difficult to test. I believe that 875 // this is worth revisiting but it isn't worth losing sleep over. Filed: 876 // https://bugs.webkit.org/show_bug.cgi?id=134641 877 // 878 // For now, we just do the minimal thing: defend against the structure right now being 879 // incompatible with the getDirect we're trying to do. The easiest way to do that is to 880 // determine if the structure belongs to the proven set. 881 882 if (!structureSet.contains(object->structure())) 883 return JSValue(); 884 885 return object->getDirect(offset); 886 } 887 888 JSValue Graph::tryGetConstantProperty(JSValue base, Structure* structure, PropertyOffset offset) 889 { 890 return tryGetConstantProperty(base, StructureSet(structure), offset); 891 } 892 893 JSValue Graph::tryGetConstantProperty( 894 JSValue base, const StructureAbstractValue& structure, PropertyOffset offset) 895 { 896 if (structure.isTop() || structure.isClobbered()) 897 return JSValue(); 898 899 return tryGetConstantProperty(base, structure.set(), offset); 900 } 901 902 JSValue Graph::tryGetConstantProperty(const AbstractValue& base, PropertyOffset offset) 903 { 904 return tryGetConstantProperty(base.m_value, base.m_structure, offset); 790 905 } 791 906 … … 901 1016 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) { 902 1017 GetByIdVariant& variant = node->multiGetByOffsetData().variants[i]; 903 visitor.appendUnbarrieredReadOnlyValue(variant.specificValue());904 1018 const StructureSet& set = variant.structureSet(); 905 1019 for (unsigned j = set.size(); j--;) -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r171660 r172129 126 126 127 127 // Check if there is any replacement. 128 Node* replacement = child-> misc.replacement;128 Node* replacement = child->replacement; 129 129 if (!replacement) 130 130 return; … … 134 134 // There is definitely a replacement. Assert that the replacement does not 135 135 // have a replacement. 136 ASSERT(!child-> misc.replacement);136 ASSERT(!child->replacement); 137 137 } 138 138 … … 676 676 void initializeNodeOwners(); 677 677 678 void getBlocksInDepthFirstOrder(Vector<BasicBlock*>& result); 678 void getBlocksInPreOrder(Vector<BasicBlock*>& result); 679 void getBlocksInPostOrder(Vector<BasicBlock*>& result); 679 680 680 681 Profiler::Compilation* compilation() { return m_plan.compilation.get(); } … … 691 692 unsigned requiredRegisterCountForExit(); 692 693 unsigned requiredRegisterCountForExecutionAndExit(); 694 695 JSValue tryGetConstantProperty(JSValue base, const StructureSet&, PropertyOffset); 696 JSValue tryGetConstantProperty(JSValue base, Structure*, PropertyOffset); 697 JSValue tryGetConstantProperty(JSValue base, const StructureAbstractValue&, PropertyOffset); 698 JSValue tryGetConstantProperty(const AbstractValue&, PropertyOffset); 693 699 694 700 JSActivation* tryGetActivation(Node*); … … 759 765 760 766 void handleSuccessor(Vector<BasicBlock*, 16>& worklist, BasicBlock*, BasicBlock* successor); 761 void addForDepthFirstSort(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, HashSet<BasicBlock*>& seen, BasicBlock*);762 767 763 768 AddSpeculationMode addImmediateShouldSpeculateInt32(Node* add, bool variableShouldSpeculateInt32, Node* immediate, RareCaseProfilingSource source) -
trunk/Source/JavaScriptCore/dfg/DFGLICMPhase.cpp
r171613 r172129 152 152 // tend to hoist dominators before dominatees. 153 153 Vector<BasicBlock*> depthFirst; 154 m_graph.getBlocksIn DepthFirstOrder(depthFirst);154 m_graph.getBlocksInPreOrder(depthFirst); 155 155 Vector<const NaturalLoop*> loopStack; 156 156 bool changed = false; … … 246 246 247 247 data.preHeader->insertBeforeLast(node); 248 node-> misc.owner = data.preHeader;248 node->owner = data.preHeader; 249 249 NodeOrigin originalOrigin = node->origin; 250 250 node->origin.forExit = data.preHeader->last()->origin.forExit; -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r171660 r172129 209 209 , m_refCount(1) 210 210 , m_prediction(SpecNone) 211 { 212 misc.replacement = 0; 211 , replacement(nullptr) 212 , owner(nullptr) 213 { 213 214 setOpAndDefaultFlags(op); 214 215 } … … 223 224 , m_opInfo(0) 224 225 , m_opInfo2(0) 225 { 226 misc.replacement = 0; 226 , replacement(nullptr) 227 , owner(nullptr) 228 { 227 229 setOpAndDefaultFlags(op); 228 230 ASSERT(!(m_flags & NodeHasVarArgs)); … … 238 240 , m_opInfo(0) 239 241 , m_opInfo2(0) 240 { 241 misc.replacement = 0; 242 , replacement(nullptr) 243 , owner(nullptr) 244 { 242 245 setOpAndDefaultFlags(op); 243 246 setResult(result); … … 254 257 , m_opInfo(imm.m_value) 255 258 , m_opInfo2(0) 256 { 257 misc.replacement = 0; 259 , replacement(nullptr) 260 , owner(nullptr) 261 { 258 262 setOpAndDefaultFlags(op); 259 263 ASSERT(!(m_flags & NodeHasVarArgs)); … … 269 273 , m_opInfo(imm.m_value) 270 274 , m_opInfo2(0) 271 { 272 misc.replacement = 0; 275 , replacement(nullptr) 276 , owner(nullptr) 277 { 273 278 setOpAndDefaultFlags(op); 274 279 setResult(result); … … 285 290 , m_opInfo(imm1.m_value) 286 291 , m_opInfo2(imm2.m_value) 287 { 288 misc.replacement = 0; 292 , replacement(nullptr) 293 , owner(nullptr) 294 { 289 295 setOpAndDefaultFlags(op); 290 296 ASSERT(!(m_flags & NodeHasVarArgs)); … … 300 306 , m_opInfo(imm1.m_value) 301 307 , m_opInfo2(imm2.m_value) 302 { 303 misc.replacement = 0; 308 , replacement(nullptr) 309 , owner(nullptr) 310 { 304 311 setOpAndDefaultFlags(op); 305 312 ASSERT(m_flags & NodeHasVarArgs); … … 367 374 setOpAndDefaultFlags(Phantom); 368 375 } 369 370 void convertToPhantomUnchecked() 371 { 372 setOpAndDefaultFlags(Phantom); 376 377 void convertToCheck() 378 { 379 setOpAndDefaultFlags(Check); 380 } 381 382 void replaceWith(Node* other) 383 { 384 convertToPhantom(); 385 replacement = other; 373 386 } 374 387 … … 437 450 m_op = ConstantStoragePointer; 438 451 m_opInfo = bitwise_cast<uintptr_t>(pointer); 452 children.reset(); 439 453 } 440 454 … … 1761 1775 1762 1776 // Miscellaneous data that is usually meaningless, but can hold some analysis results 1763 // if you ask right. For example, if you do Graph::initializeNodeOwners(), misc.owner1777 // if you ask right. For example, if you do Graph::initializeNodeOwners(), Node::owner 1764 1778 // will tell you which basic block a node belongs to. You cannot rely on this persisting 1765 1779 // across transformations unless you do the maintenance work yourself. Other phases use 1766 // misc.replacement, but they do so manually: first you do Graph::clearReplacements()1780 // Node::replacement, but they do so manually: first you do Graph::clearReplacements() 1767 1781 // and then you set, and use, replacement's yourself. 1768 1782 // … … 1770 1784 // calling some appropriate methods that initialize them the way you want. Otherwise, 1771 1785 // these fields are meaningless. 1772 union { 1773 Node* replacement; 1774 BasicBlock* owner; 1775 } misc; 1786 Node* replacement; 1787 BasicBlock* owner; 1776 1788 }; 1777 1789 -
trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
r167532 r172129 59 59 sanitizeStackForVM(vm); 60 60 61 if (bytecodeIndex) 62 codeBlock->ownerExecutable()->setDidTryToEnterInLoop(true); 63 61 64 if (codeBlock->jitType() != JITCode::DFGJIT) { 62 65 RELEASE_ASSERT(codeBlock->jitType() == JITCode::FTLJIT); -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
r171362 r172129 55 55 AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter()), 56 56 AssemblyHelpers::TrustedImm32(0)); 57 58 tooFewFails = jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(jit.codeBlock()->exitCountThresholdForReoptimization())); 57 58 // We want to figure out if there's a possibility that we're in a loop. For the outermost 59 // code block in the inline stack, we handle this appropriately by having the loop OSR trigger 60 // check the exit count of the replacement of the CodeBlock from which we are OSRing. The 61 // problem is the inlined functions, which might also have loops, but whose baseline versions 62 // don't know where to look for the exit count. Figure out if those loops are severe enough 63 // that we had tried to OSR enter. If so, then we should use the loop reoptimization trigger. 64 // Otherwise, we should use the normal reoptimization trigger. 65 66 AssemblyHelpers::JumpList loopThreshold; 67 68 for (InlineCallFrame* inlineCallFrame = exit.m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->caller.inlineCallFrame) { 69 loopThreshold.append( 70 jit.branchTest8( 71 AssemblyHelpers::NonZero, 72 AssemblyHelpers::AbsoluteAddress( 73 inlineCallFrame->executable->addressOfDidTryToEnterInLoop()))); 74 } 75 76 jit.move( 77 AssemblyHelpers::TrustedImm32(jit.codeBlock()->exitCountThresholdForReoptimization()), 78 GPRInfo::regT1); 79 80 if (!loopThreshold.empty()) { 81 AssemblyHelpers::Jump done = jit.jump(); 82 83 loopThreshold.link(&jit); 84 jit.move( 85 AssemblyHelpers::TrustedImm32( 86 jit.codeBlock()->exitCountThresholdForReoptimizationFromLoop()), 87 GPRInfo::regT1); 88 89 done.link(&jit); 90 } 91 92 tooFewFails = jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1); 59 93 60 94 reoptimizeNow.link(&jit); … … 63 97 #if !NUMBER_OF_ARGUMENT_REGISTERS 64 98 jit.poke(GPRInfo::regT0); 99 jit.poke(AssemblyHelpers::TrustedImmPtr(&exit), 1); 65 100 #else 66 101 jit.move(GPRInfo::regT0, GPRInfo::argumentGPR0); 67 ASSERT(GPRInfo::argumentGPR0 != GPRInfo::regT1);68 #endif 69 jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(triggerReoptimizationNow)), GPRInfo:: regT1);70 jit.call(GPRInfo:: regT1);102 jit.move(AssemblyHelpers::TrustedImmPtr(&exit), GPRInfo::argumentGPR1); 103 #endif 104 jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(triggerReoptimizationNow)), GPRInfo::nonArgGPR0); 105 jit.call(GPRInfo::nonArgGPR0); 71 106 AssemblyHelpers::Jump doneAdjusting = jit.jump(); 72 107 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r171096 r172129 1031 1031 JSValue value = JSValue::decode(encodedValue); 1032 1032 1033 set->notifyWrite(vm, value );1033 set->notifyWrite(vm, value, "Executed NotifyWrite"); 1034 1034 } 1035 1035 … … 1106 1106 } 1107 1107 1108 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock )1108 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit) 1109 1109 { 1110 1110 // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't … … 1130 1130 CodeBlock* optimizedCodeBlock = codeBlock->replacement(); 1131 1131 ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType())); 1132 1133 bool didTryToEnterIntoInlinedLoops = false; 1134 for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->caller.inlineCallFrame) { 1135 if (inlineCallFrame->executable->didTryToEnterInLoop()) { 1136 didTryToEnterIntoInlinedLoops = true; 1137 break; 1138 } 1139 } 1132 1140 1133 1141 // In order to trigger reoptimization, one of two things must have happened: … … 1136 1144 bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow(); 1137 1145 bool didGetStuckInLoop = 1138 codeBlock->checkIfOptimizationThresholdReached()1146 (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops) 1139 1147 && optimizedCodeBlock->shouldReoptimizeFromLoopNow(); 1140 1148 … … 1229 1237 if (Options::verboseOSR()) { 1230 1238 dataLog( 1231 *codeBlock, ": Entered trigger TierUpNow with executeCounter = ",1239 *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ", 1232 1240 jitCode->tierUpCounter, "\n"); 1233 1241 } -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r171096 r172129 32 32 #include "PutKind.h" 33 33 34 namespace JSC { 35 36 namespace DFG { 34 namespace JSC { namespace DFG { 35 36 struct OSRExitBase; 37 37 38 38 extern "C" { … … 137 137 void JIT_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void*, void*) WTF_INTERNAL; 138 138 139 void JIT_OPERATION triggerReoptimizationNow(CodeBlock* ) WTF_INTERNAL;139 void JIT_OPERATION triggerReoptimizationNow(CodeBlock*, OSRExitBase*) WTF_INTERNAL; 140 140 141 141 #if ENABLE(FTL_JIT) -
trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp
r171613 r172129 50 50 #include "DFGOSRAvailabilityAnalysisPhase.h" 51 51 #include "DFGOSREntrypointCreationPhase.h" 52 #include "DFGPhantomRemovalPhase.h" 52 53 #include "DFGPredictionInjectionPhase.h" 53 54 #include "DFGPredictionPropagationPhase.h" … … 251 252 252 253 performStrengthReduction(dfg); 253 perform CSE(dfg);254 performLocalCSE(dfg); 254 255 performArgumentsSimplification(dfg); 255 256 performCPSRethreading(dfg); … … 258 259 bool changed = false; 259 260 changed |= performCFGSimplification(dfg); 260 changed |= perform CSE(dfg);261 changed |= performLocalCSE(dfg); 261 262 262 263 if (validationEnabled()) 263 264 validate(dfg); 264 265 265 266 performCPSRethreading(dfg); 266 267 if (changed) { … … 283 284 284 285 performStoreBarrierElision(dfg); 286 performPhantomRemoval(dfg); 285 287 performCPSRethreading(dfg); 286 288 performDCE(dfg); … … 310 312 } 311 313 314 performPhantomRemoval(dfg); 312 315 performCriticalEdgeBreaking(dfg); 313 316 performLoopPreHeaderCreation(dfg); … … 315 318 performSSAConversion(dfg); 316 319 performSSALowering(dfg); 317 performCSE(dfg); 318 319 // At this point we're not allowed to do any further code motion because our reasoning 320 // about code motion assumes that it's OK to insert GC points in random places. 321 322 performStoreBarrierElision(dfg); 320 performGlobalCSE(dfg); 323 321 performLivenessAnalysis(dfg); 324 322 performCFA(dfg); … … 331 329 } 332 330 performLICM(dfg); 331 performPhantomRemoval(dfg); 333 332 performIntegerCheckCombining(dfg); 334 perform CSE(dfg);333 performGlobalCSE(dfg); 335 334 336 335 // At this point we're not allowed to do any further code motion because our reasoning … … 339 338 340 339 performStoreBarrierElision(dfg); 340 performPhantomRemoval(dfg); 341 341 performLivenessAnalysis(dfg); 342 342 performCFA(dfg); -
trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp
r168480 r172129 247 247 } 248 248 ASSERT(phi != block->variablesAtHead.operand(phi->local())); 249 phi-> misc.replacement = block->variablesAtHead.operand(phi->local());249 phi->replacement = block->variablesAtHead.operand(phi->local()); 250 250 } 251 251 } … … 262 262 if (!node) 263 263 continue; 264 while (node-> misc.replacement) {265 ASSERT(node != node-> misc.replacement);266 node = node-> misc.replacement;264 while (node->replacement) { 265 ASSERT(node != node->replacement); 266 node = node->replacement; 267 267 } 268 268 block->variablesAtHead[i] = node; … … 302 302 303 303 for (unsigned phiIndex = block->phis.size(); phiIndex--;) { 304 block->phis[phiIndex]-> misc.replacement =304 block->phis[phiIndex]->replacement = 305 305 block->variablesAtHead.operand(block->phis[phiIndex]->local()); 306 306 } 307 307 for (unsigned nodeIndex = block->size(); nodeIndex--;) 308 ASSERT(!block->at(nodeIndex)-> misc.replacement);308 ASSERT(!block->at(nodeIndex)->replacement); 309 309 310 310 for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { … … 320 320 else 321 321 node->setOpAndDefaultFlags(Check); 322 node-> misc.replacement = node->child1().node(); // Only for Upsilons.322 node->replacement = node->child1().node(); // Only for Upsilons. 323 323 break; 324 324 } … … 334 334 break; 335 335 node->convertToPhantom(); 336 node-> misc.replacement = block->variablesAtHead.operand(variable->local());336 node->replacement = block->variablesAtHead.operand(variable->local()); 337 337 break; 338 338 } … … 343 343 // This is only for Upsilons. An Upsilon will only refer to a Flush if 344 344 // there were no SetLocals or GetLocals in the block. 345 node-> misc.replacement = block->variablesAtHead.operand(node->local());345 node->replacement = block->variablesAtHead.operand(node->local()); 346 346 break; 347 347 } … … 368 368 // This is only for Upsilons. An Upsilon will only refer to a 369 369 // PhantomLocal if there were no SetLocals or GetLocals in the block. 370 node-> misc.replacement = block->variablesAtHead.operand(variable->local());370 node->replacement = block->variablesAtHead.operand(variable->local()); 371 371 break; 372 372 } … … 399 399 block->valuesAtHead.clear(); 400 400 block->valuesAtHead.clear(); 401 block->ssa = adoptPtr(new BasicBlock::SSAData(block));401 block->ssa = std::make_unique<BasicBlock::SSAData>(block); 402 402 } 403 403 -
trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
r171613 r172129 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "DFGAbstractHeap.h" 32 #include "DFGClobberize.h" 31 33 #include "DFGGraph.h" 32 34 #include "DFGInsertionSet.h" … … 217 219 } 218 220 221 case Flush: { 222 ASSERT(m_graph.m_form != SSA); 223 224 Node* setLocal = nullptr; 225 VirtualRegister local = m_node->local(); 226 227 if (m_node->variableAccessData()->isCaptured()) { 228 for (unsigned i = m_nodeIndex; i--;) { 229 Node* node = m_block->at(i); 230 bool done = false; 231 switch (node->op()) { 232 case GetLocal: 233 case Flush: 234 if (node->local() == local) 235 done = true; 236 break; 237 238 case GetLocalUnlinked: 239 if (node->unlinkedLocal() == local) 240 done = true; 241 break; 242 243 case SetLocal: { 244 if (node->local() != local) 245 break; 246 setLocal = node; 247 done = true; 248 break; 249 } 250 251 case Phantom: 252 case Check: 253 case HardPhantom: 254 case MovHint: 255 case JSConstant: 256 case DoubleConstant: 257 case Int52Constant: 258 break; 259 260 default: 261 done = true; 262 break; 263 } 264 if (done) 265 break; 266 } 267 } else { 268 for (unsigned i = m_nodeIndex; i--;) { 269 Node* node = m_block->at(i); 270 if (node->op() == SetLocal && node->local() == local) { 271 setLocal = node; 272 break; 273 } 274 if (accessesOverlap(m_graph, node, AbstractHeap(Variables, local))) 275 break; 276 } 277 } 278 279 if (!setLocal) 280 break; 281 282 m_node->convertToPhantom(); 283 Node* dataNode = setLocal->child1().node(); 284 DFG_ASSERT(m_graph, m_node, dataNode->hasResult()); 285 m_node->child1() = dataNode->defaultEdge(); 286 m_graph.dethread(); 287 m_changed = true; 288 break; 289 } 290 219 291 default: 220 292 break; -
trunk/Source/JavaScriptCore/dfg/DFGWatchableStructureWatchingPhase.cpp
r171660 r172129 87 87 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) { 88 88 GetByIdVariant& variant = node->multiGetByOffsetData().variants[i]; 89 tryWatch(m_graph.freeze(variant.specificValue())->structure());90 89 tryWatch(variant.structureSet()); 91 90 // Don't need to watch anything in the structure chain because that would -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r171660 r172129 167 167 // pipeline failed to optimize out an Identity. 168 168 break; 169 case In: 170 if (node->child2().useKind() == CellUse) 171 break; 172 return CannotCompile; 169 173 case PutByIdDirect: 170 174 case PutById: -
trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp
r171391 r172129 167 167 } 168 168 169 static void generateCheckInICFastPath( 170 State& state, CodeBlock* codeBlock, GeneratedFunction generatedFunction, 171 StackMaps::RecordMap& recordMap, CheckInDescriptor& ic, size_t sizeOfIC) 172 { 173 VM& vm = state.graph.m_vm; 174 175 StackMaps::RecordMap::iterator iter = recordMap.find(ic.stackmapID()); 176 if (iter == recordMap.end()) { 177 // It was optimized out. 178 return; 179 } 180 181 Vector<StackMaps::Record>& records = iter->value; 182 183 RELEASE_ASSERT(records.size() == ic.m_generators.size()); 184 185 for (unsigned i = records.size(); i--;) { 186 StackMaps::Record& record = records[i]; 187 auto generator = ic.m_generators[i]; 188 189 StructureStubInfo& stubInfo = *generator.m_stub; 190 auto call = generator.m_slowCall; 191 auto slowPathBegin = generator.m_beginLabel; 192 193 CCallHelpers fastPathJIT(&vm, codeBlock); 194 195 auto jump = fastPathJIT.patchableJump(); 196 auto done = fastPathJIT.label(); 197 198 char* startOfIC = 199 bitwise_cast<char*>(generatedFunction) + record.instructionOffset; 200 201 LinkBuffer fastPath(vm, fastPathJIT, startOfIC, sizeOfIC); 202 LinkBuffer& slowPath = *state.finalizer->sideCodeLinkBuffer; 203 // Note: we could handle the !isValid() case. We just don't appear to have a 204 // reason to do so, yet. 205 RELEASE_ASSERT(fastPath.isValid()); 206 207 MacroAssembler::AssemblerType_T::fillNops( 208 startOfIC + fastPath.size(), sizeOfIC - fastPath.size()); 209 210 state.finalizer->sideCodeLinkBuffer->link( 211 ic.m_slowPathDone[i], CodeLocationLabel(startOfIC + sizeOfIC)); 212 213 CodeLocationLabel slowPathBeginLoc = slowPath.locationOf(slowPathBegin); 214 fastPath.link(jump, slowPathBeginLoc); 215 216 CodeLocationCall callReturnLocation = fastPath.locationOf(call); 217 218 stubInfo.patch.deltaCallToDone = MacroAssembler::differenceBetweenCodePtr( 219 callReturnLocation, fastPath.locationOf(done)); 220 221 stubInfo.patch.deltaCallToJump = MacroAssembler::differenceBetweenCodePtr( 222 callReturnLocation, fastPath.locationOf(jump)); 223 stubInfo.callReturnLocation = callReturnLocation; 224 stubInfo.patch.deltaCallToSlowCase = MacroAssembler::differenceBetweenCodePtr( 225 callReturnLocation, slowPathBeginLoc); 226 227 } 228 } 229 230 169 231 static RegisterSet usedRegistersFor(const StackMaps::Record& record) 170 232 { … … 291 353 } 292 354 293 if (!state.getByIds.isEmpty() || !state.putByIds.isEmpty() ) {355 if (!state.getByIds.isEmpty() || !state.putByIds.isEmpty() || !state.checkIns.isEmpty()) { 294 356 CCallHelpers slowPathJIT(&vm, codeBlock); 295 357 … … 321 383 322 384 MacroAssembler::Label begin = slowPathJIT.label(); 323 385 324 386 MacroAssembler::Call call = callOperation( 325 387 state, usedRegisters, slowPathJIT, getById.codeOrigin(), &exceptionTarget, 326 388 operationGetByIdOptimize, result, gen.stubInfo(), base, getById.uid()); 327 389 328 390 gen.reportSlowPathCall(begin, call); 329 391 330 392 getById.m_slowPathDone.append(slowPathJIT.jump()); 331 393 getById.m_generators.append(gen); … … 370 432 } 371 433 } 434 435 436 for (unsigned i = state.checkIns.size(); i--;) { 437 CheckInDescriptor& checkIn = state.checkIns[i]; 438 439 if (verboseCompilationEnabled()) 440 dataLog("Handling checkIn stackmap #", checkIn.stackmapID(), "\n"); 441 442 iter = recordMap.find(checkIn.stackmapID()); 443 if (iter == recordMap.end()) { 444 // It was optimized out. 445 continue; 446 } 447 448 for (unsigned i = 0; i < iter->value.size(); ++i) { 449 StackMaps::Record& record = iter->value[i]; 450 RegisterSet usedRegisters = usedRegistersFor(record); 451 GPRReg result = record.locations[0].directGPR(); 452 GPRReg obj = record.locations[1].directGPR(); 453 StructureStubInfo* stubInfo = codeBlock->addStubInfo(); 454 stubInfo->codeOrigin = checkIn.codeOrigin(); 455 stubInfo->patch.baseGPR = static_cast<int8_t>(obj); 456 stubInfo->patch.valueGPR = static_cast<int8_t>(result); 457 stubInfo->patch.usedRegisters = usedRegisters; 458 stubInfo->patch.spillMode = NeedToSpill; 459 460 MacroAssembler::Label begin = slowPathJIT.label(); 461 462 MacroAssembler::Call slowCall = callOperation( 463 state, usedRegisters, slowPathJIT, checkIn.codeOrigin(), &exceptionTarget, 464 operationInOptimize, result, stubInfo, obj, checkIn.m_id); 465 466 checkIn.m_slowPathDone.append(slowPathJIT.jump()); 467 468 checkIn.m_generators.append(CheckInGenerator(stubInfo, slowCall, begin)); 469 } 470 } 471 372 472 373 473 exceptionTarget.link(&slowPathJIT); … … 389 489 sizeOfPutById()); 390 490 } 491 492 for (unsigned i = state.checkIns.size(); i--;) { 493 generateCheckInICFastPath( 494 state, codeBlock, generatedFunction, recordMap, state.checkIns[i], 495 sizeOfCheckIn()); 496 } 391 497 } 392 498 -
trunk/Source/JavaScriptCore/ftl/FTLForOSREntryJITCode.cpp
r155023 r172129 32 32 33 33 ForOSREntryJITCode::ForOSREntryJITCode() 34 : m_bytecodeIndex(UINT_MAX) 35 , m_entryFailureCount(0) 34 36 { 35 37 } -
trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptor.h
r163119 r172129 95 95 }; 96 96 97 struct CheckInGenerator { 98 StructureStubInfo* m_stub; 99 MacroAssembler::Call m_slowCall; 100 MacroAssembler::Label m_beginLabel; 101 102 CheckInGenerator(StructureStubInfo* stub, MacroAssembler::Call slowCall, MacroAssembler::Label beginLabel) 103 : m_stub(stub) 104 , m_slowCall(slowCall) 105 , m_beginLabel(beginLabel) 106 { 107 } 108 }; 109 110 class CheckInDescriptor : public InlineCacheDescriptor { 111 public: 112 CheckInDescriptor() { } 113 114 CheckInDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const StringImpl* id) 115 : InlineCacheDescriptor(stackmapID, codeOrigin, nullptr) 116 , m_id(id) 117 { 118 } 119 120 121 const StringImpl* m_id; 122 Vector<CheckInGenerator> m_generators; 123 }; 124 125 97 126 } } // namespace JSC::FTL 98 127 -
trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp
r166137 r172129 62 62 } 63 63 64 size_t sizeOfCheckIn() 65 { 66 #if CPU(ARM64) 67 return 4; 68 #else 69 return 5; 70 #endif 71 } 72 73 64 74 size_t sizeOfCall() 65 75 { -
trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h
r163027 r172129 34 34 size_t sizeOfPutById(); 35 35 size_t sizeOfCall(); 36 size_t sizeOfCheckIn(); 36 37 37 38 } } // namespace JSC::FTL -
trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
r171380 r172129 64 64 macro(J_JITOperation_EA, functionType(int64, intPtr, intPtr)) \ 65 65 macro(J_JITOperation_EAZ, functionType(int64, intPtr, intPtr, int32)) \ 66 macro(J_JITOperation_ECJ, functionType(int64, intPtr, intPtr, int64)) \ 66 67 macro(J_JITOperation_EDA, functionType(int64, intPtr, doubleType, intPtr)) \ 67 68 macro(J_JITOperation_EJ, functionType(int64, intPtr, int64)) \ -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r171660 r172129 145 145 146 146 Vector<BasicBlock*> depthFirst; 147 m_graph.getBlocksIn DepthFirstOrder(depthFirst);147 m_graph.getBlocksInPreOrder(depthFirst); 148 148 149 149 int maxNumberOfArguments = -1; … … 480 480 compileGetById(); 481 481 break; 482 case In: 483 compileIn(); 484 break; 485 case PutById: 482 486 case PutByIdDirect: 483 case PutById:484 487 compilePutById(); 485 488 break; … … 3281 3284 GetByIdVariant variant = data.variants[i]; 3282 3285 LValue result; 3283 if (variant.specificValue()) 3284 result = m_out.constInt64(JSValue::encode(variant.specificValue())); 3286 JSValue constantResult; 3287 if (variant.alternateBase()) { 3288 constantResult = m_graph.tryGetConstantProperty( 3289 variant.alternateBase(), variant.baseStructure(), variant.offset()); 3290 } 3291 if (constantResult) 3292 result = m_out.constInt64(JSValue::encode(constantResult)); 3285 3293 else { 3286 3294 LValue propertyBase; … … 3975 3983 } 3976 3984 3985 void compileIn() 3986 { 3987 Edge base = m_node->child2(); 3988 LValue cell = lowCell(base); 3989 speculateObject(base, cell); 3990 if (JSString* string = m_node->child1()->dynamicCastConstant<JSString*>()) { 3991 if (string->tryGetValueImpl() && string->tryGetValueImpl()->isAtomic()) { 3992 3993 const StringImpl* str = string->tryGetValueImpl(); 3994 unsigned stackmapID = m_stackmapIDs++; 3995 3996 LValue call = m_out.call( 3997 m_out.patchpointInt64Intrinsic(), 3998 m_out.constInt64(stackmapID), m_out.constInt32(sizeOfCheckIn()), 3999 constNull(m_out.ref8), m_out.constInt32(1), cell); 4000 4001 setInstructionCallingConvention(call, LLVMAnyRegCallConv); 4002 4003 m_ftlState.checkIns.append(CheckInDescriptor(stackmapID, m_node->origin.semantic, str)); 4004 setJSValue(call); 4005 return; 4006 } 4007 } 4008 4009 setJSValue(vmCall(m_out.operation(operationGenericIn), m_callFrame, cell, lowJSValue(m_node->child1()))); 4010 } 4011 3977 4012 void compileCheckHasInstance() 3978 4013 { … … 5116 5151 LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 5117 5152 { 5118 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || DFG::isCell(edge.useKind()));5153 DFG_ASSERT(m_graph, m_node, mode == ManualOperandSpeculation || DFG::isCell(edge.useKind())); 5119 5154 5120 5155 if (edge->op() == JSConstant) { -
trunk/Source/JavaScriptCore/ftl/FTLOSREntry.cpp
r168051 r172129 55 55 } 56 56 57 if (bytecodeIndex) 58 jsCast<ScriptExecutable*>(executable)->setDidTryToEnterInLoop(true); 59 57 60 if (bytecodeIndex != entryCode->bytecodeIndex()) { 58 61 if (Options::verboseOSR()) 59 dataLog(" OSR failed because we don't have an entrypoint for bc#", bytecodeIndex, "; ours is for bc#", entryCode->bytecodeIndex() );62 dataLog(" OSR failed because we don't have an entrypoint for bc#", bytecodeIndex, "; ours is for bc#", entryCode->bytecodeIndex(), "\n"); 60 63 return 0; 61 64 } -
trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.cpp
r166463 r172129 177 177 State& state, const RegisterSet& usedRegisters, CCallHelpers& jit, 178 178 CodeOrigin codeOrigin, MacroAssembler::JumpList* exceptionTarget, 179 J_JITOperation_ESsiCI operation, GPRReg result, StructureStubInfo* stubInfo, 180 GPRReg object, const StringImpl* uid) 181 { 182 storeCodeOrigin(state, jit, codeOrigin); 183 CallContext context(state, usedRegisters, jit, 4, result); 184 jit.setupArgumentsWithExecState( 185 CCallHelpers::TrustedImmPtr(stubInfo), object, CCallHelpers::TrustedImmPtr(uid)); 186 return context.makeCall(bitwise_cast<void*>(operation), exceptionTarget); 187 } 188 189 MacroAssembler::Call callOperation( 190 State& state, const RegisterSet& usedRegisters, CCallHelpers& jit, 191 CodeOrigin codeOrigin, MacroAssembler::JumpList* exceptionTarget, 179 192 J_JITOperation_ESsiJI operation, GPRReg result, StructureStubInfo* stubInfo, 180 193 GPRReg object, StringImpl* uid) -
trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.h
r163027 r172129 60 60 MacroAssembler::Call callOperation( 61 61 State&, const RegisterSet&, CCallHelpers&, CodeOrigin, CCallHelpers::JumpList*, 62 J_JITOperation_ESsiCI, GPRReg, StructureStubInfo*, GPRReg, 63 const StringImpl*); 64 MacroAssembler::Call callOperation( 65 State&, const RegisterSet&, CCallHelpers&, CodeOrigin, CCallHelpers::JumpList*, 62 66 J_JITOperation_ESsiJI, GPRReg result, StructureStubInfo*, GPRReg object, 63 67 StringImpl* uid); -
trunk/Source/JavaScriptCore/ftl/FTLState.h
r171391 r172129 74 74 SegmentedVector<GetByIdDescriptor> getByIds; 75 75 SegmentedVector<PutByIdDescriptor> putByIds; 76 SegmentedVector<CheckInDescriptor> checkIns; 76 77 Vector<JSCall> jsCalls; 77 78 Vector<CString> codeSectionNames; -
trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp
r171824 r172129 29 29 #if ENABLE(INSPECTOR) 30 30 31 #include "DebuggerScope.h" 31 32 #include "Error.h" 32 33 #include "JSCJSValue.h" … … 96 97 int index = exec->argument(0).asInt32(); 97 98 98 JSScope* scopeChain = impl().scopeChain(); 99 ScopeChainIterator end = scopeChain->end(); 100 101 // FIXME: We should be identifying and returning CATCH_SCOPE appropriately. 99 DebuggerScope* scopeChain = impl().scopeChain(); 100 DebuggerScope::Iterator end = scopeChain->end(); 102 101 103 102 bool foundLocalScope = false; 104 for (ScopeChainIterator iter = scopeChain->begin(); iter != end; ++iter) { 105 JSObject* scope = iter.get(); 106 if (scope->isActivationObject()) { 107 if (!foundLocalScope) { 108 // First activation object is local scope, each successive activation object is closure. 109 if (!index) 110 return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE); 111 foundLocalScope = true; 112 } else if (!index) 113 return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE); 103 for (DebuggerScope::Iterator iter = scopeChain->begin(); iter != end; ++iter) { 104 DebuggerScope* scope = iter.get(); 105 106 if (!foundLocalScope && scope->isFunctionScope()) { 107 // First function scope is the local scope, each successive one is a closure. 108 if (!index) 109 return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE); 110 foundLocalScope = true; 114 111 } 115 112 116 113 if (!index) { 117 // Last in the chain is global scope. 118 if (++iter == end) 114 if (scope->isWithScope()) 115 return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE); 116 if (scope->isGlobalScope()) { 117 ASSERT(++iter == end); 119 118 return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE); 120 return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE); 119 } 120 // FIXME: We should be identifying and returning CATCH_SCOPE appropriately. 121 ASSERT(scope->isFunctionScope()); 122 return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE); 121 123 } 122 124 … … 158 160 return jsNull(); 159 161 160 JSScope* scopeChain = impl().scopeChain();161 ScopeChainIterator iter = scopeChain->begin();162 ScopeChainIterator end = scopeChain->end();162 DebuggerScope* scopeChain = impl().scopeChain(); 163 DebuggerScope::Iterator iter = scopeChain->begin(); 164 DebuggerScope::Iterator end = scopeChain->end(); 163 165 164 166 // We must always have something in the scope chain. -
trunk/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h
r162970 r172129 1 1 /* 2 * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved.2 * Copyright (C) 2008, 2013-2014 Apple Inc. All Rights Reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 54 54 String functionName() const { return m_debuggerCallFrame->functionName(); } 55 55 JSC::DebuggerCallFrame::Type type() const { return m_debuggerCallFrame->type(); } 56 JSC:: JSScope* scopeChain() const { return m_debuggerCallFrame->scope(); }56 JSC::DebuggerScope* scopeChain() const { return m_debuggerCallFrame->scope(); } 57 57 JSC::JSGlobalObject* vmEntryGlobalObject() const { return m_debuggerCallFrame->vmEntryGlobalObject(); } 58 58 -
trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp
r167816 r172129 35 35 36 36 #include "DebuggerCallFrame.h" 37 #include "DebuggerScope.h" 37 38 #include "JSJavaScriptCallFrame.h" 38 39 #include "JSLock.h" -
trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp
r171660 r172129 192 192 } 193 193 194 void InspectorRuntimeAgent::getRuntimeTypeForVariable InTextRange(ErrorString*, const String& in_variableName, const String& in_id, int in_startLine, int in_startColumn, int in_endLine, int in_endColumn, String* out_types)194 void InspectorRuntimeAgent::getRuntimeTypeForVariableAtOffset(ErrorString*, const String& in_variableName, const String& in_id, int in_divot, String* out_types) 195 195 { 196 196 VM& vm = globalVM(); 197 String types(vm.getTypesForVariable InRange(in_startLine, in_startColumn, in_endLine, in_endColumn, in_variableName, in_id));197 String types(vm.getTypesForVariableAtOffset(in_divot, in_variableName, in_id)); 198 198 *out_types = types; 199 199 } -
trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h
r171660 r172129 67 67 virtual void releaseObjectGroup(ErrorString*, const String& objectGroup) override final; 68 68 virtual void run(ErrorString*) override; 69 virtual void getRuntimeTypeForVariable InTextRange(ErrorString*, const String& in_variableName, const String& in_id, int in_startLine, int in_startColumn, int in_endLine, int in_endColumn, String* out_types) override;69 virtual void getRuntimeTypeForVariableAtOffset(ErrorString*, const String& in_variableName, const String& in_id, int in_divot, String* out_types) override; 70 70 71 71 void setScriptDebugServer(ScriptDebugServer* scriptDebugServer) { m_scriptDebugServer = scriptDebugServer; } -
trunk/Source/JavaScriptCore/inspector/protocol/Runtime.json
r171660 r172129 199 199 }, 200 200 { 201 "name": "getRuntimeTypeForVariable InTextRange",201 "name": "getRuntimeTypeForVariableAtOffset", 202 202 "parameters": [ 203 203 { "name": "variableName", "type": "string", "description": "Variable we want type infromation for." }, 204 204 { "name": "sourceID", "type": "string", "description": "sourceID uniquely identifying a script" }, 205 { "name": "startLine", "type": "integer", "description": "start line for variable name" }, 206 { "name": "startColumn", "type": "integer", "description": "start column for variable name" }, 207 { "name": "endLine", "type": "integer", "description": "end line for variable name" }, 208 { "name": "endColumn", "type": "integer", "description": "end column for variable name" } 205 { "name": "divot", "type": "integer", "description": "character offset for assignment range" } 209 206 ], 210 207 "returns": [ -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r171213 r172129 1182 1182 BatchedTransitionOptimizer optimizer(vm, variableObject); 1183 1183 if (variableObject->next()) 1184 variableObject->globalObject()->varInjectionWatchpoint()->fireAll( );1184 variableObject->globalObject()->varInjectionWatchpoint()->fireAll("Executed eval, fired VarInjection watchpoint"); 1185 1185 1186 1186 for (unsigned i = 0; i < numVariables; ++i) { -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r171350 r172129 1695 1695 if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure(vm)->propertyAccessesAreCacheable()) { 1696 1696 if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) { 1697 ConcurrentJITLocker locker(codeBlock->m_lock); 1698 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure(vm)); 1699 pc[6].u.operand = slot.cachedOffset(); 1697 Structure* structure = scope->structure(vm); 1698 { 1699 ConcurrentJITLocker locker(codeBlock->m_lock); 1700 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), structure); 1701 pc[6].u.operand = slot.cachedOffset(); 1702 } 1703 structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset()); 1700 1704 } 1701 1705 } … … 1727 1731 return; 1728 1732 1729 // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time. 1730 if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) { 1731 if (slot.isCacheablePut() && slot.base() == scope && scope->structure()->propertyAccessesAreCacheable()) { 1732 ConcurrentJITLocker locker(codeBlock->m_lock); 1733 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure()); 1734 pc[6].u.operand = slot.cachedOffset(); 1735 } 1736 } 1733 CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, modeAndType, slot); 1737 1734 } 1738 1735 -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r171380 r172129 205 205 EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState*, StructureStubInfo*, EncodedJSValue, StringImpl*) WTF_INTERNAL; 206 206 EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, StringImpl*) WTF_INTERNAL; 207 EncodedJSValue JIT_OPERATION operationInOptimize(ExecState*, StructureStubInfo*, JSCell*, StringImpl*) ;208 EncodedJSValue JIT_OPERATION operationIn(ExecState*, StructureStubInfo*, JSCell*, StringImpl*) ;209 EncodedJSValue JIT_OPERATION operationGenericIn(ExecState*, JSCell*, EncodedJSValue) ;207 EncodedJSValue JIT_OPERATION operationInOptimize(ExecState*, StructureStubInfo*, JSCell*, StringImpl*) WTF_INTERNAL; 208 EncodedJSValue JIT_OPERATION operationIn(ExecState*, StructureStubInfo*, JSCell*, StringImpl*) WTF_INTERNAL; 209 EncodedJSValue JIT_OPERATION operationGenericIn(ExecState*, JSCell*, EncodedJSValue) WTF_INTERNAL; 210 210 void JIT_OPERATION operationPutByIdStrict(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl*) WTF_INTERNAL; 211 211 void JIT_OPERATION operationPutByIdNonStrict(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl*) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/jit/Repatch.cpp
r172120 r172129 98 98 } 99 99 100 static void repatchByIdSelfAccess(VM& vm, CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure, const Identifier& propertyName, PropertyOffset offset, 101 const FunctionPtr &slowPathFunction, bool compact) 100 static void repatchByIdSelfAccess( 101 VM& vm, CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure, 102 const Identifier& propertyName, PropertyOffset offset, const FunctionPtr &slowPathFunction, 103 bool compact) 102 104 { 103 105 if (structure->typeInfo().newImpurePropertyFiresWatchpoints()) 104 106 vm.registerWatchpointForImpureProperty(propertyName, stubInfo.addWatchpoint(codeBlock)); 105 107 106 108 RepatchBuffer repatchBuffer(codeBlock); 107 109 … … 356 358 currStructure = it->get(); 357 359 } 358 } 359 360 ASSERT(protoObject->structure() == currStructure); 361 } 362 363 currStructure->startWatchingPropertyForReplacements(*vm, offset); 360 364 GPRReg baseForAccessGPR; 361 365 if (chain) { … … 744 748 && !slot.watchpointSet() 745 749 && MacroAssembler::isCompactPtrAlignedAddressOffset(maxOffsetRelativeToPatchedStorage(slot.cachedOffset()))) { 746 repatchByIdSelfAccess(*vm, codeBlock, stubInfo, structure, propertyName, slot.cachedOffset(), operationGetByIdBuildList, true); 747 stubInfo.initGetByIdSelf(*vm, codeBlock->ownerExecutable(), structure); 748 return RetryCacheLater; 750 structure->startWatchingPropertyForReplacements(*vm, slot.cachedOffset()); 751 repatchByIdSelfAccess(*vm, codeBlock, stubInfo, structure, propertyName, slot.cachedOffset(), operationGetByIdBuildList, true); 752 stubInfo.initGetByIdSelf(*vm, codeBlock->ownerExecutable(), structure); 753 return RetryCacheLater; 749 754 } 750 755 … … 1232 1237 return GiveUpOnCache; 1233 1238 1239 structure->didCachePropertyReplacement(*vm, slot.cachedOffset()); 1234 1240 repatchByIdSelfAccess(*vm, codeBlock, stubInfo, structure, ident, slot.cachedOffset(), appropriateListBuildingPutByIdFunction(slot, putKind), false); 1235 1241 stubInfo.initPutByIdReplace(*vm, codeBlock->ownerExecutable(), structure); … … 1263 1269 *vm, codeBlock->ownerExecutable(), 1264 1270 slot.isCacheableSetter() ? PutByIdAccess::Setter : PutByIdAccess::CustomSetter, 1265 structure, prototypeChain, slot.customSetter(), stubRoutine));1271 structure, prototypeChain, count, slot.customSetter(), stubRoutine)); 1266 1272 1267 1273 RepatchBuffer repatchBuffer(codeBlock); … … 1347 1353 if (list->isFull()) 1348 1354 return GiveUpOnCache; // Will get here due to recursion. 1355 1356 structure->didCachePropertyReplacement(*vm, slot.cachedOffset()); 1349 1357 1350 1358 // We're now committed to creating the stub. Mogrify the meta-data accordingly. … … 1394 1402 *vm, codeBlock->ownerExecutable(), 1395 1403 slot.isCacheableSetter() ? PutByIdAccess::Setter : PutByIdAccess::CustomSetter, 1396 structure, prototypeChain, slot.customSetter(), stubRoutine));1404 structure, prototypeChain, count, slot.customSetter(), stubRoutine)); 1397 1405 1398 1406 RepatchBuffer repatchBuffer(codeBlock); -
trunk/Source/JavaScriptCore/jsc.cpp
r171939 r172129 180 180 static Masquerader* create(VM& vm, JSGlobalObject* globalObject) 181 181 { 182 globalObject->masqueradesAsUndefinedWatchpoint()->fireAll( );182 globalObject->masqueradesAsUndefinedWatchpoint()->fireAll("Masquerading object allocated"); 183 183 Structure* structure = createStructure(vm, globalObject, jsNull()); 184 184 Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure); -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r171867 r172129 702 702 } 703 703 } else { 704 structure->didCachePropertyReplacement(vm, slot.cachedOffset()); 704 705 pc[4].u.structure.set( 705 706 vm, codeBlock->ownerExecutable(), structure); … … 1418 1419 } 1419 1420 1420 LLINT_SLOW_PATH_DECL(slow_path_get_from_scope) 1421 { 1422 LLINT_BEGIN(); 1421 static JSValue getFromScopeCommon(ExecState* exec, Instruction* pc, VM& vm) 1422 { 1423 1423 const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand); 1424 1424 JSObject* scope = jsCast<JSObject*>(LLINT_OP(2).jsValue()); … … 1428 1428 if (!scope->getPropertySlot(exec, ident, slot)) { 1429 1429 if (modeAndType.mode() == ThrowIfNotFound) 1430 LLINT_RETURN(exec->vm().throwException(exec, createUndefinedVariableError(exec, ident)));1431 LLINT_RETURN(jsUndefined());1430 return exec->vm().throwException(exec, createUndefinedVariableError(exec, ident)); 1431 return jsUndefined(); 1432 1432 } 1433 1433 … … 1436 1436 if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) { 1437 1437 CodeBlock* codeBlock = exec->codeBlock(); 1438 ConcurrentJITLocker locker(codeBlock->m_lock); 1439 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure()); 1440 pc[6].u.operand = slot.cachedOffset(); 1438 Structure* structure = scope->structure(vm); 1439 { 1440 ConcurrentJITLocker locker(codeBlock->m_lock); 1441 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), structure); 1442 pc[6].u.operand = slot.cachedOffset(); 1443 } 1444 structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset()); 1441 1445 } 1442 1446 } 1443 1447 1444 LLINT_RETURN(slot.getValue(exec, ident)); 1445 } 1446 1447 static JSObject* putToScopeCommon(ExecState* exec, Instruction* pc, VM&) 1448 return slot.getValue(exec, ident); 1449 } 1450 1451 LLINT_SLOW_PATH_DECL(slow_path_get_from_scope) 1452 { 1453 LLINT_BEGIN(); 1454 JSValue value = getFromScopeCommon(exec, pc, vm); 1455 LLINT_RETURN(value); 1456 } 1457 1458 LLINT_SLOW_PATH_DECL(slow_path_get_from_scope_with_profile) 1459 { 1460 LLINT_BEGIN(); 1461 JSValue value = getFromScopeCommon(exec, pc, vm); 1462 TypeLocation* location = pc[8].u.location; 1463 vm.highFidelityLog()->recordTypeInformationForLocation(value, location); 1464 LLINT_RETURN(value); 1465 } 1466 1467 static JSObject* putToScopeCommon(ExecState* exec, Instruction* pc) 1448 1468 { 1449 1469 CodeBlock* codeBlock = exec->codeBlock(); … … 1458 1478 PutPropertySlot slot(scope, codeBlock->isStrictMode()); 1459 1479 scope->methodTable()->put(scope, exec, ident, value, slot); 1460 1461 // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time. 1462 if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) { 1463 if (slot.isCacheablePut() && slot.base() == scope && scope->structure()->propertyAccessesAreCacheable()) { 1464 ConcurrentJITLocker locker(codeBlock->m_lock); 1465 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure()); 1466 pc[6].u.operand = slot.cachedOffset(); 1467 } 1468 } 1480 1481 CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, modeAndType, slot); 1469 1482 1470 1483 return nullptr; … … 1474 1487 { 1475 1488 LLINT_BEGIN(); 1476 JSObject* error = putToScopeCommon(exec, pc , vm);1489 JSObject* error = putToScopeCommon(exec, pc); 1477 1490 if (error) 1478 1491 LLINT_THROW(error); … … 1484 1497 // The format of this instruction is the same as put_to_scope with a TypeLocation appended: put_to_scope_with_profile scope, id, value, ResolveModeAndType, Structure, Operand, TypeLocation* 1485 1498 LLINT_BEGIN(); 1486 JSObject* error = putToScopeCommon(exec, pc , vm);1499 JSObject* error = putToScopeCommon(exec, pc); 1487 1500 if (error) 1488 1501 LLINT_THROW(error); -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h
r171660 r172129 122 122 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_scope); 123 123 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_from_scope); 124 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_from_scope_with_profile); 124 125 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_to_scope); 125 126 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_to_scope_with_profile); -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r171660 r172129 1251 1251 callSlowPath(_llint_slow_path_put_to_scope_with_profile) 1252 1252 dispatch(8) 1253 1254 _llint_op_get_from_scope_with_profile: 1255 traceExecution() 1256 callSlowPath(_llint_slow_path_get_from_scope_with_profile) 1257 dispatch(9) -
trunk/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
r163844 r172129 31 31 #include "JSCInlines.h" 32 32 #include "ProfilerDatabase.h" 33 #include "Watchpoint.h" 33 34 #include <wtf/StringPrintStream.h> 34 35 … … 94 95 } 95 96 97 void Compilation::setJettisonReason(JettisonReason jettisonReason, const FireDetail* detail) 98 { 99 if (m_jettisonReason != NotJettisoned) 100 return; // We only care about the original jettison reason. 101 102 m_jettisonReason = jettisonReason; 103 if (detail) 104 m_additionalJettisonReason = toCString(*detail); 105 else 106 m_additionalJettisonReason = CString(); 107 } 108 96 109 JSValue Compilation::toJS(ExecState* exec) const 97 110 { … … 134 147 result->putDirect(exec->vm(), exec->propertyNames().numInlinedCalls, jsNumber(m_numInlinedCalls)); 135 148 result->putDirect(exec->vm(), exec->propertyNames().jettisonReason, jsString(exec, String::fromUTF8(toCString(m_jettisonReason)))); 149 if (!m_additionalJettisonReason.isNull()) 150 result->putDirect(exec->vm(), exec->propertyNames().additionalJettisonReason, jsString(exec, String::fromUTF8(m_additionalJettisonReason))); 136 151 137 152 return result; -
trunk/Source/JavaScriptCore/profiler/ProfilerCompilation.h
r163254 r172129 40 40 #include <wtf/SegmentedVector.h> 41 41 42 namespace JSC { namespace Profiler { 42 namespace JSC { 43 44 class FireDetail; 45 46 namespace Profiler { 43 47 44 48 class Bytecodes; … … 70 74 OSRExit* addOSRExit(unsigned id, const OriginStack&, ExitKind, bool isWatchpoint); 71 75 72 void setJettisonReason(JettisonReason jettisonReason) 73 { 74 m_jettisonReason = jettisonReason; 75 } 76 void setJettisonReason(JettisonReason, const FireDetail*); 76 77 77 78 JSValue toJS(ExecState*) const; … … 81 82 CompilationKind m_kind; 82 83 JettisonReason m_jettisonReason; 84 CString m_additionalJettisonReason; 83 85 Vector<ProfiledBytecodes> m_profiledBytecodes; 84 86 Vector<CompiledBytecode> m_descriptions; -
trunk/Source/JavaScriptCore/runtime/ArrayBuffer.cpp
r163844 r172129 58 58 view->neuter(); 59 59 else if (ArrayBufferNeuteringWatchpoint* watchpoint = jsDynamicCast<ArrayBufferNeuteringWatchpoint*>(cell)) 60 watchpoint-> set()->fireAll();60 watchpoint->fireAll(); 61 61 } 62 62 return true; -
trunk/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.cpp
r171824 r172129 61 61 } 62 62 63 void ArrayBufferNeuteringWatchpoint::fireAll() 64 { 65 set()->fireAll("Array buffer was neutered"); 66 } 67 63 68 } // namespace JSC 64 69 -
trunk/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.h
r160150 r172129 51 51 52 52 WatchpointSet* set() { return m_set.get(); } 53 54 void fireAll(); 53 55 54 56 private: -
trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h
r171355 r172129 63 63 macro(__lookupSetter__) \ 64 64 macro(add) \ 65 macro(additionalJettisonReason) \ 65 66 macro(anonymous) \ 66 67 macro(arguments) \ -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r171660 r172129 206 206 { 207 207 BEGIN(); 208 exec->codeBlock()->symbolTable()->m_functionEnteredOnce.touch( );208 exec->codeBlock()->symbolTable()->m_functionEnteredOnce.touch("Function (re)entered"); 209 209 END(); 210 210 } … … 267 267 JSValue value = OP_C(2).jsValue(); 268 268 if (VariableWatchpointSet* set = pc[3].u.watchpointSet) 269 set->notifyWrite(vm, value );269 set->notifyWrite(vm, value, "Executed op_captured_mov"); 270 270 RETURN(value); 271 271 } … … 278 278 JSValue value = JSFunction::create(vm, codeBlock->functionDecl(pc[2].u.operand), exec->scope()); 279 279 if (VariableWatchpointSet* set = pc[3].u.watchpointSet) 280 set->notifyWrite(vm, value );280 set->notifyWrite(vm, value, "Executed op_new_captured_func"); 281 281 RETURN(value); 282 282 } -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h
r170147 r172129 90 90 return false; 91 91 return baseObj->hasProperty(exec, property); 92 } 93 94 inline void tryCachePutToScopeGlobal( 95 ExecState* exec, CodeBlock* codeBlock, Instruction* pc, JSObject* scope, 96 ResolveModeAndType modeAndType, PutPropertySlot& slot) 97 { 98 // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time. 99 100 if (modeAndType.type() != GlobalProperty && modeAndType.type() != GlobalPropertyWithVarInjectionChecks) 101 return; 102 103 if (!slot.isCacheablePut() 104 || slot.base() != scope 105 || !scope->structure()->propertyAccessesAreCacheable()) 106 return; 107 108 if (slot.type() == PutPropertySlot::NewProperty) { 109 // Don't cache if we've done a transition. We want to detect the first replace so that we 110 // can invalidate the watchpoint. 111 return; 112 } 113 114 scope->structure()->didCachePropertyReplacement(exec->vm(), slot.cachedOffset()); 115 116 ConcurrentJITLocker locker(codeBlock->m_lock); 117 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure()); 118 pc[6].u.operand = slot.cachedOffset(); 92 119 } 93 120 -
trunk/Source/JavaScriptCore/runtime/Executable.cpp
r171939 r172129 44 44 const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, CREATE_METHOD_TABLE(ExecutableBase) }; 45 45 46 #if ENABLE(JIT)47 46 void ExecutableBase::destroy(JSCell* cell) 48 47 { 49 48 static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase(); 50 49 } 51 #endif52 50 53 51 void ExecutableBase::clearCode() … … 81 79 const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(NativeExecutable) }; 82 80 83 #if ENABLE(JIT)84 81 void NativeExecutable::destroy(JSCell* cell) 85 82 { 86 83 static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable(); 87 84 } 88 #endif89 85 90 86 #if ENABLE(DFG_JIT) … … 97 93 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(ScriptExecutable) }; 98 94 99 #if ENABLE(JIT) 95 ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext) 96 : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED) 97 , m_source(source) 98 , m_features(isInStrictContext ? StrictModeFeature : 0) 99 , m_hasCapturedVariables(false) 100 , m_neverInline(false) 101 , m_didTryToEnterInLoop(false) 102 , m_firstLine(-1) 103 , m_lastLine(-1) 104 , m_startColumn(UINT_MAX) 105 , m_endColumn(UINT_MAX) 106 { 107 } 108 100 109 void ScriptExecutable::destroy(JSCell* cell) 101 110 { 102 111 static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable(); 103 112 } 104 #endif105 113 106 114 void ScriptExecutable::installCode(CodeBlock* genericCodeBlock) … … 108 116 RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this); 109 117 RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType())); 118 119 if (Options::verboseOSR()) 120 dataLog("Installing ", *genericCodeBlock, "\n"); 110 121 111 122 VM& vm = *genericCodeBlock->vm(); … … 349 360 350 361 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext) 351 : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec , source, inStrictContext)362 : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec->vm(), source, inStrictContext) 352 363 { 353 364 } … … 361 372 362 373 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source) 363 : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec , source, false)374 : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec->vm(), source, false) 364 375 { 365 376 } -
trunk/Source/JavaScriptCore/runtime/Executable.h
r171939 r172129 1 1 /* 2 * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2009, 2010, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 87 87 typedef JSCell Base; 88 88 89 #if ENABLE(JIT)90 89 static const bool needsDestruction = true; 91 90 static const bool hasImmortalStructure = true; 92 91 static void destroy(JSCell*); 93 #endif94 92 95 93 CodeBlockHash hashFor(CodeSpecializationKind) const; … … 299 297 } 300 298 301 #if ENABLE(JIT)302 299 static void destroy(JSCell*); 303 #endif304 300 305 301 CodeBlockHash hashFor(CodeSpecializationKind) const; … … 357 353 typedef ExecutableBase Base; 358 354 359 ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext) 360 : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED) 361 , m_source(source) 362 , m_features(isInStrictContext ? StrictModeFeature : 0) 363 , m_neverInline(false) 364 , m_startColumn(UINT_MAX) 365 , m_endColumn(UINT_MAX) 366 { 367 } 368 369 ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext) 370 : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED) 371 , m_source(source) 372 , m_features(isInStrictContext ? StrictModeFeature : 0) 373 , m_neverInline(false) 374 , m_startColumn(UINT_MAX) 375 , m_endColumn(UINT_MAX) 376 { 377 } 378 379 #if ENABLE(JIT) 355 ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext); 356 380 357 static void destroy(JSCell*); 381 #endif382 358 383 359 CodeBlockHash hashFor(CodeSpecializationKind) const; … … 398 374 399 375 void setNeverInline(bool value) { m_neverInline = value; } 376 void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; } 400 377 bool neverInline() const { return m_neverInline; } 378 bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; } 401 379 bool isInliningCandidate() const { return !neverInline(); } 380 381 bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; } 402 382 403 383 void unlinkCalls(); … … 451 431 bool m_hasCapturedVariables; 452 432 bool m_neverInline; 433 bool m_didTryToEnterInLoop; 453 434 int m_firstLine; 454 435 int m_lastLine; -
trunk/Source/JavaScriptCore/runtime/GetterSetter.cpp
r171939 r172129 2 2 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2004, 2007, 2008, 2009 Apple Inc. All rights reserved.4 * Copyright (C) 2004, 2007, 2008, 2009, 2014 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 45 45 } 46 46 47 GetterSetter* GetterSetter::withGetter(VM& vm, JSObject* newGetter) 48 { 49 if (!getter()) { 50 setGetter(vm, newGetter); 51 return this; 52 } 53 54 GetterSetter* result = GetterSetter::create(vm); 55 result->setGetter(vm, newGetter); 56 result->setSetter(vm, setter()); 57 return result; 58 } 59 60 GetterSetter* GetterSetter::withSetter(VM& vm, JSObject* newSetter) 61 { 62 if (!setter()) { 63 setSetter(vm, newSetter); 64 return this; 65 } 66 67 GetterSetter* result = GetterSetter::create(vm); 68 result->setGetter(vm, getter()); 69 result->setSetter(vm, newSetter); 70 return result; 71 } 72 47 73 JSValue callGetter(ExecState* exec, JSValue base, JSValue getterSetter) 48 74 { -
trunk/Source/JavaScriptCore/runtime/GetterSetter.h
r171939 r172129 2 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2014 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 34 34 35 35 // This is an internal value object which stores getter and setter functions 36 // for a property. 36 // for a property. Instances of this class have the property that once a getter 37 // or setter is set to a non-null value, then they cannot be changed. This means 38 // that if a property holding a GetterSetter reference is constant-inferred and 39 // that constant is observed to have a non-null setter (or getter) then we can 40 // constant fold that setter (or getter). 37 41 class GetterSetter : public JSCell { 38 42 friend class JIT; … … 57 61 58 62 JSObject* getter() const { return m_getter.get(); } 59 void setGetter(VM& vm, JSObject* getter) { m_getter.setMayBeNull(vm, this, getter); } 63 64 JSObject* getterConcurrently() const 65 { 66 JSObject* result = getter(); 67 WTF::loadLoadFence(); 68 return result; 69 } 70 71 // Set the getter. It's only valid to call this if you've never set the getter on this 72 // object. 73 void setGetter(VM& vm, JSObject* getter) 74 { 75 RELEASE_ASSERT(!m_getter); 76 WTF::storeStoreFence(); 77 m_getter.setMayBeNull(vm, this, getter); 78 } 79 60 80 JSObject* setter() const { return m_setter.get(); } 61 void setSetter(VM& vm, JSObject* setter) { m_setter.setMayBeNull(vm, this, setter); } 81 82 JSObject* setterConcurrently() const 83 { 84 JSObject* result = setter(); 85 WTF::loadLoadFence(); 86 return result; 87 } 88 89 // Set the setter. It's only valid to call this if you've never set the setter on this 90 // object. 91 void setSetter(VM& vm, JSObject* setter) 92 { 93 RELEASE_ASSERT(!m_setter); 94 WTF::storeStoreFence(); 95 m_setter.setMayBeNull(vm, this, setter); 96 } 97 98 GetterSetter* withGetter(VM&, JSObject* getter); 99 GetterSetter* withSetter(VM&, JSObject* setter); 100 62 101 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 63 102 { -
trunk/Source/JavaScriptCore/runtime/HighFidelityLog.cpp
r171660 r172129 54 54 } 55 55 56 void HighFidelityLog::recordTypeInformationForLocation(JSValue v, TypeLocation* location)57 {58 ASSERT(m_logStartPtr);59 ASSERT(m_currentOffset < m_highFidelityLogSize);60 61 LogEntry* entry = m_logStartPtr + m_currentOffset;62 63 entry->location = location;64 entry->value = v;65 entry->structure = (v.isCell() ? v.asCell()->structure() : nullptr);66 67 m_currentOffset += 1;68 if (m_currentOffset == m_highFidelityLogSize)69 processHighFidelityLog(true, "Log Full");70 }71 72 56 void HighFidelityLog::processHighFidelityLog(bool asynchronously, String reason) 73 57 { … … 86 70 87 71 m_currentOffset = 0; 88 LogEntry* temp = m_logStartPtr; 89 m_logStartPtr = m_nextBuffer; 90 m_nextBuffer = temp; 72 std::swap(m_logStartPtr, m_nextBuffer); 91 73 92 74 if (asynchronously) … … 98 80 void HighFidelityLog::actuallyProcessLogThreadFunction(void* arg) 99 81 { 100 double before = currentTimeMS();82 double before = currentTimeMS(); 101 83 ThreadData* data = static_cast<ThreadData*>(arg); 102 84 LogEntry* entry = data->m_processLogPtr; 85 HashMap<StructureID, RefPtr<StructureShape>> seenShapes; 103 86 size_t processLogToOffset = data->m_proccessLogToOffset; 104 87 size_t i = 0; 105 88 while (i < processLogToOffset) { 106 Structure * structure = entry->structure ? entry->structure : nullptr;89 StructureID id = entry->structureID; 107 90 RefPtr<StructureShape> shape; 108 if (structure) 109 shape = structure->toStructureShape(); 91 if (id) { 92 auto iter = seenShapes.find(id); 93 if (iter == seenShapes.end()) { 94 shape = entry->value.asCell()->structure()->toStructureShape(); 95 seenShapes.set(id, shape); 96 } else 97 shape = iter->value; 98 } 99 110 100 if (entry->location->m_globalTypeSet) 111 entry->location->m_globalTypeSet->addTypeForValue(entry->value, shape); 112 entry->location->m_instructionTypeSet->addTypeForValue(entry->value, shape); 101 entry->location->m_globalTypeSet->addTypeForValue(entry->value, shape, id); 102 entry->location->m_instructionTypeSet->addTypeForValue(entry->value, shape, id); 103 113 104 entry++; 114 105 i++; … … 119 110 double after = currentTimeMS(); 120 111 if (verbose) 121 dataLogF(" Processing the log took: '%f' ms\n", after - before);112 dataLogF(" Processing the log took: '%f' ms\n", after - before); 122 113 } 123 114 -
trunk/Source/JavaScriptCore/runtime/HighFidelityLog.h
r171660 r172129 46 46 JSValue value; 47 47 TypeLocation* location; 48 Structure * structure;48 StructureID structureID; 49 49 }; 50 50 … … 57 57 ~HighFidelityLog(); 58 58 59 void recordTypeInformationForLocation(JSValue v, TypeLocation*); 59 ALWAYS_INLINE void recordTypeInformationForLocation(JSValue value, TypeLocation* location) 60 { 61 ASSERT(m_logStartPtr); 62 ASSERT(m_currentOffset < m_highFidelityLogSize); 63 64 LogEntry* entry = m_logStartPtr + m_currentOffset; 65 66 entry->location = location; 67 entry->value = value; 68 entry->structureID = (value.isCell() ? value.asCell()->structureID() : 0); 69 70 m_currentOffset += 1; 71 if (m_currentOffset == m_highFidelityLogSize) 72 processHighFidelityLog(true, "Log Full"); 73 } 74 60 75 void processHighFidelityLog(bool asynchronously = false, String = ""); 61 76 -
trunk/Source/JavaScriptCore/runtime/HighFidelityTypeProfiler.cpp
r171660 r172129 33 33 static const bool verbose = false; 34 34 35 String HighFidelityTypeProfiler::getTypesForVariableIn Range(unsigned startLine, unsigned startColumn, unsigned endLine , unsigned endColumn, const String& variableName, intptr_t sourceID)35 String HighFidelityTypeProfiler::getTypesForVariableInAtOffset(unsigned divot, const String& variableName, intptr_t sourceID) 36 36 { 37 String global = getGlobalTypesForVariable InRange(startLine, startColumn, endLine, endColumn, variableName, sourceID);37 String global = getGlobalTypesForVariableAtOffset(divot, variableName, sourceID); 38 38 if (!global.isEmpty()) 39 39 return global; 40 40 41 return getLocalTypesForVariable InRange(startLine, startColumn, endLine, endColumn, variableName, sourceID);41 return getLocalTypesForVariableAtOffset(divot, variableName, sourceID); 42 42 } 43 43 44 WTF::String HighFidelityTypeProfiler::getGlobalTypesForVariableInRange(unsigned startLine, unsigned, unsigned, unsigned, const WTF::String&, intptr_t sourceID)44 String HighFidelityTypeProfiler::getGlobalTypesForVariableAtOffset(unsigned divot, const String& , intptr_t sourceID) 45 45 { 46 auto iterLocationMap = m_globalLocationToGlobalIDMap.find(getLocationBasedHash(sourceID, startLine)); 47 if (iterLocationMap == m_globalLocationToGlobalIDMap.end()) 46 TypeLocation* location = findLocation(divot, sourceID); 47 if (!location) 48 return ""; 49 50 if (location->m_globalVariableID == HighFidelityNoGlobalIDExists) 48 51 return ""; 49 52 50 auto iterIDMap = m_globalIDMap.find(iterLocationMap->second); 51 if (iterIDMap == m_globalIDMap.end()) 52 return ""; 53 54 return iterIDMap->second->seenTypes(); 53 return location->m_globalTypeSet->seenTypes(); 55 54 } 56 55 57 WTF::String HighFidelityTypeProfiler::getLocalTypesForVariableInRange(unsigned startLine, unsigned , unsigned , unsigned , const WTF::String& , intptr_t sourceID)56 String HighFidelityTypeProfiler::getLocalTypesForVariableAtOffset(unsigned divot, const String& , intptr_t sourceID) 58 57 { 59 auto iter = m_globalLocationMap.find(getLocationBasedHash(sourceID, startLine)); 60 auto end = m_globalLocationMap.end(); 61 if (iter == end) 58 TypeLocation* location = findLocation(divot, sourceID); 59 if (!location) 62 60 return ""; 63 61 64 return iter->second->seenTypes();62 return location->m_instructionTypeSet->seenTypes(); 65 63 } 66 64 … … 68 66 { 69 67 if (verbose) 70 dataLogF("Registering location:: line:%u, column:%u\n", location->m_line, location->m_column);68 dataLogF("Registering location:: divotStart:%u, divotEnd:%u\n", location->m_divotStart, location->m_divotEnd); 71 69 72 LocationKey key(getLocationBasedHash(location->m_sourceID, location->m_line)); 73 74 if (location->m_globalVariableID != HighFidelityNoGlobalIDExists) { 75 // Build the mapping relationships Map1:key=>globalId, Map2:globalID=>TypeSet 76 m_globalLocationToGlobalIDMap[key] = location->m_globalVariableID; 77 m_globalIDMap[location->m_globalVariableID] = location->m_globalTypeSet; 70 if (!m_bucketMap.contains(location->m_sourceID)) { 71 Vector<TypeLocation*> bucket; 72 m_bucketMap.set(location->m_sourceID, bucket); 78 73 } 79 74 80 m_globalLocationMap[key] = location->m_instructionTypeSet; 75 Vector<TypeLocation*>& bucket = m_bucketMap.find(location->m_sourceID)->value; 76 bucket.append(location); 81 77 } 82 78 83 LocationKey HighFidelityTypeProfiler::getLocationBasedHash(intptr_t id, unsigned line)79 TypeLocation* HighFidelityTypeProfiler::findLocation(unsigned divot, intptr_t sourceID) 84 80 { 85 return LocationKey(id, line, 1); 81 ASSERT(m_bucketMap.contains(sourceID)); 82 83 Vector<TypeLocation*>& bucket = m_bucketMap.find(sourceID)->value; 84 unsigned distance = UINT_MAX; // Because assignments may be nested, make sure we find the closest enclosing assignment to this character offset. 85 TypeLocation* bestMatch = nullptr; 86 for (size_t i = 0, size = bucket.size(); i < size; i++) { 87 TypeLocation* location = bucket.at(i); 88 if (location->m_divotStart <= divot && divot <= location->m_divotEnd && location->m_divotEnd - location->m_divotStart <= distance) { 89 distance = location->m_divotEnd - location->m_divotStart; 90 bestMatch = location; 91 } 92 } 93 94 // FIXME: BestMatch should never be null. This doesn't hold currently because we ignore some Eval/With/VarInjection variable assignments. 95 return bestMatch; 86 96 } 87 97 -
trunk/Source/JavaScriptCore/runtime/HighFidelityTypeProfiler.h
r171660 r172129 32 32 #include <wtf/HashMethod.h> 33 33 #include <wtf/text/WTFString.h> 34 #include <wtf/Vector.h> 34 35 35 36 namespace JSC { … … 37 38 class TypeLocation; 38 39 39 struct LocationKey {40 41 public:42 LocationKey(intptr_t sourceID, unsigned line, unsigned column)43 : m_sourceID(sourceID)44 , m_line(line)45 , m_column(column)46 47 {48 }49 50 unsigned hash() const51 {52 return m_line + m_sourceID;53 }54 55 // FIXME: For now, this is a hack. We do the following: Map:"ID:Line" => TypeSet. Obviously, this assumes all assignments are on discrete lines, which is an incorrect assumption.56 bool operator==(const LocationKey& other) const57 {58 return m_sourceID == other.m_sourceID59 && m_line == other.m_line;60 }61 62 intptr_t m_sourceID;63 unsigned m_line;64 unsigned m_column;65 };66 67 40 class HighFidelityTypeProfiler { 68 41 69 42 public: 70 String getTypesForVariableIn Range(unsigned startLine, unsigned startColumn, unsigned endLine, unsigned endColumn, const String& variableName, intptr_t sourceID);71 String getGlobalTypesForVariable InRange(unsigned startLine, unsigned startColumn, unsigned endLine, unsigned endColumn, const String& variableName, intptr_t sourceID);72 String getLocalTypesForVariable InRange(unsigned startLine, unsigned startColumn, unsigned endLine, unsigned endColumn, const String& variableName, intptr_t sourceID);43 String getTypesForVariableInAtOffset(unsigned divot, const String& variableName, intptr_t sourceID); 44 String getGlobalTypesForVariableAtOffset(unsigned divot, const String& variableName, intptr_t sourceID); 45 String getLocalTypesForVariableAtOffset(unsigned divot, const String& variableName, intptr_t sourceID); 73 46 void insertNewLocation(TypeLocation*); 74 47 75 48 private: 76 static LocationKey getLocationBasedHash(intptr_t, unsigned);49 TypeLocation* findLocation(unsigned divot, intptr_t sourceID); 77 50 78 typedef std::unordered_map<LocationKey, RefPtr<TypeSet>, HashMethod<LocationKey>> GlobalLocationMap; 79 typedef std::unordered_map<int64_t, RefPtr<TypeSet>> GlobalIDMap; 80 typedef std::unordered_map<LocationKey, int64_t, HashMethod<LocationKey>> GlobalLocationToGlobalIDMap; 81 82 GlobalIDMap m_globalIDMap; 83 GlobalLocationMap m_globalLocationMap; 84 GlobalLocationToGlobalIDMap m_globalLocationToGlobalIDMap; 51 typedef HashMap<intptr_t, Vector<TypeLocation*>> SourceIDToLocationBucketMap; 52 SourceIDToLocationBucketMap m_bucketMap; 85 53 }; 86 54 -
trunk/Source/JavaScriptCore/runtime/Identifier.cpp
r165999 r172129 98 98 } 99 99 100 void Identifier::dump(PrintStream& out) const 101 { 102 if (impl()) 103 out.print(impl()); 104 else 105 out.print("<null identifier>"); 106 } 107 100 108 #ifndef NDEBUG 101 109 -
trunk/Source/JavaScriptCore/runtime/Identifier.h
r171483 r172129 97 97 JS_EXPORT_PRIVATE static PassRef<StringImpl> add(VM*, const char*); 98 98 JS_EXPORT_PRIVATE static PassRef<StringImpl> add(ExecState*, const char*); 99 100 void dump(PrintStream&) const; 99 101 100 102 private: -
trunk/Source/JavaScriptCore/runtime/IndexingHeader.h
r169121 r172129 1 1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without -
trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp
r171613 r172129 108 108 for (unsigned i = 0; i < m_vector.size(); ++i) { 109 109 unsigned attributes; 110 JSCell* specificValue; 111 PropertyOffset offset = m_vector[i]->getConcurrently(vm, uid, attributes, specificValue); 110 PropertyOffset offset = m_vector[i]->getConcurrently(vm, uid, attributes); 112 111 if (!isValidOffset(offset)) 113 112 continue; … … 129 128 } 130 129 return true; 130 } 131 132 bool IntendedStructureChain::takesSlowPathInDFGForImpureProperty() 133 { 134 for (size_t i = 0; i < size(); ++i) { 135 if (at(i)->takesSlowPathInDFGForImpureProperty()) 136 return true; 137 } 138 return false; 131 139 } 132 140 -
trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.h
r171613 r172129 53 53 bool isNormalized(); 54 54 55 bool takesSlowPathInDFGForImpureProperty(); 56 55 57 JSValue prototype() const { return m_prototype; } 56 58 -
trunk/Source/JavaScriptCore/runtime/JSActivation.cpp
r171939 r172129 104 104 return false; 105 105 if (VariableWatchpointSet* set = iter->value.watchpointSet()) 106 set->invalidate( ); // Don't mess around - if we had found this statically, we would have invcalidated it.106 set->invalidate(VariableWriteFireDetail(this, propertyName)); // Don't mess around - if we had found this statically, we would have invcalidated it. 107 107 reg = ®isterAt(iter->value.getIndex()); 108 108 } -
trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp
r171613 r172129 142 142 for (; ; obj = asObject(prototype)) { 143 143 unsigned attributes; 144 JSCell* specificValue; 145 PropertyOffset offset = obj->structure()->get(vm, propertyName, attributes, specificValue); 144 PropertyOffset offset = obj->structure()->get(vm, propertyName, attributes); 146 145 if (offset != invalidOffset) { 147 146 if (attributes & ReadOnly) { -
trunk/Source/JavaScriptCore/runtime/JSFunction.cpp
r171939 r172129 406 406 thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot); 407 407 thisObject->m_allocationProfile.clear(); 408 thisObject->m_allocationProfileWatchpoint.fireAll( );408 thisObject->m_allocationProfileWatchpoint.fireAll("Store to prototype property of a function"); 409 409 // Don't allow this to be cached, since a [[Put]] must clear m_allocationProfile. 410 410 PutPropertySlot dontCache(thisObject); … … 453 453 thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot); 454 454 thisObject->m_allocationProfile.clear(); 455 thisObject->m_allocationProfileWatchpoint.fireAll( );455 thisObject->m_allocationProfileWatchpoint.fireAll("Store to prototype property of a function"); 456 456 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); 457 457 } -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r171939 r172129 46 46 #include "DatePrototype.h" 47 47 #include "Debugger.h" 48 #include "DebuggerScope.h" 48 49 #include "Error.h" 49 50 #include "ErrorConstructor.h" … … 263 264 registerAt(var.registerNumber).set(exec->vm(), this, value); 264 265 if (var.set) 265 var.set->notifyWrite(vm, value );266 var.set->notifyWrite(vm, value, VariableWriteFireDetail(this, propertyName)); 266 267 } 267 268 … … 282 283 m_functionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get())); 283 284 m_boundFunctionStructure.set(vm, this, JSBoundFunction::createStructure(vm, this, m_functionPrototype.get())); 284 m_namedFunctionStructure.set(vm, this, Structure::addPropertyTransition(vm, m_functionStructure.get(), vm.propertyNames->name, DontDelete | ReadOnly | DontEnum, 0,m_functionNameOffset));285 m_namedFunctionStructure.set(vm, this, Structure::addPropertyTransition(vm, m_functionStructure.get(), vm.propertyNames->name, DontDelete | ReadOnly | DontEnum, m_functionNameOffset)); 285 286 m_internalFunctionStructure.set(vm, this, InternalFunction::createStructure(vm, this, m_functionPrototype.get())); 286 287 JSFunction* callFunction = 0; … … 321 322 m_activationStructure.set(vm, this, JSActivation::createStructure(vm, this, jsNull())); 322 323 m_strictEvalActivationStructure.set(vm, this, StrictEvalActivation::createStructure(vm, this, jsNull())); 324 m_debuggerScopeStructure.set(m_vm, this, DebuggerScope::createStructure(m_vm, this, jsNull())); 323 325 m_withScopeStructure.set(vm, this, JSWithScope::createStructure(vm, this, jsNull())); 324 326 … … 428 430 Structure* iteratorResultStructure = prototypeMap.emptyObjectStructureForPrototype(m_objectPrototype.get(), JSFinalObject::defaultInlineCapacity()); 429 431 PropertyOffset offset; 430 iteratorResultStructure = Structure::addPropertyTransition(vm, iteratorResultStructure, vm.propertyNames->done, 0, 0,offset);431 iteratorResultStructure = Structure::addPropertyTransition(vm, iteratorResultStructure, vm.propertyNames->value, 0, 0,offset);432 iteratorResultStructure = Structure::addPropertyTransition(vm, iteratorResultStructure, vm.propertyNames->done, 0, offset); 433 iteratorResultStructure = Structure::addPropertyTransition(vm, iteratorResultStructure, vm.propertyNames->value, 0, offset); 432 434 m_iteratorResultStructure.set(vm, this, iteratorResultStructure); 433 435 … … 562 564 // the assumption that it's safe to transition to a non-SlowPut array storage don't 563 565 // do so anymore. 564 m_havingABadTimeWatchpoint->fireAll( );566 m_havingABadTimeWatchpoint->fireAll("Having a bad time"); 565 567 ASSERT(isHavingABadTime()); // The watchpoint is what tells us that we're having a bad time. 566 568 … … 663 665 #endif 664 666 667 visitor.append(&thisObject->m_debuggerScopeStructure); 665 668 visitor.append(&thisObject->m_withScopeStructure); 666 669 visitor.append(&thisObject->m_strictEvalActivationStructure); -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r171939 r172129 187 187 #endif 188 188 189 WriteBarrier<Structure> m_debuggerScopeStructure; 189 190 WriteBarrier<Structure> m_withScopeStructure; 190 191 WriteBarrier<Structure> m_strictEvalActivationStructure; … … 392 393 #endif 393 394 395 Structure* debuggerScopeStructure() const { return m_debuggerScopeStructure.get(); } 394 396 Structure* withScopeStructure() const { return m_withScopeStructure.get(); } 395 397 Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); } -
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r171824 r172129 2 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.4 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2012, 2013, 2014 Apple Inc. All rights reserved. 5 5 * Copyright (C) 2007 Eric Seidel (eric@webkit.org) 6 6 * … … 56 56 // ArrayConventions.h. 57 57 static unsigned lastArraySize = 0; 58 59 JSCell* getCallableObjectSlow(JSCell* cell)60 {61 if (cell->type() == JSFunctionType)62 return cell;63 if (cell->structure()->classInfo()->isSubClassOf(InternalFunction::info()))64 return cell;65 return 0;66 }67 58 68 59 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSObject); … … 362 353 if (prototype.isNull()) { 363 354 ASSERT(!thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName)); 364 if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot , getCallableObject(value))355 if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot) 365 356 && slot.isStrictMode()) 366 357 throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError)); … … 373 364 for (obj = thisObject; ; obj = asObject(prototype)) { 374 365 unsigned attributes; 375 JSCell* specificValue; 376 PropertyOffset offset = obj->structure(vm)->get(vm, propertyName, attributes, specificValue); 366 PropertyOffset offset = obj->structure(vm)->get(vm, propertyName, attributes); 377 367 if (isValidOffset(offset)) { 378 368 if (attributes & ReadOnly) { … … 414 404 415 405 ASSERT(!thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName) || obj == thisObject); 416 if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot , getCallableObject(value)) && slot.isStrictMode())406 if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot) && slot.isStrictMode()) 417 407 throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError)); 418 408 return; … … 1236 1226 1237 1227 PutPropertySlot slot(this); 1238 putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot , getCallableObject(value));1228 putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot); 1239 1229 1240 1230 ASSERT(slot.type() == PutPropertySlot::NewProperty); … … 1249 1239 { 1250 1240 PutPropertySlot slot(this); 1251 putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot , getCallableObject(value));1241 putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot); 1252 1242 1253 1243 // putDirect will change our Structure if we add a new property. For … … 1289 1279 1290 1280 unsigned attributes; 1291 JSCell* specificValue;1292 1281 VM& vm = exec->vm(); 1293 if (isValidOffset(thisObject->structure(vm)->get(vm, propertyName, attributes , specificValue))) {1282 if (isValidOffset(thisObject->structure(vm)->get(vm, propertyName, attributes))) { 1294 1283 if (attributes & DontDelete && !vm.isInDefineOwnProperty()) 1295 1284 return false; … … 1405 1394 JSValue JSObject::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint) 1406 1395 { 1396 // Make sure that whatever default value methods there are on object's prototype chain are 1397 // being watched. 1398 object->structure()->startWatchingInternalPropertiesIfNecessaryForEntireChain(exec->vm()); 1399 1407 1400 // Must call toString first for Date objects. 1408 1401 if ((hint == PreferString) || (hint != PreferNumber && object->prototype() == exec->lexicalGlobalObject()->datePrototype())) { … … 1465 1458 return true; 1466 1459 } 1467 return false;1468 }1469 1470 bool JSObject::getPropertySpecificValue(ExecState* exec, PropertyName propertyName, JSCell*& specificValue) const1471 {1472 VM& vm = exec->vm();1473 unsigned attributes;1474 if (isValidOffset(structure(vm)->get(vm, propertyName, attributes, specificValue)))1475 return true;1476 1477 // This could be a function within the static table? - should probably1478 // also look in the hash? This currently should not be a problem, since1479 // we've currently always call 'get' first, which should have populated1480 // the normal storage.1481 1460 return false; 1482 1461 } … … 2657 2636 return false; 2658 2637 GetterSetter* getterSetter; 2638 bool getterSetterChanged = false; 2659 2639 if (accessor.isCustomGetterSetter()) 2660 2640 getterSetter = GetterSetter::create(exec->vm()); … … 2663 2643 getterSetter = asGetterSetter(accessor); 2664 2644 } 2665 if (descriptor.setterPresent()) 2666 getterSetter->setSetter(exec->vm(), descriptor.setterObject()); 2667 if (descriptor.getterPresent()) 2668 getterSetter->setGetter(exec->vm(), descriptor.getterObject()); 2669 if (current.attributesEqual(descriptor)) 2645 if (descriptor.setterPresent()) { 2646 getterSetter = getterSetter->withSetter(exec->vm(), descriptor.setterObject()); 2647 getterSetterChanged = true; 2648 } 2649 if (descriptor.getterPresent()) { 2650 getterSetter = getterSetter->withGetter(exec->vm(), descriptor.getterObject()); 2651 getterSetterChanged = true; 2652 } 2653 if (current.attributesEqual(descriptor) && !getterSetterChanged) 2670 2654 return true; 2671 2655 methodTable(exec->vm())->deleteProperty(this, exec, propertyName); -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r171824 r172129 2 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013, 2014 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 56 56 return value.asCell(); 57 57 return 0; 58 }59 60 JS_EXPORT_PRIVATE JSCell* getCallableObjectSlow(JSCell*);61 62 inline JSCell* getCallableObject(JSValue value)63 {64 if (!value.isCell())65 return 0;66 return getCallableObjectSlow(value.asCell());67 58 } 68 59 … … 494 485 JS_EXPORT_PRIVATE static JSValue toThis(JSCell*, ExecState*, ECMAMode); 495 486 496 bool getPropertySpecificValue(ExecState*, PropertyName, JSCell*& specificFunction) const;497 498 487 // This get function only looks at the property map. 499 488 JSValue getDirect(VM& vm, PropertyName propertyName) const … … 504 493 return offset != invalidOffset ? getDirect(offset) : JSValue(); 505 494 } 506 495 507 496 JSValue getDirect(VM& vm, PropertyName propertyName, unsigned& attributes) const 508 497 { 509 JSCell* specific;510 498 Structure* structure = this->structure(vm); 511 PropertyOffset offset = structure->get(vm, propertyName, attributes , specific);499 PropertyOffset offset = structure->get(vm, propertyName, attributes); 512 500 checkOffset(offset, structure->inlineCapacity()); 513 501 return offset != invalidOffset ? getDirect(offset) : JSValue(); … … 524 512 PropertyOffset getDirectOffset(VM& vm, PropertyName propertyName, unsigned& attributes) 525 513 { 526 JSCell* specific;527 514 Structure* structure = this->structure(vm); 528 PropertyOffset offset = structure->get(vm, propertyName, attributes , specific);515 PropertyOffset offset = structure->get(vm, propertyName, attributes); 529 516 checkOffset(offset, structure->inlineCapacity()); 530 517 return offset; … … 603 590 bool isActivationObject() const; 604 591 bool isErrorInstance() const; 592 bool isWithScope() const; 605 593 606 594 JS_EXPORT_PRIVATE void seal(VM&); … … 961 949 962 950 template<PutMode> 963 bool putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot& , JSCell*);951 bool putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot&); 964 952 965 953 bool inlineGetOwnPropertySlot(VM&, Structure&, PropertyName, PropertySlot&); … … 1159 1147 } 1160 1148 1149 inline bool JSObject::isWithScope() const 1150 { 1151 return type() == WithScopeType; 1152 } 1153 1161 1154 inline void JSObject::setStructureAndButterfly(VM& vm, Structure* structure, Butterfly* butterfly) 1162 1155 { … … 1219 1212 { 1220 1213 unsigned attributes; 1221 JSCell* specific; 1222 PropertyOffset offset = structure.get(vm, propertyName, attributes, specific); 1214 PropertyOffset offset = structure.get(vm, propertyName, attributes); 1223 1215 if (!isValidOffset(offset)) 1224 1216 return false; … … 1324 1316 1325 1317 template<JSObject::PutMode mode> 1326 inline bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot , JSCell* specificFunction)1318 inline bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot) 1327 1319 { 1328 1320 ASSERT(value); … … 1334 1326 if (structure->isDictionary()) { 1335 1327 unsigned currentAttributes; 1336 JSCell* currentSpecificFunction; 1337 PropertyOffset offset = structure->get(vm, propertyName, currentAttributes, currentSpecificFunction); 1328 PropertyOffset offset = structure->get(vm, propertyName, currentAttributes); 1338 1329 if (offset != invalidOffset) { 1339 // If there is currently a specific function, and there now either isn't,1340 // or the new value is different, then despecify.1341 if (currentSpecificFunction && (specificFunction != currentSpecificFunction))1342 structure->despecifyDictionaryFunction(vm, propertyName);1343 1330 if ((mode == PutModePut) && currentAttributes & ReadOnly) 1344 1331 return false; 1345 1332 1346 1333 putDirect(vm, offset, value); 1347 // At this point, the objects structure only has a specific value set if previously there 1348 // had been one set, and if the new value being specified is the same (otherwise we would 1349 // have despecified, above). So, if currentSpecificFunction is not set, or if the new 1350 // value is different (or there is no new value), then the slot now has no value - and 1351 // as such it is cachable. 1352 // If there was previously a value, and the new value is the same, then we cannot cache. 1353 if (!currentSpecificFunction || (specificFunction != currentSpecificFunction)) 1354 slot.setExistingProperty(this, offset); 1334 structure->didReplaceProperty(offset); 1335 1336 slot.setExistingProperty(this, offset); 1355 1337 return true; 1356 1338 } … … 1363 1345 if (this->structure()->putWillGrowOutOfLineStorage()) 1364 1346 newButterfly = growOutOfLineStorage(vm, this->structure()->outOfLineCapacity(), this->structure()->suggestedNewOutOfLineStorageCapacity()); 1365 offset = this->structure()->addPropertyWithoutTransition(vm, propertyName, attributes , specificFunction);1347 offset = this->structure()->addPropertyWithoutTransition(vm, propertyName, attributes); 1366 1348 setStructureAndButterfly(vm, this->structure(), newButterfly); 1367 1349 … … 1369 1351 ASSERT(this->structure()->isValidOffset(offset)); 1370 1352 putDirect(vm, offset, value); 1371 // See comment on setNewProperty call below. 1372 if (!specificFunction) 1373 slot.setNewProperty(this, offset); 1353 slot.setNewProperty(this, offset); 1374 1354 if (attributes & ReadOnly) 1375 1355 this->structure()->setContainsReadOnlyProperties(); … … 1379 1359 PropertyOffset offset; 1380 1360 size_t currentCapacity = this->structure()->outOfLineCapacity(); 1381 if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction,offset)) {1361 if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, offset)) { 1382 1362 DeferGC deferGC(vm.heap); 1383 1363 Butterfly* newButterfly = butterfly(); … … 1391 1371 setStructureAndButterfly(vm, structure, newButterfly); 1392 1372 putDirect(vm, offset, value); 1393 // This is a new property; transitions with specific values are not currently cachable, 1394 // so leave the slot in an uncachable state. 1395 if (!specificFunction) 1396 slot.setNewProperty(this, offset); 1373 slot.setNewProperty(this, offset); 1397 1374 return true; 1398 1375 } 1399 1376 1400 1377 unsigned currentAttributes; 1401 JSCell* currentSpecificFunction; 1402 offset = structure->get(vm, propertyName, currentAttributes, currentSpecificFunction); 1378 offset = structure->get(vm, propertyName, currentAttributes); 1403 1379 if (offset != invalidOffset) { 1404 1380 if ((mode == PutModePut) && currentAttributes & ReadOnly) 1405 1381 return false; 1406 1382 1407 // There are three possibilities here: 1408 // (1) There is an existing specific value set, and we're overwriting with *the same value*. 1409 // * Do nothing - no need to despecify, but that means we can't cache (a cached 1410 // put could write a different value). Leave the slot in an uncachable state. 1411 // (2) There is a specific value currently set, but we're writing a different value. 1412 // * First, we have to despecify. Having done so, this is now a regular slot 1413 // with no specific value, so go ahead & cache like normal. 1414 // (3) Normal case, there is no specific value set. 1415 // * Go ahead & cache like normal. 1416 if (currentSpecificFunction) { 1417 // case (1) Do the put, then return leaving the slot uncachable. 1418 if (specificFunction == currentSpecificFunction) { 1419 putDirect(vm, offset, value); 1420 return true; 1421 } 1422 // case (2) Despecify, fall through to (3). 1423 setStructure(vm, Structure::despecifyFunctionTransition(vm, structure, propertyName)); 1424 } 1425 1426 // case (3) set the slot, do the put, return. 1383 structure->didReplaceProperty(offset); 1427 1384 slot.setExistingProperty(this, offset); 1428 1385 putDirect(vm, offset, value); … … 1433 1390 return false; 1434 1391 1435 structure = Structure::addPropertyTransition(vm, structure, propertyName, attributes, specificFunction,offset, slot.context());1392 structure = Structure::addPropertyTransition(vm, structure, propertyName, attributes, offset, slot.context()); 1436 1393 1437 1394 validateOffset(offset); … … 1440 1397 1441 1398 putDirect(vm, offset, value); 1442 // This is a new property; transitions with specific values are not currently cachable, 1443 // so leave the slot in an uncachable state. 1444 if (!specificFunction) 1445 slot.setNewProperty(this, offset); 1399 slot.setNewProperty(this, offset); 1446 1400 if (attributes & ReadOnly) 1447 1401 structure->setContainsReadOnlyProperties(); … … 1477 1431 ASSERT(!structure()->hasCustomGetterSetterProperties()); 1478 1432 1479 return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot , getCallableObject(value));1433 return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot); 1480 1434 } 1481 1435 … … 1485 1439 ASSERT(!value.isCustomGetterSetter()); 1486 1440 PutPropertySlot slot(this); 1487 putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot , getCallableObject(value));1441 putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot); 1488 1442 } 1489 1443 … … 1492 1446 ASSERT(!value.isGetterSetter()); 1493 1447 ASSERT(!value.isCustomGetterSetter()); 1494 putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, 0, slot , getCallableObject(value));1448 putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, 0, slot); 1495 1449 } 1496 1450 … … 1503 1457 if (structure()->putWillGrowOutOfLineStorage()) 1504 1458 newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity()); 1505 PropertyOffset offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes , getCallableObject(value));1459 PropertyOffset offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes); 1506 1460 setStructureAndButterfly(vm, structure(), newButterfly); 1507 1461 putDirect(vm, offset, value); -
trunk/Source/JavaScriptCore/runtime/JSScope.cpp
r171939 r172129 97 97 return true; 98 98 } 99 100 op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), 0, 0, slot.cachedOffset()); 99 100 WatchpointState state = globalObject->structure()->ensurePropertyReplacementWatchpointSet(exec->vm(), slot.cachedOffset())->state(); 101 if (state == IsWatched && getOrPut == Put) { 102 // The field exists, but because the replacement watchpoint is still intact. This is 103 // kind of dangerous. We have two options: 104 // 1) Invalidate the watchpoint set. That would work, but it's possible that this code 105 // path never executes - in which case this would be unwise. 106 // 2) Have the invalidation happen at run-time. All we have to do is leave the code 107 // uncached. The only downside is slightly more work when this does execute. 108 // We go with option (2) here because it seems less evil. 109 op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, 0, 0, 0, 0); 110 } else 111 op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), 0, 0, slot.cachedOffset()); 101 112 return true; 102 113 } -
trunk/Source/JavaScriptCore/runtime/JSScope.h
r171939 r172129 151 151 static size_t offsetOfNext(); 152 152 153 JS_EXPORT_PRIVATEstatic JSObject* objectAtScope(JSScope*);153 static JSObject* objectAtScope(JSScope*); 154 154 155 155 static JSValue resolve(ExecState*, JSScope*, const Identifier&); -
trunk/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
r171939 r172129 36 36 37 37 namespace JSC { 38 39 class JSSymbolTableObject; 38 40 39 41 class JSSymbolTableObject : public JSScope { … … 144 146 // FIXME: It's strange that we're doing this while holding the symbol table's lock. 145 147 // https://bugs.webkit.org/show_bug.cgi?id=134601 146 set->notifyWrite(vm, value );148 set->notifyWrite(vm, value, object, propertyName); 147 149 } 148 150 reg = &object->registerAt(fastEntry.getIndex()); … … 172 174 ASSERT(!entry.isNull()); 173 175 if (VariableWatchpointSet* set = entry.watchpointSet()) 174 set->notifyWrite(vm, value );176 set->notifyWrite(vm, value, object, propertyName); 175 177 entry.setAttributes(attributes); 176 178 reg = &object->registerAt(entry.getIndex()); -
trunk/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
r171939 r172129 1 1 /* 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 83 83 PropertyOffset offset; 84 84 unsigned attributes; 85 WriteBarrier<JSCell> specificValue; 86 87 PropertyMapEntry(VM& vm, JSCell* owner, StringImpl* key, PropertyOffset offset, unsigned attributes, JSCell* specificValue) 85 86 PropertyMapEntry(StringImpl* key, PropertyOffset offset, unsigned attributes) 88 87 : key(key) 89 88 , offset(offset) 90 89 , attributes(attributes) 91 , specificValue(vm, owner, specificValue, WriteBarrier<JSCell>::MayBeNull)92 90 { 93 91 } … … 148 146 } 149 147 150 static void visitChildren(JSCell*, SlotVisitor&);151 152 148 typedef StringImpl* KeyType; 153 149 typedef PropertyMapEntry ValueType; -
trunk/Source/JavaScriptCore/runtime/PropertyName.h
r171838 r172129 109 109 return m_impl ? toUInt32FromStringImpl(m_impl) : NotAnIndex; 110 110 } 111 112 void dump(PrintStream& out) const 113 { 114 if (m_impl) 115 out.print(m_impl); 116 else 117 out.print("<null property name>"); 118 } 111 119 112 120 private: -
trunk/Source/JavaScriptCore/runtime/PropertyTable.cpp
r171939 r172129 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 83 83 84 84 iterator end = this->end(); 85 for (iterator iter = begin(); iter != end; ++iter) {85 for (iterator iter = begin(); iter != end; ++iter) 86 86 iter->key->ref(); 87 vm.heap.writeBarrier(this, iter->specificValue.get());88 }89 87 90 88 // Copy the m_deletedOffsets vector. … … 110 108 reinsert(*iter); 111 109 iter->key->ref(); 112 vm.heap.writeBarrier(this, iter->specificValue.get());113 110 } 114 111 … … 133 130 } 134 131 135 void PropertyTable::visitChildren(JSCell* cell, SlotVisitor& visitor) 136 { 137 PropertyTable* thisObject = jsCast<PropertyTable*>(cell); 138 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 132 } // namespace JSC 139 133 140 JSCell::visitChildren(thisObject, visitor);141 142 PropertyTable::iterator end = thisObject->end();143 for (PropertyTable::iterator ptr = thisObject->begin(); ptr != end; ++ptr)144 visitor.append(&ptr->specificValue);145 }146 147 } -
trunk/Source/JavaScriptCore/runtime/Structure.cpp
r171939 r172129 1 1 /* 2 * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 167 167 setHasNonEnumerableProperties(false); 168 168 setAttributesInPrevious(0); 169 setSpecificFunctionThrashCount(0);170 169 setPreventExtensions(false); 171 170 setDidTransition(false); … … 198 197 setHasNonEnumerableProperties(false); 199 198 setAttributesInPrevious(0); 200 setSpecificFunctionThrashCount(0);201 199 setPreventExtensions(false); 202 200 setDidTransition(false); … … 228 226 setHasNonEnumerableProperties(previous->hasNonEnumerableProperties()); 229 227 setAttributesInPrevious(0); 230 setSpecificFunctionThrashCount(previous->specificFunctionThrashCount());231 228 setPreventExtensions(previous->preventExtensions()); 232 229 setDidTransition(true); … … 239 236 240 237 ASSERT(!previous->typeInfo().structureIsImmortal()); 241 if (previous->hasRareData() && previous->rareData()->needsCloning())242 cloneRareDataFrom(vm, previous);243 238 setPreviousID(vm, previous); 244 239 245 previous-> notifyTransitionFromThisStructure();240 previous->didTransitionFromThisStructure(); 246 241 if (previous->m_globalObject) 247 242 m_globalObject.set(vm, this, previous->m_globalObject.get()); … … 314 309 if (!structure->m_nameInPrevious) 315 310 continue; 316 PropertyMapEntry entry( vm, this, structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious(), structure->m_specificValueInPrevious.get());311 PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious()); 317 312 propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange); 318 313 } … … 321 316 } 322 317 323 void Structure::despecifyDictionaryFunction(VM& vm, PropertyName propertyName) 324 { 325 StringImpl* rep = propertyName.uid(); 326 327 DeferGC deferGC(vm.heap); 328 materializePropertyMapIfNecessary(vm, deferGC); 329 330 ASSERT(isDictionary()); 331 ASSERT(propertyTable()); 332 333 PropertyMapEntry* entry = propertyTable()->get(rep); 334 ASSERT(entry); 335 entry->specificValue.clear(); 336 } 337 338 Structure* Structure::addPropertyTransitionToExistingStructureImpl(Structure* structure, StringImpl* uid, unsigned attributes, JSCell* specificValue, PropertyOffset& offset) 318 Structure* Structure::addPropertyTransitionToExistingStructureImpl(Structure* structure, StringImpl* uid, unsigned attributes, PropertyOffset& offset) 339 319 { 340 320 ASSERT(!structure->isDictionary()); … … 342 322 343 323 if (Structure* existingTransition = structure->m_transitionTable.get(uid, attributes)) { 344 JSCell* specificValueInPrevious = existingTransition->m_specificValueInPrevious.get();345 if (specificValueInPrevious && specificValueInPrevious != specificValue)346 return 0;347 324 validateOffset(existingTransition->m_offset, existingTransition->inlineCapacity()); 348 325 offset = existingTransition->m_offset; … … 353 330 } 354 331 355 Structure* Structure::addPropertyTransitionToExistingStructure(Structure* structure, PropertyName propertyName, unsigned attributes, JSCell* specificValue,PropertyOffset& offset)332 Structure* Structure::addPropertyTransitionToExistingStructure(Structure* structure, PropertyName propertyName, unsigned attributes, PropertyOffset& offset) 356 333 { 357 334 ASSERT(!isCompilationThread()); 358 return addPropertyTransitionToExistingStructureImpl(structure, propertyName.uid(), attributes, specificValue,offset);359 } 360 361 Structure* Structure::addPropertyTransitionToExistingStructureConcurrently(Structure* structure, StringImpl* uid, unsigned attributes, JSCell* specificValue,PropertyOffset& offset)335 return addPropertyTransitionToExistingStructureImpl(structure, propertyName.uid(), attributes, offset); 336 } 337 338 Structure* Structure::addPropertyTransitionToExistingStructureConcurrently(Structure* structure, StringImpl* uid, unsigned attributes, PropertyOffset& offset) 362 339 { 363 340 ConcurrentJITLocker locker(structure->m_lock); 364 return addPropertyTransitionToExistingStructureImpl(structure, uid, attributes, specificValue,offset);341 return addPropertyTransitionToExistingStructureImpl(structure, uid, attributes, offset); 365 342 } 366 343 … … 417 394 } 418 395 419 Structure* Structure::addPropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes, JSCell* specificValue, PropertyOffset& offset, PutPropertySlot::Context context) 420 { 421 // If we have a specific function, we may have got to this point if there is 422 // already a transition with the correct property name and attributes, but 423 // specialized to a different function. In this case we just want to give up 424 // and despecialize the transition. 425 // In this case we clear the value of specificFunction which will result 426 // in us adding a non-specific transition, and any subsequent lookup in 427 // Structure::addPropertyTransitionToExistingStructure will just use that. 428 if (specificValue && structure->m_transitionTable.contains(propertyName.uid(), attributes)) 429 specificValue = 0; 430 396 Structure* Structure::addPropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes, PropertyOffset& offset, PutPropertySlot::Context context) 397 { 431 398 ASSERT(!structure->isDictionary()); 432 399 ASSERT(structure->isObject()); 433 ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset)); 434 435 if (structure->specificFunctionThrashCount() == maxSpecificFunctionThrashCount) 436 specificValue = 0; 437 400 ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, offset)); 401 438 402 int maxTransitionLength; 439 403 if (context == PutPropertySlot::PutById) … … 444 408 Structure* transition = toCacheableDictionaryTransition(vm, structure); 445 409 ASSERT(structure != transition); 446 offset = transition-> putSpecificValue(vm, propertyName, attributes, specificValue);410 offset = transition->add(vm, propertyName, attributes); 447 411 return transition; 448 412 } … … 453 417 transition->m_nameInPrevious = propertyName.uid(); 454 418 transition->setAttributesInPrevious(attributes); 455 transition->m_specificValueInPrevious.setMayBeNull(vm, transition, specificValue);456 419 transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm)); 457 420 transition->m_offset = structure->m_offset; 458 421 459 offset = transition-> putSpecificValue(vm, propertyName, attributes, specificValue);422 offset = transition->add(vm, propertyName, attributes); 460 423 461 424 checkOffset(transition->m_offset, transition->inlineCapacity()); … … 492 455 transition->m_offset = structure->m_offset; 493 456 transition->pin(); 494 495 transition->checkOffsetConsistency();496 return transition;497 }498 499 Structure* Structure::despecifyFunctionTransition(VM& vm, Structure* structure, PropertyName replaceFunction)500 {501 ASSERT(structure->specificFunctionThrashCount() < maxSpecificFunctionThrashCount);502 Structure* transition = create(vm, structure);503 504 transition->setSpecificFunctionThrashCount(transition->specificFunctionThrashCount() + 1);505 506 DeferGC deferGC(vm.heap);507 structure->materializePropertyMapIfNecessary(vm, deferGC);508 transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm));509 transition->m_offset = structure->m_offset;510 transition->pin();511 512 if (transition->specificFunctionThrashCount() == maxSpecificFunctionThrashCount)513 transition->despecifyAllFunctions(vm);514 else {515 bool removed = transition->despecifyFunction(vm, replaceFunction);516 ASSERT_UNUSED(removed, removed);517 }518 457 519 458 transition->checkOffsetConsistency(); … … 650 589 Structure* result = globalObject->originalArrayStructureForIndexingType(indexingType); 651 590 if (result->indexingTypeIncludingHistory() == indexingType) { 652 structure-> notifyTransitionFromThisStructure();591 structure->didTransitionFromThisStructure(); 653 592 return result; 654 593 } … … 772 711 } 773 712 774 PropertyOffset Structure::addPropertyWithoutTransition(VM& vm, PropertyName propertyName, unsigned attributes , JSCell* specificValue)713 PropertyOffset Structure::addPropertyWithoutTransition(VM& vm, PropertyName propertyName, unsigned attributes) 775 714 { 776 715 ASSERT(!enumerationCache()); 777 778 if (specificFunctionThrashCount() == maxSpecificFunctionThrashCount)779 specificValue = 0;780 716 781 717 DeferGC deferGC(vm.heap); … … 784 720 pin(); 785 721 786 return putSpecificValue(vm, propertyName, attributes, specificValue);722 return add(vm, propertyName, attributes); 787 723 } 788 724 … … 811 747 ASSERT(!hasRareData()); 812 748 StructureRareData* rareData = StructureRareData::create(vm, previous()); 749 WTF::storeStoreFence(); 813 750 m_previousOrRareData.set(vm, this, rareData); 751 WTF::storeStoreFence(); 814 752 setHasRareData(true); 815 753 ASSERT(hasRareData()); 816 754 } 817 755 818 void Structure::cloneRareDataFrom(VM& vm, const Structure* other) 819 { 820 ASSERT(!hasRareData()); 821 ASSERT(other->hasRareData()); 822 StructureRareData* newRareData = StructureRareData::clone(vm, other->rareData()); 823 m_previousOrRareData.set(vm, this, newRareData); 824 setHasRareData(true); 825 ASSERT(hasRareData()); 756 WatchpointSet* Structure::ensurePropertyReplacementWatchpointSet(VM& vm, PropertyOffset offset) 757 { 758 ASSERT(!isUncacheableDictionary()); 759 760 if (!hasRareData()) 761 allocateRareData(vm); 762 ConcurrentJITLocker locker(m_lock); 763 StructureRareData* rareData = this->rareData(); 764 if (!rareData->m_replacementWatchpointSets) { 765 rareData->m_replacementWatchpointSets = 766 std::make_unique<StructureRareData::PropertyWatchpointMap>(); 767 WTF::storeStoreFence(); 768 } 769 auto result = rareData->m_replacementWatchpointSets->add(offset, nullptr); 770 if (result.isNewEntry) 771 result.iterator->value = adoptRef(new WatchpointSet(IsWatched)); 772 return result.iterator->value.get(); 773 } 774 775 void Structure::startWatchingPropertyForReplacements(VM& vm, PropertyName propertyName) 776 { 777 ASSERT(!isUncacheableDictionary()); 778 779 PropertyOffset offset = get(vm, propertyName); 780 if (!JSC::isValidOffset(offset)) 781 return; 782 783 startWatchingPropertyForReplacements(vm, offset); 784 } 785 786 void Structure::didCachePropertyReplacement(VM& vm, PropertyOffset offset) 787 { 788 ensurePropertyReplacementWatchpointSet(vm, offset)->fireAll("Did cache property replacement"); 789 } 790 791 void Structure::startWatchingInternalProperties(VM& vm) 792 { 793 if (!isUncacheableDictionary()) { 794 startWatchingPropertyForReplacements(vm, vm.propertyNames->toString); 795 startWatchingPropertyForReplacements(vm, vm.propertyNames->valueOf); 796 } 797 setDidWatchInternalProperties(true); 826 798 } 827 799 … … 882 854 } 883 855 884 PropertyOffset Structure::getConcurrently(VM&, StringImpl* uid, unsigned& attributes , JSCell*& specificValue)856 PropertyOffset Structure::getConcurrently(VM&, StringImpl* uid, unsigned& attributes) 885 857 { 886 858 Vector<Structure*, 8> structures; … … 894 866 if (entry) { 895 867 attributes = entry->attributes; 896 specificValue = entry->specificValue.get();897 868 PropertyOffset result = entry->offset; 898 869 structure->m_lock.unlock(); … … 908 879 909 880 attributes = structure->attributesInPrevious(); 910 specificValue = structure->m_specificValueInPrevious.get();911 881 return structure->m_offset; 912 882 } … … 915 885 } 916 886 917 bool Structure::despecifyFunction(VM& vm, PropertyName propertyName) 918 { 919 DeferGC deferGC(vm.heap); 920 materializePropertyMapIfNecessary(vm, deferGC); 921 if (!propertyTable()) 922 return false; 923 924 PropertyMapEntry* entry = propertyTable()->get(propertyName.uid()); 925 if (!entry) 926 return false; 927 928 ASSERT(entry->specificValue); 929 entry->specificValue.clear(); 930 return true; 931 } 932 933 void Structure::despecifyAllFunctions(VM& vm) 934 { 935 DeferGC deferGC(vm.heap); 936 materializePropertyMapIfNecessary(vm, deferGC); 937 if (!propertyTable()) 938 return; 939 940 PropertyTable::iterator end = propertyTable()->end(); 941 for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) 942 iter->specificValue.clear(); 943 } 944 945 PropertyOffset Structure::putSpecificValue(VM& vm, PropertyName propertyName, unsigned attributes, JSCell* specificValue) 887 PropertyOffset Structure::add(VM& vm, PropertyName propertyName, unsigned attributes) 946 888 { 947 889 GCSafeConcurrentJITLocker locker(m_lock, vm.heap); … … 960 902 PropertyOffset newOffset = propertyTable()->nextOffset(m_inlineCapacity); 961 903 962 propertyTable()->add(PropertyMapEntry( vm, propertyTable().get(), rep, newOffset, attributes, specificValue), m_offset, PropertyTable::PropertyOffsetMayChange);904 propertyTable()->add(PropertyMapEntry(rep, newOffset, attributes), m_offset, PropertyTable::PropertyOffsetMayChange); 963 905 964 906 checkConsistency(); … … 1019 961 } 1020 962 963 namespace { 964 965 class StructureFireDetail : public FireDetail { 966 public: 967 StructureFireDetail(const Structure* structure) 968 : m_structure(structure) 969 { 970 } 971 972 virtual void dump(PrintStream& out) const override 973 { 974 out.print("Structure transition from ", *m_structure); 975 } 976 977 private: 978 const Structure* m_structure; 979 }; 980 981 } // anonymous namespace 982 983 void Structure::didTransitionFromThisStructure() const 984 { 985 m_transitionWatchpointSet.fireAll(StructureFireDetail(this)); 986 } 987 1021 988 JSValue Structure::prototypeForLookup(CodeBlock* codeBlock) const 1022 989 { … … 1038 1005 } 1039 1006 visitor.append(&thisObject->m_previousOrRareData); 1040 visitor.append(&thisObject->m_specificValueInPrevious);1041 1007 1042 1008 if (thisObject->isPinnedPropertyTable()) { … … 1061 1027 1062 1028 unsigned attributes; 1063 JSCell* specificValue; 1064 PropertyOffset offset = current->get(vm, propertyName, attributes, specificValue); 1029 PropertyOffset offset = current->get(vm, propertyName, attributes); 1065 1030 if (!JSC::isValidOffset(offset)) 1066 1031 continue; … … 1102 1067 1103 1068 shape->markAsFinal(); 1104 1105 1069 return shape.release(); 1106 1070 } … … 1122 1086 PropertyTable::iterator iter = table->begin(); 1123 1087 PropertyTable::iterator end = table->end(); 1124 for (; iter != end; ++iter) {1088 for (; iter != end; ++iter) 1125 1089 out.print(comma, iter->key, ":", static_cast<int>(iter->offset)); 1126 if (iter->specificValue) {1127 DumpContext dummyContext;1128 out.print("=>", RawPointer(iter->specificValue.get()));1129 }1130 }1131 1090 1132 1091 structure->m_lock.unlock(); … … 1138 1097 continue; 1139 1098 out.print(comma, structure->m_nameInPrevious.get(), ":", static_cast<int>(structure->m_offset)); 1140 if (structure->m_specificValueInPrevious) {1141 DumpContext dummyContext;1142 out.print("=>", RawPointer(structure->m_specificValueInPrevious.get()));1143 }1144 1099 } 1145 1100 -
trunk/Source/JavaScriptCore/runtime/Structure.h
r171660 r172129 60 60 class PropertyTable; 61 61 class StructureChain; 62 class StructureShape; 62 63 class SlotVisitor; 63 64 class JSString; … … 112 113 static void dumpStatistics(); 113 114 114 JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, JSCell* specificValue,PropertyOffset&, PutPropertySlot::Context = PutPropertySlot::UnknownContext);115 static Structure* addPropertyTransitionToExistingStructureConcurrently(Structure*, StringImpl* uid, unsigned attributes, JSCell* specificValue,PropertyOffset&);116 JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, JSCell* specificValue,PropertyOffset&);115 JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, PropertyOffset&, PutPropertySlot::Context = PutPropertySlot::UnknownContext); 116 static Structure* addPropertyTransitionToExistingStructureConcurrently(Structure*, StringImpl* uid, unsigned attributes, PropertyOffset&); 117 JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, PropertyOffset&); 117 118 static Structure* removePropertyTransition(VM&, Structure*, PropertyName, PropertyOffset&); 118 119 JS_EXPORT_PRIVATE static Structure* changePrototypeTransition(VM&, Structure*, JSValue prototype); 119 JS_EXPORT_PRIVATE static Structure* despecifyFunctionTransition(VM&, Structure*, PropertyName);120 120 static Structure* attributeChangeTransition(VM&, Structure*, PropertyName, unsigned attributes); 121 121 JS_EXPORT_PRIVATE static Structure* toCacheableDictionaryTransition(VM&, Structure*); … … 139 139 140 140 // These should be used with caution. 141 JS_EXPORT_PRIVATE PropertyOffset addPropertyWithoutTransition(VM&, PropertyName, unsigned attributes , JSCell* specificValue);141 JS_EXPORT_PRIVATE PropertyOffset addPropertyWithoutTransition(VM&, PropertyName, unsigned attributes); 142 142 PropertyOffset removePropertyWithoutTransition(VM&, PropertyName); 143 143 void setPrototypeWithoutTransition(VM& vm, JSValue prototype) { m_prototype.set(vm, this, prototype); } … … 189 189 bool prototypeChainMayInterceptStoreTo(VM&, PropertyName); 190 190 191 bool transitionDidInvolveSpecificValue() const { return !!m_specificValueInPrevious; }192 193 191 Structure* previousID() const 194 192 { … … 264 262 PropertyOffset get(VM&, PropertyName); 265 263 PropertyOffset get(VM&, const WTF::String& name); 266 PropertyOffset get(VM&, PropertyName, unsigned& attributes , JSCell*& specificValue);264 PropertyOffset get(VM&, PropertyName, unsigned& attributes); 267 265 268 266 PropertyOffset getConcurrently(VM&, StringImpl* uid); 269 PropertyOffset getConcurrently(VM&, StringImpl* uid, unsigned& attributes , JSCell*& specificValue);267 PropertyOffset getConcurrently(VM&, StringImpl* uid, unsigned& attributes); 270 268 271 269 void setHasGetterSetterPropertiesWithProtoCheck(bool is__proto__) … … 290 288 return !JSC::isValidOffset(m_offset); 291 289 } 292 293 JS_EXPORT_PRIVATE void despecifyDictionaryFunction(VM&, PropertyName);294 void disableSpecificFunctionTracking() { setSpecificFunctionThrashCount(maxSpecificFunctionThrashCount); }295 290 296 291 void setEnumerationCache(VM&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h. … … 372 367 m_transitionWatchpointSet.add(watchpoint); 373 368 } 374 375 void notifyTransitionFromThisStructure() const 376 { 377 m_transitionWatchpointSet.fireAll(); 378 } 369 370 void didTransitionFromThisStructure() const; 379 371 380 372 InlineWatchpointSet& transitionWatchpointSet() const 381 373 { 382 374 return m_transitionWatchpointSet; 375 } 376 377 WatchpointSet* ensurePropertyReplacementWatchpointSet(VM&, PropertyOffset); 378 void startWatchingPropertyForReplacements(VM& vm, PropertyOffset offset) 379 { 380 ensurePropertyReplacementWatchpointSet(vm, offset); 381 } 382 void startWatchingPropertyForReplacements(VM&, PropertyName); 383 WatchpointSet* propertyReplacementWatchpointSet(PropertyOffset); 384 void didReplaceProperty(PropertyOffset); 385 void didCachePropertyReplacement(VM&, PropertyOffset); 386 387 void startWatchingInternalPropertiesIfNecessary(VM& vm) 388 { 389 if (LIKELY(didWatchInternalProperties())) 390 return; 391 startWatchingInternalProperties(vm); 392 } 393 394 void startWatchingInternalPropertiesIfNecessaryForEntireChain(VM& vm) 395 { 396 for (Structure* structure = this; structure; structure = structure->storedPrototypeStructure()) 397 structure->startWatchingInternalPropertiesIfNecessary(vm); 383 398 } 384 399 … … 417 432 DEFINE_BITFIELD(bool, hasNonEnumerableProperties, HasNonEnumerableProperties, 1, 5); 418 433 DEFINE_BITFIELD(unsigned, attributesInPrevious, AttributesInPrevious, 14, 6); 419 DEFINE_BITFIELD( unsigned, specificFunctionThrashCount, SpecificFunctionThrashCount, 2, 20);420 DEFINE_BITFIELD(bool, preventExtensions, PreventExtensions, 1, 22);421 DEFINE_BITFIELD(bool, didTransition, DidTransition, 1, 23);422 DEFINE_BITFIELD(bool, staticFunctionsReified, StaticFunctionsReified, 1, 24);423 DEFINE_BITFIELD(bool, has RareData, HasRareData, 1, 25);424 DEFINE_BITFIELD(bool, has BeenFlattenedBefore, HasBeenFlattenedBefore, 1, 26);425 DEFINE_BITFIELD(bool, hasCustomGetterSetterProperties, HasCustomGetterSetterProperties, 1, 27);434 DEFINE_BITFIELD(bool, preventExtensions, PreventExtensions, 1, 20); 435 DEFINE_BITFIELD(bool, didTransition, DidTransition, 1, 21); 436 DEFINE_BITFIELD(bool, staticFunctionsReified, StaticFunctionsReified, 1, 22); 437 DEFINE_BITFIELD(bool, hasRareData, HasRareData, 1, 23); 438 DEFINE_BITFIELD(bool, hasBeenFlattenedBefore, HasBeenFlattenedBefore, 1, 24); 439 DEFINE_BITFIELD(bool, hasCustomGetterSetterProperties, HasCustomGetterSetterProperties, 1, 25); 440 DEFINE_BITFIELD(bool, didWatchInternalProperties, DidWatchInternalProperties, 1, 26); 426 441 427 442 private: … … 434 449 static Structure* create(VM&, Structure*); 435 450 436 static Structure* addPropertyTransitionToExistingStructureImpl(Structure*, StringImpl* uid, unsigned attributes, JSCell* specificValue,PropertyOffset&);451 static Structure* addPropertyTransitionToExistingStructureImpl(Structure*, StringImpl* uid, unsigned attributes, PropertyOffset&); 437 452 438 453 // This will return the structure that has a usable property table, that property table, … … 444 459 static Structure* toDictionaryTransition(VM&, Structure*, DictionaryKind); 445 460 446 PropertyOffset putSpecificValue(VM&, PropertyName, unsigned attributes, JSCell* specificValue);461 PropertyOffset add(VM&, PropertyName, unsigned attributes); 447 462 PropertyOffset remove(PropertyName); 448 463 449 464 void createPropertyMap(const GCSafeConcurrentJITLocker&, VM&, unsigned keyCount = 0); 450 465 void checkConsistency(); 451 452 bool despecifyFunction(VM&, PropertyName);453 void despecifyAllFunctions(VM&);454 466 455 467 WriteBarrier<PropertyTable>& propertyTable(); … … 528 540 529 541 JS_EXPORT_PRIVATE void allocateRareData(VM&); 530 void cloneRareDataFrom(VM&, const Structure*); 542 543 void startWatchingInternalProperties(VM&); 531 544 532 545 static const int s_maxTransitionLength = 64; 533 546 static const int s_maxTransitionLengthForNonEvalPutById = 512; 534 547 535 static const unsigned maxSpecificFunctionThrashCount = 3;536 537 548 // These need to be properly aligned at the beginning of the 'Structure' 538 549 // part of the object. … … 547 558 548 559 RefPtr<StringImpl> m_nameInPrevious; 549 WriteBarrier<JSCell> m_specificValueInPrevious;550 560 551 561 const ClassInfo* m_classInfo; -
trunk/Source/JavaScriptCore/runtime/StructureInlines.h
r171660 r172129 62 62 JSValue value = m_prototype.get(); 63 63 if (value.isNull()) 64 return 0;64 return nullptr; 65 65 return asObject(value); 66 66 } … … 70 70 JSObject* object = storedPrototypeObject(); 71 71 if (!object) 72 return 0;72 return nullptr; 73 73 return object->structure(); 74 74 } … … 100 100 } 101 101 102 ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes , JSCell*& specificValue)102 ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes) 103 103 { 104 104 ASSERT(!isCompilationThread()); … … 115 115 116 116 attributes = entry->attributes; 117 specificValue = entry->specificValue.get();118 117 return entry->offset; 119 118 } … … 122 121 { 123 122 unsigned attributesIgnored; 124 JSCell* specificValueIgnored; 125 return getConcurrently( 126 vm, uid, attributesIgnored, specificValueIgnored); 123 return getConcurrently(vm, uid, attributesIgnored); 127 124 } 128 125 … … 241 238 ASSERT(!globalObject() || !globalObject()->vm().heap.isCollecting()); 242 239 return m_propertyTableUnsafe; 240 } 241 242 inline void Structure::didReplaceProperty(PropertyOffset offset) 243 { 244 if (LIKELY(!hasRareData())) 245 return; 246 StructureRareData::PropertyWatchpointMap* map = rareData()->m_replacementWatchpointSets.get(); 247 if (LIKELY(!map)) 248 return; 249 WatchpointSet* set = map->get(offset); 250 if (LIKELY(!set)) 251 return; 252 set->fireAll("Property did get replaced"); 253 } 254 255 inline WatchpointSet* Structure::propertyReplacementWatchpointSet(PropertyOffset offset) 256 { 257 ConcurrentJITLocker locker(m_lock); 258 if (!hasRareData()) 259 return nullptr; 260 WTF::loadLoadFence(); 261 StructureRareData::PropertyWatchpointMap* map = rareData()->m_replacementWatchpointSets.get(); 262 if (!map) 263 return nullptr; 264 return map->get(offset); 243 265 } 244 266 -
trunk/Source/JavaScriptCore/runtime/StructureRareData.cpp
r171939 r172129 47 47 } 48 48 49 StructureRareData* StructureRareData::clone(VM& vm, const StructureRareData* other)49 void StructureRareData::destroy(JSCell* cell) 50 50 { 51 StructureRareData* newRareData = new (NotNull, allocateCell<StructureRareData>(vm.heap)) StructureRareData(vm, other); 52 newRareData->finishCreation(vm); 53 return newRareData; 51 static_cast<StructureRareData*>(cell)->StructureRareData::~StructureRareData(); 54 52 } 55 53 … … 59 57 if (previous) 60 58 m_previous.set(vm, this, previous); 61 }62 63 StructureRareData::StructureRareData(VM& vm, const StructureRareData* other)64 : JSCell(vm, other->structure())65 {66 if (other->previousID())67 m_previous.set(vm, this, other->previousID());68 if (other->objectToStringValue())69 m_objectToStringValue.set(vm, this, other->objectToStringValue());70 59 } 71 60 -
trunk/Source/JavaScriptCore/runtime/StructureRareData.h
r171939 r172129 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 #include "JSCell.h" 31 31 #include "JSTypeInfo.h" 32 #include "PropertyOffset.h" 32 33 33 34 namespace JSC { … … 40 41 public: 41 42 static StructureRareData* create(VM&, Structure*); 42 static StructureRareData* clone(VM&, const StructureRareData* other); 43 44 static const bool needsDestruction = true; 45 static const bool hasImmortalStructure = true; 46 static void destroy(JSCell*); 43 47 44 48 static void visitChildren(JSCell*, SlotVisitor&); 45 49 46 50 static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype); 47 48 // Returns true if this StructureRareData should also be cloned when cloning the owner Structure.49 bool needsCloning() const { return false; }50 51 51 52 Structure* previousID() const; … … 62 63 63 64 private: 65 friend class Structure; 66 64 67 StructureRareData(VM&, Structure*); 65 StructureRareData(VM&, const StructureRareData*);66 68 67 69 static const unsigned StructureFlags = JSCell::StructureFlags; … … 70 72 WriteBarrier<JSString> m_objectToStringValue; 71 73 WriteBarrier<JSPropertyNameIterator> m_enumerationCache; 74 75 typedef HashMap<PropertyOffset, RefPtr<WatchpointSet>, WTF::IntHash<PropertyOffset>, WTF::UnsignedWithZeroKeyHashTraits<PropertyOffset>> PropertyWatchpointMap; 76 std::unique_ptr<PropertyWatchpointMap> m_replacementWatchpointSets; 72 77 }; 73 78 -
trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp
r171824 r172129 80 80 } 81 81 82 void SymbolTableEntry::notifyWriteSlow(VM& vm, JSValue value )82 void SymbolTableEntry::notifyWriteSlow(VM& vm, JSValue value, const FireDetail& detail) 83 83 { 84 84 VariableWatchpointSet* watchpoints = fatEntry()->m_watchpoints.get(); … … 86 86 return; 87 87 88 watchpoints->notifyWrite(vm, value );88 watchpoints->notifyWrite(vm, value, detail); 89 89 } 90 90 … … 133 133 void SymbolTable::WatchpointCleanup::finalizeUnconditionally() 134 134 { 135 StringFireDetail detail("Symbol table clean-up during GC"); 135 136 Map::iterator iter = m_symbolTable->m_map.begin(); 136 137 Map::iterator end = m_symbolTable->m_map.end(); 137 138 for (; iter != end; ++iter) { 138 139 if (VariableWatchpointSet* set = iter->value.watchpointSet()) 139 set->finalizeUnconditionally( );140 set->finalizeUnconditionally(detail); 140 141 } 141 142 } -
trunk/Source/JavaScriptCore/runtime/SymbolTable.h
r171660 r172129 231 231 } 232 232 233 ALWAYS_INLINE void notifyWrite(VM& vm, JSValue value )233 ALWAYS_INLINE void notifyWrite(VM& vm, JSValue value, const FireDetail& detail) 234 234 { 235 235 if (LIKELY(!isFat())) 236 236 return; 237 notifyWriteSlow(vm, value );237 notifyWriteSlow(vm, value, detail); 238 238 } 239 239 … … 259 259 260 260 SymbolTableEntry& copySlow(const SymbolTableEntry&); 261 JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue );261 JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const FireDetail&); 262 262 263 263 bool isFat() const -
trunk/Source/JavaScriptCore/runtime/TypeSet.cpp
r171660 r172129 39 39 : m_seenTypes(TypeNothing) 40 40 , m_structureHistory(new Vector<RefPtr<StructureShape>>) 41 , m_mightHaveDuplicatesInStructureHistory(false)42 41 { 43 42 } … … 70 69 } 71 70 72 void TypeSet::addTypeForValue(JSValue v, PassRefPtr<StructureShape> shape )71 void TypeSet::addTypeForValue(JSValue v, PassRefPtr<StructureShape> shape, StructureID id) 73 72 { 74 73 RuntimeType t = getRuntimeTypeForValue(v); 75 74 m_seenTypes = m_seenTypes | t; 76 75 77 if (shape) { 78 m_structureHistory->append(shape); 79 m_mightHaveDuplicatesInStructureHistory = true; 80 } 81 } 82 83 void TypeSet::removeDuplicatesInStructureHistory() 84 { 85 Vector<RefPtr<StructureShape>>* newHistory = new Vector<RefPtr<StructureShape>>; 86 HashMap<String, bool> container; 87 for (size_t i = 0; i < m_structureHistory->size(); i++) { 88 RefPtr<StructureShape> a = m_structureHistory->at(i); 89 String hash = a->propertyHash(); 90 auto iter = container.find(hash); 91 if (iter == container.end()) { 92 container.add(hash, true); 93 newHistory->append(a); 76 if (id && shape) { 77 ASSERT(m_structureIDHistory.isValidKey(id)); 78 auto iter = m_structureIDHistory.find(id); 79 if (iter == m_structureIDHistory.end()) { 80 m_structureIDHistory.set(id, 1); 81 // Make one more pass making sure that we don't have the same shape. (Same shapes may have different StructureIDs). 82 bool found = false; 83 String hash = shape->propertyHash(); 84 for (size_t i = 0; i < m_structureHistory->size(); i++) { 85 RefPtr<StructureShape> obj = m_structureHistory->at(i); 86 if (obj->propertyHash() == hash) { 87 found = true; 88 break; 89 } 90 } 91 92 if (!found) 93 m_structureHistory->append(shape); 94 94 } 95 95 } 96 97 delete m_structureHistory;98 m_structureHistory = newHistory;99 m_mightHaveDuplicatesInStructureHistory = false;100 96 } 101 97 … … 104 100 if (m_seenTypes == TypeNothing) 105 101 return "(Unreached Statement)"; 106 107 if (m_mightHaveDuplicatesInStructureHistory)108 removeDuplicatesInStructureHistory();109 102 110 103 StringBuilder seen; … … 129 122 seen.append("Object "); 130 123 124 for (size_t i = 0; i < m_structureHistory->size(); i++) { 125 RefPtr<StructureShape> shape = m_structureHistory->at(i); 126 if (!shape->m_constructorName.isEmpty()) { 127 seen.append(shape->m_constructorName); 128 seen.append(" "); 129 } 130 } 131 131 132 if (m_structureHistory->size()) 132 133 seen.append("\nStructures:[ "); -
trunk/Source/JavaScriptCore/runtime/TypeSet.h
r171660 r172129 27 27 #define TypeSet_h 28 28 29 #include "StructureIDTable.h" 29 30 #include <wtf/HashMap.h> 30 31 #include <wtf/RefCounted.h> … … 61 62 static String leastUpperBound(Vector<RefPtr<StructureShape>>*); 62 63 String stringRepresentation(); 64 void setConstructorName(String name) { m_constructorName = name; } 63 65 64 66 private: 65 67 HashMap<RefPtr<StringImpl>, bool> m_fields; 66 68 std::unique_ptr<String> m_propertyHash; 69 String m_constructorName; 67 70 bool m_final; 68 71 }; … … 73 76 static PassRefPtr<TypeSet> create() { return adoptRef(new TypeSet); } 74 77 TypeSet(); 75 void addTypeForValue(JSValue v, PassRefPtr<StructureShape> );78 void addTypeForValue(JSValue v, PassRefPtr<StructureShape>, StructureID); 76 79 static RuntimeType getRuntimeTypeForValue(JSValue); 77 80 JS_EXPORT_PRIVATE String seenTypes(); … … 81 84 void dumpSeenTypes(); 82 85 Vector<RefPtr<StructureShape>>* m_structureHistory; 83 bool m_mightHaveDuplicatesInStructureHistory; 84 void removeDuplicatesInStructureHistory(); 85 86 HashMap<StructureID, uint8_t> m_structureIDHistory; 86 87 }; 87 88 -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r171824 r172129 41 41 #include "DFGLongLivedState.h" 42 42 #include "DFGWorklist.h" 43 #include "DebuggerScope.h"44 43 #include "ErrorInstance.h" 45 44 #include "FTLThunks.h" … … 207 206 structureStructure.set(*this, Structure::createStructure(*this)); 208 207 structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull())); 209 debuggerScopeStructure.set(*this, DebuggerScope::createStructure(*this, 0, jsNull()));210 208 terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull())); 211 209 stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull())); … … 836 834 { 837 835 if (RefPtr<WatchpointSet> watchpointSet = m_impurePropertyWatchpointSets.take(propertyName)) 838 watchpointSet->fireAll( );836 watchpointSet->fireAll("Impure property added"); 839 837 } 840 838 … … 859 857 } 860 858 861 String VM::getTypesForVariable InRange(unsigned startLine, unsigned startColumn, unsigned endLine, unsigned endColumn, const String& variableName, const String& sourceIDAsString)859 String VM::getTypesForVariableAtOffset(unsigned offset, const String& variableName, const String& sourceIDAsString) 862 860 { 863 861 if (!isProfilingTypesWithHighFidelity()) … … 870 868 871 869 updateHighFidelityTypeProfileState(); 872 return m_highFidelityTypeProfiler->getTypesForVariableIn Range(startLine, startColumn, endLine, endColumn, variableName, sourceID);870 return m_highFidelityTypeProfiler->getTypesForVariableInAtOffset(offset, variableName, sourceID); 873 871 } 874 872 … … 890 888 for (Bag<TypeLocation>::iterator iter = m_locationInfo.begin(); !!iter; ++iter) { 891 889 TypeLocation* location = *iter; 892 dataLogF("[ Line, Column]::[%u, %u] ", location->m_line, location->m_column);890 dataLogF("[Start, End]::[%u, %u] ", location->m_divotStart, location->m_divotEnd); 893 891 dataLog("\n\t\t#Local#\n\t\t", 894 profiler->getLocalTypesForVariable InRange(location->m_line, location->m_column, location->m_line, location->m_column, "", location->m_sourceID).replace("\n", "\n\t\t"),892 profiler->getLocalTypesForVariableAtOffset(location->m_divotStart, "", location->m_sourceID).replace("\n", "\n\t\t"), 895 893 "\n\t\t#Global#\n\t\t", 896 profiler->getGlobalTypesForVariable InRange(location->m_line, location->m_column, location->m_line, location->m_column, "", location->m_sourceID).replace("\n", "\n\t\t"),894 profiler->getGlobalTypesForVariableAtOffset(location->m_divotStart, "", location->m_sourceID).replace("\n", "\n\t\t"), 897 895 "\n"); 898 896 } -
trunk/Source/JavaScriptCore/runtime/VM.h
r171824 r172129 241 241 Strong<Structure> structureStructure; 242 242 Strong<Structure> structureRareDataStructure; 243 Strong<Structure> debuggerScopeStructure;244 243 Strong<Structure> terminatedExecutionErrorStructure; 245 244 Strong<Structure> stringStructure; … … 495 494 496 495 bool isProfilingTypesWithHighFidelity() { return !!m_highFidelityTypeProfiler; } 497 String getTypesForVariable InRange(unsigned startLine, unsigned startColumn, unsigned endLine, unsigned endColumn, const String& variableName, const String& sourceID);496 String getTypesForVariableAtOffset(unsigned divot, const String& variableName, const String& sourceID); 498 497 HighFidelityLog* highFidelityLog() { return m_highFidelityLog.get(); } 499 498 HighFidelityTypeProfiler* highFidelityTypeProfiler() { return m_highFidelityTypeProfiler.get(); } -
trunk/Source/WTF/wtf/PrintStream.h
r164424 r172129 1 1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 35 35 namespace WTF { 36 36 37 class AtomicStringImpl; 37 38 class CString; 38 39 class String; … … 70 71 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const String&); 71 72 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const StringImpl*); 73 inline void printInternal(PrintStream& out, const AtomicStringImpl* value) { printInternal(out, bitwise_cast<const StringImpl*>(value)); } 72 74 inline void printInternal(PrintStream& out, char* value) { printInternal(out, static_cast<const char*>(value)); } 73 75 inline void printInternal(PrintStream& out, CString& value) { printInternal(out, static_cast<const CString&>(value)); } 74 76 inline void printInternal(PrintStream& out, String& value) { printInternal(out, static_cast<const String&>(value)); } 75 77 inline void printInternal(PrintStream& out, StringImpl* value) { printInternal(out, static_cast<const StringImpl*>(value)); } 78 inline void printInternal(PrintStream& out, AtomicStringImpl* value) { printInternal(out, static_cast<const AtomicStringImpl*>(value)); } 76 79 WTF_EXPORT_PRIVATE void printInternal(PrintStream&, bool); 77 80 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 -
trunk/Source/WebCore/ChangeLog
r172128 r172129 1 2014-07-29 Filip Pizlo <fpizlo@apple.com> 2 3 Merge r170564, r170571, r170604, r170628, r170672, r170680, r170724, r170728, r170729, r170819, r170821, r170836, r170855, r170860, r170890, r170907, r170929, r171052, r171106, r171152, r171153, r171214 from ftlopt. 4 5 2014-07-01 Mark Lam <mark.lam@apple.com> 6 7 [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope. 8 <https://webkit.org/b/134420> 9 10 Reviewed by Geoffrey Garen. 11 12 No new tests. 13 14 * ForwardingHeaders/debugger/DebuggerCallFrame.h: Removed. 15 - This is not in use. Hence, we can remove it. 16 * bindings/js/ScriptController.cpp: 17 (WebCore::ScriptController::attachDebugger): 18 - We should acquire the JSLock before modifying a JS global object. 19 20 2014-06-25 Filip Pizlo <fpizlo@apple.com> 21 22 [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint 23 https://bugs.webkit.org/show_bug.cgi?id=134333 24 25 Reviewed by Geoffrey Garen. 26 27 No new tests because no change in behavior. 28 29 * bindings/scripts/CodeGeneratorJS.pm: 30 (GenerateHeader): 31 1 32 2014-08-05 Ryuan Choi <ryuan.choi@samsung.com> 2 33 -
trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp
r171824 r172129 283 283 continue; 284 284 JSDOMWindowBase* jsWindow = JSC::jsCast<JSDOMWindowBase*>(wrapper); 285 jsWindow->m_windowCloseWatchpoints.fireAll( );285 jsWindow->m_windowCloseWatchpoints.fireAll("Frame cleared"); 286 286 } 287 287 } -
trunk/Source/WebCore/bindings/js/ScriptController.cpp
r172006 r172129 308 308 309 309 JSDOMWindow* globalObject = shell->window(); 310 JSLockHolder lock(globalObject->vm()); 310 311 if (debugger) 311 312 debugger->attach(globalObject); -
trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
r172128 r172129 850 850 push(@headerContent, " static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n"); 851 851 push(@headerContent, " {\n"); 852 push(@headerContent, " globalObject->masqueradesAsUndefinedWatchpoint()->fireAll( );\n");852 push(@headerContent, " globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(\"Allocated masquerading object\");\n"); 853 853 push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, globalObject, impl);\n"); 854 854 push(@headerContent, " ptr->finishCreation(globalObject->vm());\n"); -
trunk/Tools/ChangeLog
r172118 r172129 1 2014-07-29 Filip Pizlo <fpizlo@apple.com> 2 3 Merge r170564, r170571, r170604, r170628, r170672, r170680, r170724, r170728, r170729, r170819, r170821, r170836, r170855, r170860, r170890, r170907, r170929, r171052, r171106, r171152, r171153, r171214 from ftlopt. 4 5 2014-06-25 Filip Pizlo <fpizlo@apple.com> 6 7 [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint 8 https://bugs.webkit.org/show_bug.cgi?id=134333 9 10 Reviewed by Geoffrey Garen. 11 12 * Scripts/display-profiler-output: 13 1 14 2014-08-05 David Farler <dfarler@apple.com> 2 15 -
trunk/Tools/Scripts/display-profiler-output
r163259 r172129 332 332 attr_accessor :bytecode, :engine, :descriptions, :counters, :compilationIndex 333 333 attr_accessor :osrExits, :profiledBytecodes, :numInlinedGetByIds, :numInlinedPutByIds 334 attr_accessor :numInlinedCalls, :jettisonReason 334 attr_accessor :numInlinedCalls, :jettisonReason, :additionalJettisonReason 335 335 336 336 def initialize(json) … … 386 386 @numInlinedCalls = json["numInlinedCalls"] 387 387 @jettisonReason = json["jettisonReason"] 388 @additionalJettisonReason = json["additionalJettisonReason"] 388 389 end 389 390 … … 859 860 if compilation.jettisonReason != "NotJettisoned" 860 861 puts " Jettisoned due to #{compilation.jettisonReason}" 862 if compilation.additionalJettisonReason 863 puts " #{compilation.additionalJettisonReason}" 864 end 861 865 end 862 866 }
Note:
See TracChangeset
for help on using the changeset viewer.