Changeset 266242 in webkit for trunk/Source/JavaScriptCore
- Timestamp:
- Aug 27, 2020, 10:10:18 AM (5 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r266236 r266242 1 2020-08-27 Keith Miller <[email protected]> 2 3 OSR availability validation should run for any node with exitOK 4 https://bugs.webkit.org/show_bug.cgi?id=215672 5 6 Reviewed by Saam Barati. 7 8 Currently we only validate OSR exit availability if a node would 9 say `mayExit(graph, node) != DoesNotExit` and the node is marked 10 as exitOK. However, it would be perfectly valid to insert a node 11 that exits anywhere we have a node marked exitOK. So with this 12 patch we now validate all places where it would ever be possible 13 to OSR exit. 14 15 Relaxing our criteria revealed a number of bugs however. Which I 16 will describe below in, IMO, increasing complexity/subtly. 17 18 First, we currently don't mark arity fixup during inlining as not 19 exitOK. However, since our arity code says its code origin is 20 OpEnter, we assume arity fixup has already happened. 21 22 Second, OpGetScope, should not mark its first argument as used 23 since it's not actually used. This is problematic because we could 24 have a loop where OpGetScope is the first bytecode, namely when 25 doing tail recursive inlining. If we were in that position, there 26 could be a local that was used at a merge point at the loop 27 backedge that had two MovHint defs from both predecessors. In DFG 28 IR this would look like: 29 30 BB#1: 31 @1: MovHint(Undefined, loc1) 32 ... 33 Jump(#2) 34 35 BB#2: 36 ... // loc1 is live here in bytecode 37 @2: MovHint(@scopeObject, loc1) 38 @3: SetLocal(@scopeObject, loc1) 39 Branch(#3, #4) // #4 is the successor of the tail call loop 40 41 BB#3: 42 @4 MovHint(Undefined, loc1) 43 ... 44 Jump(#2) 45 46 When we do CPS conversion the MovHints at @1 and @4 will be seen 47 as different variables (there's no GetLocal). Then, after, during 48 SSA conversion we won't insert a phi connecting them, making the 49 argument to OpGetScope, in this case loc1, unrecoverable there are 50 conflicting nodes and the value isn't saved on the stack. 51 52 There were also issues with MovHintRemoval Phase but rather than 53 fix them we opted to just remove the phase as it didn't show any 54 performance impact. I'll describe the issues I found below for 55 completeness, however. 56 57 Third, MovHint removal phase had a bug where it would not mark 58 sections where a zombied MovHint has yet to be killed as not 59 exitOK. So in theory another phase could come along and insert an 60 exiting node there. 61 62 Fourth, MovHint removal phase had a second bug where a MovHint 63 that was not killed in the current block would be zombied, which 64 is wrong for SSA. It's wrong because the MovHinted value could 65 still be live for OSR exit in a successor block. 66 67 Lastly, this patch adds some new verbose options as well as the ability to 68 dump a DFG::BasicBlock without dereferencing it. 69 70 * bytecode/BytecodeUseDef.cpp: 71 (JSC::computeUsesForBytecodeIndexImpl): 72 * dfg/DFGBasicBlock.cpp: 73 (WTF::printInternal): 74 * dfg/DFGBasicBlock.h: 75 * dfg/DFGByteCodeParser.cpp: 76 (JSC::DFG::ByteCodeParser::inlineCall): 77 * dfg/DFGCPSRethreadingPhase.cpp: 78 (JSC::DFG::CPSRethreadingPhase::propagatePhis): 79 * dfg/DFGEpoch.h: 80 (JSC::DFG::Epoch::operator bool const): 81 * dfg/DFGOSRAvailabilityAnalysisPhase.cpp: 82 (JSC::DFG::OSRAvailabilityAnalysisPhase::run): 83 * dfg/DFGSSACalculator.cpp: 84 (JSC::DFG::SSACalculator::dump const): 85 1 86 2020-08-27 Keith Miller <[email protected]> 2 87 -
trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp
r265907 r266242 101 101 case op_super_sampler_begin: 102 102 case op_super_sampler_end: 103 return;104 105 USES(OpGetScope, dst) 103 case op_get_scope: 104 return; 105 106 106 USES(OpToThis, srcDst) 107 107 USES(OpCheckTdz, targetVirtualRegister) -
trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.cpp
r261895 r266242 151 151 } } // namespace JSC::DFG 152 152 153 namespace WTF { 154 155 void printInternal(PrintStream& out, JSC::DFG::BasicBlock* block) 156 { 157 out.print(*block); 158 } 159 160 } 161 153 162 #endif // ENABLE(DFG_JIT) 154 163 -
trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.h
r254735 r266242 276 276 } } // namespace JSC::DFG 277 277 278 namespace WTF { 279 void printInternal(PrintStream&, JSC::DFG::BasicBlock*); 280 } 281 278 282 #endif // ENABLE(DFG_JIT) -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r265934 r266242 1722 1722 BytecodeIndex oldIndex = m_currentIndex; 1723 1723 m_currentIndex = BytecodeIndex(0); 1724 1725 // We don't want to exit here since we could do things like arity fixup which complicates OSR exit availability. 1726 m_exitOK = false; 1724 1727 1725 1728 switch (kind) { -
trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
r261895 r266242 36 36 37 37 class CPSRethreadingPhase : public Phase { 38 static constexpr bool verbose = false; 38 39 public: 39 40 CPSRethreadingPhase(Graph& graph) … … 426 427 size_t index = entry.m_index; 427 428 429 if (verbose) { 430 dataLog(" Iterating on phi from block ", block, " "); 431 m_graph.dump(WTF::dataFile(), "", currentPhi); 432 } 433 428 434 for (size_t i = predecessors.size(); i--;) { 429 435 BasicBlock* predecessorBlock = predecessors[i]; … … 434 440 predecessorBlock->variablesAtTail.atFor<operandKind>(index) = variableInPrevious; 435 441 predecessorBlock->variablesAtHead.atFor<operandKind>(index) = variableInPrevious; 442 dataLogLnIf(verbose, " No variable in predecessor ", predecessorBlock, " creating a new phi: ", variableInPrevious); 436 443 } else { 437 444 switch (variableInPrevious->op()) { … … 439 446 case PhantomLocal: 440 447 case Flush: 448 dataLogLnIf(verbose, " Variable in predecessor ", predecessorBlock, " ", variableInPrevious, " needs to be forwarded to first child ", variableInPrevious->child1().node()); 441 449 ASSERT(variableInPrevious->variableAccessData() == variableInPrevious->child1()->variableAccessData()); 442 450 variableInPrevious = variableInPrevious->child1().node(); … … 453 461 || variableInPrevious->op() == SetArgumentMaybe); 454 462 463 if (verbose) 464 m_graph.dump(WTF::dataFile(), " Adding new variable from predecessor ", variableInPrevious); 465 455 466 if (!currentPhi->child1()) { 456 467 currentPhi->children.setChild1(Edge(variableInPrevious)); -
trunk/Source/JavaScriptCore/dfg/DFGEpoch.h
r250005 r266242 65 65 } 66 66 67 explicit operator bool() const 68 { 69 return !!*this; 70 } 71 67 72 Epoch next() const 68 73 { -
trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp
r266095 r266242 135 135 for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { 136 136 Node* node = block->at(nodeIndex); 137 // FIXME: The mayExit status of a node doesn't seem like it should mean we don't need to have everything available. 138 if (mayExit(m_graph, node) != DoesNotExit && node->origin.exitOK) { 137 if (node->origin.exitOK) { 139 138 // If we're allowed to exit here, the heap must be in a state 140 139 // where exiting wouldn't crash. These particular fields are … … 144 143 145 144 CodeOrigin exitOrigin = node->origin.forExit; 146 AvailabilityMap& availabilityMap = calculator.m_availability; 145 // FIXME: availabilityMap seems like it should be able to be a reference to the calculator's map. https://bugs.webkit.org/show_bug.cgi?id=215675 146 AvailabilityMap availabilityMap = calculator.m_availability; 147 147 availabilityMap.pruneByLiveness(m_graph, exitOrigin); 148 148 -
trunk/Source/JavaScriptCore/dfg/DFGSSACalculator.cpp
r261895 r266242 116 116 m_variables[i].dumpVerbose(out); 117 117 } 118 out.print("], Defs: [");118 out.print("], \nDefs: ["); 119 119 comma = CommaPrinter(); 120 120 for (Def* def : const_cast<SSACalculator*>(this)->m_defs) 121 121 out.print(comma, *def); 122 out.print("], Phis: [");122 out.print("], \nPhis: ["); 123 123 comma = CommaPrinter(); 124 124 for (Def* def : const_cast<SSACalculator*>(this)->m_phis) 125 125 out.print(comma, *def); 126 out.print("], Block data: [");127 comma = CommaPrinter( );126 out.print("], \nBlock data: ["); 127 comma = CommaPrinter(",\n"); 128 128 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { 129 129 BasicBlock* block = m_graph.block(blockIndex);
Note:
See TracChangeset
for help on using the changeset viewer.