Changeset 183207 in webkit
- Timestamp:
- Apr 23, 2015, 1:47:31 PM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 3 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r183199 r183207 204 204 dfg/DFGOperations.cpp 205 205 dfg/DFGPhantomCanonicalizationPhase.cpp 206 dfg/DFGPhantomInsertionPhase.cpp 206 207 dfg/DFGPhantomRemovalPhase.cpp 207 208 dfg/DFGPhase.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r183201 r183207 1 2015-04-22 Filip Pizlo <[email protected]> 2 3 DFG should insert Phantoms late using BytecodeKills and block-local OSR availability 4 https://bugs.webkit.org/show_bug.cgi?id=143735 5 6 Reviewed by Geoffrey Garen. 7 8 We've always had bugs arising from the fact that we would MovHint something into a local, 9 and then fail to keep it alive. We would then try to keep things alive by putting Phantoms 10 on those Nodes that were MovHinted. But this became increasingly tricky. Given the 11 sophistication of the transformations we are doing today, this approach is just not sound 12 anymore. 13 14 This comprehensively fixes these bugs by having the DFG backend automatically insert 15 Phantoms just before codegen based on bytecode liveness. To make this practical, this also 16 makes it much faster to query bytecode liveness. 17 18 It's about as perf-neutral as it gets for a change that increases compiler work without 19 actually optimizing anything. Later changes will remove the old Phantom-preserving logic, 20 which should then speed us up. I can't really report concrete slow-down numbers because 21 they are low enough to basically be in the noise. For example, a 20-iteration run of 22 SunSpider yields "maybe 0.8% slower", whatever that means. 23 24 * CMakeLists.txt: 25 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 26 * JavaScriptCore.xcodeproj/project.pbxproj: 27 * bytecode/BytecodeLivenessAnalysis.cpp: 28 (JSC::BytecodeLivenessAnalysis::computeFullLiveness): 29 * bytecode/FullBytecodeLiveness.h: 30 (JSC::FullBytecodeLiveness::getLiveness): 31 * bytecode/VirtualRegister.h: 32 (JSC::VirtualRegister::operator+): 33 (JSC::VirtualRegister::operator-): 34 * dfg/DFGForAllKills.h: 35 (JSC::DFG::forAllLiveNodesAtTail): 36 (JSC::DFG::forAllKilledOperands): 37 (JSC::DFG::forAllKilledNodesAtNodeIndex): 38 * dfg/DFGGraph.cpp: 39 (JSC::DFG::Graph::isLiveInBytecode): 40 (JSC::DFG::Graph::localsLiveInBytecode): 41 * dfg/DFGGraph.h: 42 (JSC::DFG::Graph::forAllLocalsLiveInBytecode): 43 (JSC::DFG::Graph::forAllLiveInBytecode): 44 * dfg/DFGMayExit.cpp: 45 (JSC::DFG::mayExit): 46 * dfg/DFGMovHintRemovalPhase.cpp: 47 * dfg/DFGNodeType.h: 48 * dfg/DFGPhantomInsertionPhase.cpp: Added. 49 (JSC::DFG::performPhantomInsertion): 50 * dfg/DFGPhantomInsertionPhase.h: Added. 51 * dfg/DFGPlan.cpp: 52 (JSC::DFG::Plan::compileInThreadImpl): 53 * dfg/DFGScoreBoard.h: 54 (JSC::DFG::ScoreBoard::sortFree): 55 (JSC::DFG::ScoreBoard::assertClear): 56 * dfg/DFGVirtualRegisterAllocationPhase.cpp: 57 (JSC::DFG::VirtualRegisterAllocationPhase::run): 58 * ftl/FTLLowerDFGToLLVM.cpp: 59 (JSC::FTL::LowerDFGToLLVM::buildExitArguments): 60 * tests/stress/phantom-inadequacy.js: Added. 61 (bar): 62 (baz): 63 (foo): 64 1 65 2015-04-23 Filip Pizlo <[email protected]> 2 66 -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r183161 r183207 448 448 <ClCompile Include="..\dfg\DFGObjectMaterializationData.cpp" /> 449 449 <ClCompile Include="..\dfg\DFGPhantomCanonicalizationPhase.cpp" /> 450 <ClCompile Include="..\dfg\DFGPhantomInsertionPhase.cpp" /> 450 451 <ClCompile Include="..\dfg\DFGPhantomRemovalPhase.cpp" /> 451 452 <ClCompile Include="..\dfg\DFGPhase.cpp" /> … … 1143 1144 <ClInclude Include="..\dfg\DFGOSRExitPreparation.h" /> 1144 1145 <ClInclude Include="..\dfg\DFGPhantomCanonicalizationPhase.h" /> 1146 <ClInclude Include="..\dfg\DFGPhantomInsertionPhase.h" /> 1145 1147 <ClInclude Include="..\dfg\DFGPhantomRemovalPhase.h" /> 1146 1148 <ClInclude Include="..\dfg\DFGPhase.h" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r183161 r183207 349 349 0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */; settings = {ATTRIBUTES = (Private, ); }; }; 350 350 0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */; settings = {ATTRIBUTES = (Private, ); }; }; 351 0F6237971AE45CA700D402EA /* DFGPhantomInsertionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6237951AE45CA700D402EA /* DFGPhantomInsertionPhase.cpp */; }; 352 0F6237981AE45CA700D402EA /* DFGPhantomInsertionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6237961AE45CA700D402EA /* DFGPhantomInsertionPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 351 353 0F63943F15C75F19006A597C /* DFGTypeCheckHoistingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63943D15C75F14006A597C /* DFGTypeCheckHoistingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 352 354 0F63944015C75F1D006A597C /* DFGTypeCheckHoistingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F63943C15C75F14006A597C /* DFGTypeCheckHoistingPhase.cpp */; }; … … 2084 2086 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBasicBlock.h; path = dfg/DFGBasicBlock.h; sourceTree = "<group>"; }; 2085 2087 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessData.h; path = dfg/DFGVariableAccessData.h; sourceTree = "<group>"; }; 2088 0F6237951AE45CA700D402EA /* DFGPhantomInsertionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPhantomInsertionPhase.cpp; path = dfg/DFGPhantomInsertionPhase.cpp; sourceTree = "<group>"; }; 2089 0F6237961AE45CA700D402EA /* DFGPhantomInsertionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPhantomInsertionPhase.h; path = dfg/DFGPhantomInsertionPhase.h; sourceTree = "<group>"; }; 2086 2090 0F63943C15C75F14006A597C /* DFGTypeCheckHoistingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGTypeCheckHoistingPhase.cpp; path = dfg/DFGTypeCheckHoistingPhase.cpp; sourceTree = "<group>"; }; 2087 2091 0F63943D15C75F14006A597C /* DFGTypeCheckHoistingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGTypeCheckHoistingPhase.h; path = dfg/DFGTypeCheckHoistingPhase.h; sourceTree = "<group>"; }; … … 5025 5029 0F7B365F197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.cpp */, 5026 5030 0F7B3660197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.h */, 5031 0F6237951AE45CA700D402EA /* DFGPhantomInsertionPhase.cpp */, 5032 0F6237961AE45CA700D402EA /* DFGPhantomInsertionPhase.h */, 5027 5033 0FBFDD02196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp */, 5028 5034 0FBFDD03196C92BF007A5BFA /* DFGPhantomRemovalPhase.h */, … … 6221 6227 BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */, 6222 6228 A72FFD64139985A800E5365A /* KeywordLookup.h in Headers */, 6229 0F6237981AE45CA700D402EA /* DFGPhantomInsertionPhase.h in Headers */, 6223 6230 969A072A0ED1CE6900F1F681 /* Label.h in Headers */, 6224 6231 960097A60EBABB58007A7297 /* LabelScope.h in Headers */, … … 7474 7481 0FF729AD166AD35C000F5BA3 /* ProfilerBytecode.cpp in Sources */, 7475 7482 0FF729AE166AD35C000F5BA3 /* ProfilerBytecodes.cpp in Sources */, 7483 0F6237971AE45CA700D402EA /* DFGPhantomInsertionPhase.cpp in Sources */, 7476 7484 0F13912916771C33009CCB07 /* ProfilerBytecodeSequence.cpp in Sources */, 7477 7485 0FF729AF166AD35C000F5BA3 /* ProfilerCompilation.cpp in Sources */, -
trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp
r181993 r183207 238 238 FastBitVector out; 239 239 240 result.m_map. clear();240 result.m_map.resize(m_codeBlock->instructions().size()); 241 241 242 242 for (unsigned i = m_basicBlocks.size(); i--;) { … … 250 250 unsigned bytecodeOffset = block->bytecodeOffsets()[i]; 251 251 stepOverInstruction(m_codeBlock, m_basicBlocks, bytecodeOffset, out); 252 result.m_map .add(bytecodeOffset, out);252 result.m_map[bytecodeOffset] = out; 253 253 } 254 254 } -
trunk/Source/JavaScriptCore/bytecode/FullBytecodeLiveness.h
r181993 r183207 39 39 const FastBitVector& getLiveness(unsigned bytecodeIndex) const 40 40 { 41 BytecodeToBitmapMap::const_iterator iter = m_map.find(bytecodeIndex); 42 ASSERT(iter != m_map.end()); 43 return iter->value; 41 return m_map[bytecodeIndex]; 44 42 } 45 43 … … 52 50 friend class BytecodeLivenessAnalysis; 53 51 54 BytecodeToBitmapMapm_map;52 Vector<FastBitVector, 0, UnsafeVectorOverflow> m_map; 55 53 }; 56 54 -
trunk/Source/JavaScriptCore/bytecode/VirtualRegister.h
r181993 r183207 83 83 return VirtualRegister(offset() - value); 84 84 } 85 VirtualRegister operator+(VirtualRegister value) const 86 { 87 return VirtualRegister(offset() + value.offset()); 88 } 89 VirtualRegister operator-(VirtualRegister value) const 90 { 91 return VirtualRegister(offset() - value.offset()); 92 } 85 93 VirtualRegister& operator+=(int value) 86 94 { -
trunk/Source/JavaScriptCore/dfg/DFGForAllKills.h
r183094 r183207 52 52 53 53 AvailabilityMap& availabilityMap = block->ssa->availabilityAtTail; 54 for (unsigned i = availabilityMap.m_locals.size(); i--;) { 55 VirtualRegister reg = availabilityMap.m_locals.virtualRegisterForIndex(i); 56 57 if (!graph.isLiveInBytecode(reg, block->terminal()->origin.forExit)) 58 continue; 59 60 availabilityMap.closeStartingWithLocal( 61 reg, 62 [&] (Node* node) -> bool { 63 return seen.contains(node); 64 }, 65 [&] (Node* node) -> bool { 66 if (!seen.add(node).isNewEntry) 67 return false; 68 functor(node); 69 return true; 70 }); 71 } 72 } 73 74 template<typename Functor> 75 void forAllKilledOperands(Graph& graph, CodeOrigin before, Node* nodeAfter, const Functor& functor) 76 { 54 graph.forAllLocalsLiveInBytecode( 55 block->terminal()->origin.forExit, 56 [&] (VirtualRegister reg) { 57 availabilityMap.closeStartingWithLocal( 58 reg, 59 [&] (Node* node) -> bool { 60 return seen.contains(node); 61 }, 62 [&] (Node* node) -> bool { 63 if (!seen.add(node).isNewEntry) 64 return false; 65 functor(node); 66 return true; 67 }); 68 }); 69 } 70 71 // This tells you those things that die on the boundary between nodeBefore and nodeAfter. It is 72 // conservative in the sense that it might resort to telling you some things that are still live at 73 // nodeAfter. 74 template<typename Functor> 75 void forAllKilledOperands(Graph& graph, Node* nodeBefore, Node* nodeAfter, const Functor& functor) 76 { 77 CodeOrigin before = nodeBefore->origin.forExit; 77 78 CodeOrigin after = nodeAfter->origin.forExit; 79 80 VirtualRegister alreadyNoted; 81 if (!!after) { 82 // If we MovHint something that is live at the time, then we kill the old value. 83 if (nodeAfter->containsMovHint()) { 84 VirtualRegister reg = nodeAfter->unlinkedLocal(); 85 if (graph.isLiveInBytecode(reg, after)) { 86 functor(reg); 87 alreadyNoted = reg; 88 } 89 } 90 } 78 91 79 92 if (!before) { … … 83 96 // many such predecessors and they will likely all have a different origin. So, it's better 84 97 // to do the conservative thing. 85 for (unsigned i = graph.block(0)->variablesAtHead.numberOfLocals(); i--;) { 86 VirtualRegister reg = virtualRegisterForLocal(i); 87 if (graph.isLiveInBytecode(reg, after)) 88 functor(reg); 89 } 98 graph.forAllLocalsLiveInBytecode(after, functor); 90 99 return; 91 }92 93 // If we MovHint something that is live at the time, then we kill the old value.94 VirtualRegister alreadyNoted;95 if (nodeAfter->containsMovHint()) {96 VirtualRegister reg = nodeAfter->unlinkedLocal();97 if (graph.isLiveInBytecode(reg, after)) {98 functor(reg);99 alreadyNoted = reg;100 }101 100 } 102 101 … … 107 106 ASSERT(!!after); 108 107 108 // It's easier to do this if the inline call frames are the same. This is way faster than the 109 // other loop, below. 110 if (before.inlineCallFrame == after.inlineCallFrame) { 111 int stackOffset = before.inlineCallFrame ? before.inlineCallFrame->stackOffset : 0; 112 CodeBlock* codeBlock = graph.baselineCodeBlockFor(before.inlineCallFrame); 113 FullBytecodeLiveness& fullLiveness = graph.livenessFor(codeBlock); 114 const FastBitVector& liveBefore = fullLiveness.getLiveness(before.bytecodeIndex); 115 const FastBitVector& liveAfter = fullLiveness.getLiveness(after.bytecodeIndex); 116 117 for (unsigned relativeLocal = codeBlock->m_numCalleeRegisters; relativeLocal--;) { 118 if (liveBefore.get(relativeLocal) && !liveAfter.get(relativeLocal)) 119 functor(virtualRegisterForLocal(relativeLocal) + stackOffset); 120 } 121 122 return; 123 } 124 109 125 // Detect kills the super conservative way: it is killed if it was live before and dead after. 110 for (unsigned i = graph.block(0)->variablesAtHead.numberOfLocals(); i--;) { 111 VirtualRegister reg = virtualRegisterForLocal(i); 112 if (reg == alreadyNoted) 113 continue; 114 if (graph.isLiveInBytecode(reg, before) && !graph.isLiveInBytecode(reg, after)) 126 BitVector liveAfter = graph.localsLiveInBytecode(after); 127 graph.forAllLocalsLiveInBytecode( 128 before, 129 [&] (VirtualRegister reg) { 130 if (reg == alreadyNoted) 131 return; 132 if (liveAfter.get(reg.toLocal())) 133 return; 115 134 functor(reg); 116 }135 }); 117 136 } 118 137 … … 141 160 }); 142 161 143 CodeOrigin before;162 Node* before = nullptr; 144 163 if (nodeIndex) 145 before = block->at(nodeIndex - 1) ->origin.forExit;164 before = block->at(nodeIndex - 1); 146 165 147 166 forAllKilledOperands( -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r183162 r183207 945 945 // Arguments are always live. This would be redundant if it wasn't for our 946 946 // op_call_varargs inlining. 947 // FIXME: 'this' might not be live, but we don't have a way of knowing.948 // https://bugs.webkit.org/show_bug.cgi?id=128519949 947 if (reg.isArgument() 950 948 && static_cast<size_t>(reg.toArgument()) < inlineCallFrame->arguments.size()) … … 955 953 956 954 return true; 955 } 956 957 BitVector Graph::localsLiveInBytecode(CodeOrigin codeOrigin) 958 { 959 BitVector result; 960 result.ensureSize(block(0)->variablesAtHead.numberOfLocals()); 961 forAllLocalsLiveInBytecode( 962 codeOrigin, 963 [&] (VirtualRegister reg) { 964 ASSERT(reg.isLocal()); 965 result.quickSet(reg.toLocal()); 966 }); 967 return result; 957 968 } 958 969 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r183163 r183207 30 30 31 31 #include "AssemblyHelpers.h" 32 #include "BytecodeLivenessAnalysisInlines.h" 32 33 #include "CodeBlock.h" 33 34 #include "DFGArgumentPosition.h" … … 42 43 #include "DFGPrePostNumbering.h" 43 44 #include "DFGScannable.h" 45 #include "FullBytecodeLiveness.h" 44 46 #include "JSStack.h" 45 47 #include "MethodOfGettingAValueProfile.h" … … 678 680 FullBytecodeLiveness& livenessFor(CodeBlock*); 679 681 FullBytecodeLiveness& livenessFor(InlineCallFrame*); 682 683 // Quickly query if a single local is live at the given point. This is faster than calling 684 // forAllLiveInBytecode() if you will only query one local. But, if you want to know all of the 685 // locals live, then calling this for each local is much slower than forAllLiveInBytecode(). 680 686 bool isLiveInBytecode(VirtualRegister, CodeOrigin); 687 688 // Quickly get all of the non-argument locals live at the given point. This doesn't give you 689 // any arguments because those are all presumed live. You can call forAllLiveInBytecode() to 690 // also get the arguments. This is much faster than calling isLiveInBytecode() for each local. 691 template<typename Functor> 692 void forAllLocalsLiveInBytecode(CodeOrigin codeOrigin, const Functor& functor) 693 { 694 // Support for not redundantly reporting arguments. Necessary because in case of a varargs 695 // call, only the callee knows that arguments are live while in the case of a non-varargs 696 // call, both callee and caller will see the variables live. 697 VirtualRegister exclusionStart; 698 VirtualRegister exclusionEnd; 699 700 for (;;) { 701 InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; 702 VirtualRegister stackOffset(inlineCallFrame ? inlineCallFrame->stackOffset : 0); 703 704 if (inlineCallFrame) { 705 if (inlineCallFrame->isClosureCall) 706 functor(stackOffset + JSStack::Callee); 707 if (inlineCallFrame->isVarargs()) 708 functor(stackOffset + JSStack::ArgumentCount); 709 } 710 711 CodeBlock* codeBlock = baselineCodeBlockFor(inlineCallFrame); 712 FullBytecodeLiveness& fullLiveness = livenessFor(codeBlock); 713 const FastBitVector& liveness = fullLiveness.getLiveness(codeOrigin.bytecodeIndex); 714 for (unsigned relativeLocal = codeBlock->m_numCalleeRegisters; relativeLocal--;) { 715 VirtualRegister reg = stackOffset + virtualRegisterForLocal(relativeLocal); 716 717 // Don't report if our callee already reported. 718 if (reg >= exclusionStart && reg < exclusionEnd) 719 continue; 720 721 if (liveness.get(relativeLocal)) 722 functor(reg); 723 } 724 725 if (!inlineCallFrame) 726 break; 727 728 // Arguments are always live. This would be redundant if it wasn't for our 729 // op_call_varargs inlining. See the comment above. 730 exclusionStart = stackOffset + CallFrame::argumentOffsetIncludingThis(0); 731 exclusionEnd = stackOffset + CallFrame::argumentOffsetIncludingThis(inlineCallFrame->arguments.size()); 732 733 // We will always have a "this" argument and exclusionStart should be a smaller stack 734 // offset than exclusionEnd. 735 ASSERT(exclusionStart < exclusionEnd); 736 737 for (VirtualRegister reg = exclusionStart; reg < exclusionEnd; reg += 1) 738 functor(reg); 739 740 codeOrigin = inlineCallFrame->caller; 741 } 742 } 743 744 // Get a BitVector of all of the non-argument locals live right now. This is mostly useful if 745 // you want to compare two sets of live locals from two different CodeOrigins. 746 BitVector localsLiveInBytecode(CodeOrigin); 747 748 // Tells you all of the arguments and locals live at the given CodeOrigin. This is a small 749 // extension to forAllLocalsLiveInBytecode(), since all arguments are always presumed live. 750 template<typename Functor> 751 void forAllLiveInBytecode(CodeOrigin codeOrigin, const Functor& functor) 752 { 753 forAllLocalsLiveInBytecode(codeOrigin, functor); 754 755 // Report all arguments as being live. 756 for (unsigned argument = block(0)->variablesAtHead.numberOfArguments(); argument--;) 757 functor(virtualRegisterForArgument(argument)); 758 } 681 759 682 760 BytecodeKills& killsFor(CodeBlock*); -
trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp
r183201 r183207 89 89 case PhantomLocal: 90 90 case CountExecution: 91 case Jump: 92 case Branch: 93 case Unreachable: 91 94 break; 92 95 -
trunk/Source/JavaScriptCore/dfg/DFGMovHintRemovalPhase.cpp
r183094 r183207 81 81 Epoch currentEpoch = Epoch::first(); 82 82 83 for (unsigned i = m_state.size(); i--;) { 84 VirtualRegister reg = m_state.virtualRegisterForIndex(i); 85 if (m_graph.isLiveInBytecode(reg, block->terminal()->origin.forExit)) 86 m_state[i] = currentEpoch; 87 else 88 m_state[i] = Epoch(); 89 } 83 m_state.fill(Epoch()); 84 m_graph.forAllLiveInBytecode( 85 block->terminal()->origin.forExit, 86 [&] (VirtualRegister reg) { 87 m_state.operand(reg) = currentEpoch; 88 }); 90 89 91 90 if (verbose) … … 115 114 if (nodeIndex) { 116 115 forAllKilledOperands( 117 m_graph, block->at(nodeIndex - 1) ->origin.forExit, node,116 m_graph, block->at(nodeIndex - 1), node, 118 117 [&] (VirtualRegister reg) { 119 118 // This function is a bit sloppy - it might claim to kill a local even if -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r183201 r183207 56 56 /* Any two nodes that are part of the same Phi graph will share the same */\ 57 57 /* VariableAccessData, and thus will share predictions. FIXME: We should come up with */\ 58 /* better names for a lot of these. https://bugs.webkit.org/show_bug.cgi?id=137307 */\ 59 macro(GetLocal, NodeResultJS) \ 58 /* better names for a lot of these. https://bugs.webkit.org/show_bug.cgi?id=137307. */\ 59 /* Note that GetLocal is MustGenerate because it's our only way of knowing that some other */\ 60 /* basic block might have read a local variable in bytecode. We only remove GetLocals if it */\ 61 /* is redundant because of an earlier GetLocal or SetLocal in the same block. We could make */\ 62 /* these not MustGenerate and use a more sophisticated analysis to insert PhantomLocals in */\ 63 /* the same way that we insert Phantoms. https://bugs.webkit.org/show_bug.cgi?id=144086 */\ 64 macro(GetLocal, NodeResultJS | NodeMustGenerate) \ 60 65 macro(SetLocal, 0) \ 61 66 \ -
trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp
r183072 r183207 53 53 #include "DFGObjectAllocationSinkingPhase.h" 54 54 #include "DFGPhantomCanonicalizationPhase.h" 55 #include "DFGPhantomInsertionPhase.h" 55 56 #include "DFGPhantomRemovalPhase.h" 56 57 #include "DFGPredictionInjectionPhase.h" … … 321 322 performCPSRethreading(dfg); 322 323 performDCE(dfg); 324 performPhantomInsertion(dfg); 323 325 performStackLayout(dfg); 324 326 performVirtualRegisterAllocation(dfg); -
trunk/Source/JavaScriptCore/dfg/DFGScoreBoard.h
r159886 r183207 56 56 } 57 57 58 void sortFree() 59 { 60 std::sort(m_free.begin(), m_free.end()); 61 } 62 58 63 void assertClear() 59 64 { 60 #if !ASSERT_DISABLED 65 if (ASSERT_DISABLED) 66 return; 67 61 68 // For every entry in the used list the use count of the virtual register should be zero, or max, due to it being a preserved local. 62 69 for (size_t i = 0; i < m_used.size(); ++i) 63 ASSERT(!m_used[i] || m_used[i] == max());70 RELEASE_ASSERT(!m_used[i] || m_used[i] == max()); 64 71 // For every entry in the free list, the use count should be zero. 65 72 for (size_t i = 0; i < m_free.size(); ++i) 66 ASSERT(!m_used[m_free[i]]);73 RELEASE_ASSERT(!m_used[m_free[i]]); 67 74 // There must not be duplicates in the free list. 68 75 for (size_t i = 0; i < m_free.size(); ++i) { 69 76 for (size_t j = i + 1; j < m_free.size(); ++j) 70 ASSERT(m_free[i] != m_free[j]);77 RELEASE_ASSERT(m_free[i] != m_free[j]); 71 78 } 72 #endif73 79 } 74 80 -
trunk/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp
r180691 r183207 56 56 if (!block->isReachable) 57 57 continue; 58 if (!ASSERT_DISABLED) { 59 // Force usage of highest-numbered virtual registers. 60 scoreBoard.sortFree(); 61 } 58 62 for (size_t indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) { 59 63 Node* node = block->at(indexInBlock); -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r183201 r183207 7200 7200 7201 7201 AvailabilityMap availabilityMap = this->availabilityMap(); 7202 7203 for (unsigned i = 0; i < exit.m_values.size(); ++i) { 7204 int operand = exit.m_values.operandForIndex(i); 7205 bool isLive = m_graph.isLiveInBytecode(VirtualRegister(operand), codeOrigin); 7206 if (!isLive) 7207 availabilityMap.m_locals[i] = Availability(); 7208 } 7202 availabilityMap.m_locals.fill(Availability()); 7203 7204 m_graph.forAllLiveInBytecode( 7205 codeOrigin, 7206 [&] (VirtualRegister reg) { 7207 availabilityMap.m_locals.operand(reg) = 7208 this->availabilityMap().m_locals.operand(reg); 7209 }); 7209 7210 7210 7211 availabilityMap.prune();
Note:
See TracChangeset
for help on using the changeset viewer.