Changeset 192190 in webkit
- Timestamp:
- Nov 9, 2015 4:39:13 PM (8 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r192187 r192190 1 2015-11-09 Saam barati <sbarati@apple.com> 2 3 DFG::PutStackSinkingPhase should not treat the stack variables written by LoadVarargs/ForwardVarargs as being live 4 https://bugs.webkit.org/show_bug.cgi?id=145295 5 6 Reviewed by Filip Pizlo. 7 8 This patch fixes PutStackSinkingPhase to no longer escape the stack 9 locations that LoadVarargs and ForwardVarargs write to. We used 10 to consider sinking PutStacks right before a LoadVarargs/ForwardVarargs 11 because we considered them uses of such stack locations. They aren't 12 uses of those stack locations, they unconditionally write to those 13 stack locations. Sinking PutStacks to these nodes was not needed before, 14 but seemed mostly innocent. But I ran into a problem with this while implementing 15 FTL try/catch where we would end up having to generate a value for a sunken PutStack 16 right before a LoadVarargs. This would cause us to issue a GetStack that loaded garbage that 17 was then forwarded into a Phi that was used as the source as the PutStack. This caused the 18 abstract interpreter to confuse itself on type information for the garbage GetStack 19 that was fed into the Phi, which would cause the abstract interpreter to then claim 20 that the basic block with the PutStack in it would never be reached. This isn't true, the 21 block would indeed be reached. The solution here is to be more precise about the 22 liveness of locals w.r.t LoadVarargs and ForwardVarargs. 23 24 * dfg/DFGPreciseLocalClobberize.h: 25 (JSC::DFG::PreciseLocalClobberizeAdaptor::PreciseLocalClobberizeAdaptor): 26 (JSC::DFG::PreciseLocalClobberizeAdaptor::write): 27 * dfg/DFGPutStackSinkingPhase.cpp: 28 * dfg/DFGSSACalculator.h: 29 1 30 2015-11-09 Filip Pizlo <fpizlo@apple.com> 2 31 -
trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h
r191965 r192190 43 43 , m_node(node) 44 44 , m_read(read) 45 , m_ write(write)45 , m_unconditionalWrite(write) 46 46 , m_def(def) 47 47 { … … 71 71 if (heap.kind() == Stack) { 72 72 RELEASE_ASSERT(!heap.payload().isTop()); 73 callIfAppropriate(m_ write, VirtualRegister(heap.payload().value32()));73 callIfAppropriate(m_unconditionalWrite, VirtualRegister(heap.payload().value32())); 74 74 return; 75 75 } … … 156 156 Node* m_node; 157 157 const ReadFunctor& m_read; 158 const WriteFunctor& m_ write;158 const WriteFunctor& m_unconditionalWrite; 159 159 const DefFunctor& m_def; 160 160 }; -
trunk/Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp
r191870 r192190 109 109 dataLog("Live at ", node, ": ", live, "\n"); 110 110 111 Vector<VirtualRegister, 4> reads; 112 Vector<VirtualRegister, 4> writes; 111 113 auto escapeHandler = [&] (VirtualRegister operand) { 112 114 if (operand.isHeader()) … … 114 116 if (verbose) 115 117 dataLog(" ", operand, " is live at ", node, "\n"); 118 reads.append(operand); 119 }; 120 121 auto writeHandler = [&] (VirtualRegister operand) { 122 RELEASE_ASSERT(node->op() == PutStack || node->op() == LoadVarargs || node->op() == ForwardVarargs); 123 writes.append(operand); 124 }; 125 126 preciseLocalClobberize( 127 m_graph, node, escapeHandler, writeHandler, 128 [&] (VirtualRegister, LazyNode) { }); 129 130 for (VirtualRegister operand : writes) 131 live.operand(operand) = false; 132 for (VirtualRegister operand : reads) 116 133 live.operand(operand) = true; 117 };118 119 // FIXME: This might mishandle LoadVarargs and ForwardVarargs. It might make us120 // think that the locals being written are stack-live here. They aren't. This121 // should be harmless since we overwrite them anyway, but still, it's sloppy.122 // https://bugs.webkit.org/show_bug.cgi?id=145295123 preciseLocalClobberize(124 m_graph, node, escapeHandler, escapeHandler,125 [&] (VirtualRegister operand, LazyNode source) {126 RELEASE_ASSERT(source.isNode());127 128 if (source.asNode() == node) {129 // This is a load. Ignore it.130 return;131 }132 133 RELEASE_ASSERT(node->op() == PutStack);134 live.operand(operand) = false;135 });136 134 } 137 135 … … 206 204 // identified an operation that would have observed that PutStack. 207 205 // 208 // This code has some interesting quirks because of the fact that neither liveness nor 209 // deferrals are very precise. They are only precise enough to be able to correctly tell us 210 // when we may [sic] need to execute PutStacks. This means that they may report the need to 211 // execute a PutStack in cases where we actually don't really need it, and that's totally OK. 206 // We need to be precise about liveness in this phase because not doing so 207 // could cause us to insert a PutStack before a node we thought may escape a 208 // value that it doesn't really escape. Sinking this PutStack above such a node may 209 // cause us to insert a GetStack that we forward to the Phi we're feeding into the 210 // sunken PutStack. Inserting such a GetStack could cause us to load garbage and 211 // can confuse the AI to claim untrue things (like that the program will exit when 212 // it really won't). 212 213 BlockMap<Operands<FlushFormat>> deferredAtHead(m_graph); 213 214 BlockMap<Operands<FlushFormat>> deferredAtTail(m_graph); … … 270 271 // from. 271 272 continue; 273 } else if (node->op() == PutStack) { 274 VirtualRegister operand = node->stackAccessData()->local; 275 deferred.operand(operand) = node->stackAccessData()->format; 276 continue; 272 277 } 273 278 … … 280 285 deferred.operand(operand) = DeadFlush; 281 286 }; 287 288 auto writeHandler = [&] (VirtualRegister operand) { 289 RELEASE_ASSERT(node->op() == LoadVarargs || node->op() == ForwardVarargs); 290 deferred.operand(operand) = DeadFlush; 291 }; 282 292 283 293 preciseLocalClobberize( 284 m_graph, node, escapeHandler, escapeHandler, 285 [&] (VirtualRegister operand, LazyNode source) { 286 RELEASE_ASSERT(source.isNode()); 287 288 if (source.asNode() == node) { 289 // This is a load. Ignore it. 290 return; 291 } 292 293 deferred.operand(operand) = node->stackAccessData()->format; 294 }); 294 m_graph, node, escapeHandler, writeHandler, 295 [&] (VirtualRegister, LazyNode) { }); 295 296 } 296 297 … … 352 353 } 353 354 354 HashSet<Node*> put LocalsToSink;355 HashSet<Node*> putStacksToSink; 355 356 356 357 for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { … … 358 359 switch (node->op()) { 359 360 case PutStack: 360 put LocalsToSink.add(node);361 putStacksToSink.add(node); 361 362 ssaCalculator.newDef( 362 363 operandToVariable.operand(node->stackAccessData()->local), … … 497 498 deferred.operand(operand) = DeadFlush; 498 499 }; 499 500 501 auto writeHandler = [&] (VirtualRegister operand) { 502 // LoadVarargs and ForwardVarargs are unconditional writes to the stack 503 // locations they claim to write to. They do not read from the stack 504 // locations they write to. This makes those stack locations dead right 505 // before a LoadVarargs/ForwardVarargs. This means we should never sink 506 // PutStacks right to this point. 507 RELEASE_ASSERT(node->op() == LoadVarargs || node->op() == ForwardVarargs); 508 deferred.operand(operand) = DeadFlush; 509 }; 510 500 511 preciseLocalClobberize( 501 m_graph, node, escapeHandler, escapeHandler,512 m_graph, node, escapeHandler, writeHandler, 502 513 [&] (VirtualRegister, LazyNode) { }); 503 514 break; … … 553 564 Node* node = block->at(nodeIndex); 554 565 555 if (!put LocalsToSink.contains(node))566 if (!putStacksToSink.contains(node)) 556 567 continue; 557 568 558 569 node->remove(); 559 570 } 560 561 insertionSet.execute(block);562 571 } 563 572 -
trunk/Source/JavaScriptCore/dfg/DFGSSACalculator.h
r191870 r192190 92 92 // https://bugs.webkit.org/show_bug.cgi?id=136639 93 93 // 94 // 4.3) Insert Upsilons for each Phi in each successor block. Use the available values table to95 // decide the source value for each Phi's variable. Note that you could also use96 // SSACalculator::reachingDefAtTail() instead of the available values table, though your97 // local available values table is likely to be more efficient.94 // 4.3) Insert Upsilons at the end of the current block for the corresponding Phis in each successor block. 95 // Use the available values table to decide the source value for each Phi's variable. Note that 96 // you could also use SSACalculator::reachingDefAtTail() instead of the available values table, 97 // though your local available values table is likely to be more efficient. 98 98 // 99 99 // The most obvious use of SSACalculator is for the CPS->SSA conversion itself, but it's meant to
Note: See TracChangeset
for help on using the changeset viewer.