Ignore:
Timestamp:
Jan 11, 2019, 4:26:06 PM (7 years ago)
Author:
[email protected]
Message:

DFG combined liveness can be wrong for terminal basic blocks
https://bugs.webkit.org/show_bug.cgi?id=193304
<rdar://problem/45268632>

Reviewed by Yusuke Suzuki.

JSTests:

  • stress/dfg-combined-liveness-consider-terminal-blocks-bytecode-liveness.js: Added.

Source/JavaScriptCore:

If a block doesn't have any successors, it can't rely on the typical
backwards liveness propagation that CombinedLiveness was doing. The phase
first got what was live in bytecode and IR at the heads of each block. Then
for each block, it made the live at tail the union of the live at head for
each successor. For a terminal block though, this could be wrong. We could
end up saying nothing is live even though many things may be live in bytecode.
We must account for what's bytecode live at the end of the block. Consider a
block that ends with:
`
ForceOSRExit
Unreachable
`

Things may definitely be live in bytecode at the tail. However, we'll
report nothing as being alive. This probably subtly breaks many analyses,
but we have a test case of it breaking the interference analysis that
the ArgumentsEliminationPhase performs.

  • dfg/DFGBasicBlock.h:

(JSC::DFG::BasicBlock::last const):

  • dfg/DFGCombinedLiveness.cpp:

(JSC::DFG::addBytecodeLiveness):
(JSC::DFG::liveNodesAtHead):
(JSC::DFG::CombinedLiveness::CombinedLiveness):

  • dfg/DFGCombinedLiveness.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGCombinedLiveness.cpp

    r232334 r239882  
    3636namespace JSC { namespace DFG {
    3737
    38 NodeSet liveNodesAtHead(Graph& graph, BasicBlock* block)
     38static void addBytecodeLiveness(Graph& graph, AvailabilityMap& availabilityMap, NodeSet& seen, Node* node)
    3939{
    40     NodeSet seen;
    41     for (NodeFlowProjection node : block->ssa->liveAtHead) {
    42         if (node.kind() == NodeFlowProjection::Primary)
    43             seen.addVoid(node.node());
    44     }
    45    
    46     AvailabilityMap& availabilityMap = block->ssa->availabilityAtHead;
    4740    graph.forAllLiveInBytecode(
    48         block->at(0)->origin.forExit,
     41        node->origin.forExit,
    4942        [&] (VirtualRegister reg) {
    5043            availabilityMap.closeStartingWithLocal(
     
    5750                });
    5851        });
    59    
     52}
     53
     54NodeSet liveNodesAtHead(Graph& graph, BasicBlock* block)
     55{
     56    NodeSet seen;
     57    for (NodeFlowProjection node : block->ssa->liveAtHead) {
     58        if (node.kind() == NodeFlowProjection::Primary)
     59            seen.addVoid(node.node());
     60    }
     61
     62    addBytecodeLiveness(graph, block->ssa->availabilityAtHead, seen, block->at(0));
    6063    return seen;
    6164}
     
    6568    , liveAtTail(graph)
    6669{
    67     // First compute the liveAtHead for each block.
    68     for (BasicBlock* block : graph.blocksInNaturalOrder())
     70    // First compute
     71    // - The liveAtHead for each block.
     72    // - The liveAtTail for blocks that won't properly propagate
     73    //   the information based on their empty successor list.
     74    for (BasicBlock* block : graph.blocksInNaturalOrder()) {
    6975        liveAtHead[block] = liveNodesAtHead(graph, block);
     76
     77        // If we don't have successors, we can't rely on the propagation below. This doesn't usually
     78        // do anything for terminal blocks, since the last node is usually a return, so nothing is live
     79        // after it. However, we may also have the end of the basic block be:
     80        //
     81        // ForceOSRExit
     82        // Unreachable
     83        //
     84        // And things may definitely be live in bytecode at that point in the program.
     85        if (!block->numSuccessors()) {
     86            NodeSet seen;
     87            addBytecodeLiveness(graph, block->ssa->availabilityAtTail, seen, block->last());
     88            liveAtTail[block] = seen;
     89        }
     90    }
    7091   
    7192    // Now compute the liveAtTail by unifying the liveAtHead of the successors.
Note: See TracChangeset for help on using the changeset viewer.