Changeset 240364 in webkit
- Timestamp:
- Jan 23, 2019 4:17:15 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r240329 r240364 1 2019-01-23 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [DFG] AvailabilityMap::pruneByLiveness should make non-live operands Availability::unavailable instead of Availability() 4 https://bugs.webkit.org/show_bug.cgi?id=193711 5 <rdar://problem/47250262> 6 7 Reviewed by Saam Barati. 8 9 * stress/availability-was-cleared-when-locals-are-not-live.js: Added. 10 (shouldBe): 11 (foo): 12 (bar): 13 (baz): 14 1 15 2019-01-22 Yusuke Suzuki <ysuzuki@apple.com> 2 16 -
trunk/Source/JavaScriptCore/ChangeLog
r240335 r240364 1 2019-01-23 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [DFG] AvailabilityMap::pruneByLiveness should make non-live operands Availability::unavailable instead of Availability() 4 https://bugs.webkit.org/show_bug.cgi?id=193711 5 <rdar://problem/47250262> 6 7 Reviewed by Saam Barati. 8 9 When pruning OSR Availability based on bytecode liveness, we accidentally clear the Availability (making it DeadFlush) instead of 10 making it Availability::unavailable() (Making it ConflictingFlush). In OSRAvailabilityAnalysisPhase, we perform forward analysis. 11 We first clear all the availability of basic blocks DeadFlush, which is an empty set. And then, we set operands in the root block 12 ConflictingFlush. In this forward analysis, DeadFlush is BOTTOM, and ConflictingFlush is TOP. Then, we propagate information by 13 merging availability until we reach to the fixed-point. As an optimization, we perform "pruning" of the availability in the head 14 of the basic blocks. We remove availabilities of operands which are not live in the bytecode liveness at the head of the basic block. 15 The problem is, when removing availabilities, we set DeadFlush for them instead of ConflictingFlush. Basically, it means that we set 16 BOTTOM (an empty set) instead of TOP. Let's consider the following simple example. We have 6 basic blocks, and they are connected 17 as follows. 18 19 BB0 -> BB1 -> BB2 -> BB4 20 | \ ^ 21 v > BB3 / 22 BB5 23 24 And consider about loc1 in FTL, which is required to be recovered in BB4's OSR exit. 25 26 BB0 does nothing 27 head: loc1 is dead 28 tail: loc1 is dead 29 30 BB1 has MovHint @1, loc1 31 head: loc1 is dead 32 tail: loc1 is live 33 34 BB2 does nothing 35 head: loc1 is live 36 tail: loc1 is live 37 38 BB3 has PutStack @1, loc1 39 head: loc1 is live 40 tail: loc1 is live 41 42 BB4 has OSR exit using loc1 43 head: loc1 is live 44 tail: loc1 is live (in bytecode) 45 46 BB5 does nothing 47 head: loc1 is dead 48 tail: loc1 is dead 49 50 In our OSR Availability analysis, we always prune loc1 result in BB1's head since its head says "loc1 is dead". 51 But at that time, we clear the availability for loc1, which makes it DeadFlush, instead of making it ConflictingFlush. 52 53 So, the flush format of loc1 in each tail of BB is like this. 54 55 BB0 56 ConflictingFlush (because all the local operands are initialized with ConflictingFlush) 57 BB1 58 DeadFlush+@1 (pruning clears it) 59 BB2 60 DeadFlush+@1 (since it is propagated from BB1) 61 BB3 62 FlushedJSValue+@1 with loc1 (since it has PutStack) 63 BB4 64 FlushedJSValue+@1 with loc1 (since MERGE(DeadFlush, FlushedJSValue) = FlushedJSValue) 65 BB5 66 DeadFlush (pruning clears it) 67 68 Then, if we go the path BB0->BB1->BB2->BB4, we read the value from the stack while it is not flushed. 69 The correct fix is making availability "unavailable" when pruning based on bytecode liveness. 70 71 * dfg/DFGAvailabilityMap.cpp: 72 (JSC::DFG::AvailabilityMap::pruneByLiveness): When pruning availability, we first set all the operands Availability::unavailable(), 73 and copy the calculated value from the current availability map. 74 * dfg/DFGOSRAvailabilityAnalysisPhase.cpp: 75 (JSC::DFG::OSRAvailabilityAnalysisPhase::run): Add logging things for debugging. 76 1 77 2019-01-23 David Kilzer <ddkilzer@apple.com> 2 78 -
trunk/Source/JavaScriptCore/dfg/DFGAvailabilityMap.cpp
r219502 r240364 66 66 void AvailabilityMap::pruneByLiveness(Graph& graph, CodeOrigin where) 67 67 { 68 Operands<Availability> localsCopy( OperandsLike, m_locals);68 Operands<Availability> localsCopy(m_locals.numberOfArguments(), m_locals.numberOfLocals(), Availability::unavailable()); 69 69 graph.forAllLiveInBytecode( 70 70 where, -
trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp
r226033 r240364 36 36 37 37 namespace JSC { namespace DFG { 38 namespace DFGOSRAvailabilityAnalysisPhaseInternal { 39 static constexpr bool verbose = false; 40 } 38 41 39 42 class OSRAvailabilityAnalysisPhase : public Phase { … … 64 67 // This could be made more efficient by processing blocks in reverse postorder. 65 68 69 auto dumpAvailability = [] (BasicBlock* block) { 70 dataLogLn(block->ssa->availabilityAtHead); 71 dataLogLn(block->ssa->availabilityAtTail); 72 }; 73 74 auto dumpBytecodeLivenessAtHead = [&] (BasicBlock* block) { 75 dataLog("Live: "); 76 m_graph.forAllLiveInBytecode( 77 block->at(0)->origin.forExit, 78 [&] (VirtualRegister reg) { 79 dataLog(reg, " "); 80 }); 81 dataLogLn(""); 82 }; 83 66 84 LocalOSRAvailabilityCalculator calculator(m_graph); 67 85 bool changed; … … 74 92 continue; 75 93 94 if (DFGOSRAvailabilityAnalysisPhaseInternal::verbose) { 95 dataLogLn("Before changing Block #", block->index); 96 dumpAvailability(block); 97 } 76 98 calculator.beginBlock(block); 77 99 … … 84 106 block->ssa->availabilityAtTail = calculator.m_availability; 85 107 changed = true; 108 109 if (DFGOSRAvailabilityAnalysisPhaseInternal::verbose) { 110 dataLogLn("After changing Block #", block->index); 111 dumpAvailability(block); 112 } 86 113 87 114 for (unsigned successorIndex = block->numSuccessors(); successorIndex--;) { … … 94 121 successor->ssa->availabilityAtHead.pruneByLiveness( 95 122 m_graph, successor->at(0)->origin.forExit); 123 if (DFGOSRAvailabilityAnalysisPhaseInternal::verbose) { 124 dataLogLn("After pruning Block #", successor->index); 125 dumpAvailability(successor); 126 dumpBytecodeLivenessAtHead(successor); 127 } 96 128 } 97 129 }
Note: See TracChangeset
for help on using the changeset viewer.