Ejemplo n.º 1
0
OSRExit::OSRExit(ExitKind kind, JSValueSource jsValueSource, MethodOfGettingAValueProfile valueProfile, SpeculativeJIT* jit, unsigned streamIndex, unsigned recoveryIndex)
    : OSRExitBase(kind, jit->m_origin.forExit, jit->m_origin.semantic)
    , m_jsValueSource(jsValueSource)
    , m_valueProfile(valueProfile)
    , m_patchableCodeOffset(0)
    , m_recoveryIndex(recoveryIndex)
    , m_streamIndex(streamIndex)
    , m_willArriveAtOSRExitFromGenericUnwind(false)
{
    bool canExit = jit->m_origin.exitOK;
    if (!canExit && jit->m_currentNode) {
        ExitMode exitMode = mayExit(jit->m_jit.graph(), jit->m_currentNode);
        canExit = exitMode == ExitMode::Exits || exitMode == ExitMode::ExitsForExceptions;
    }
    DFG_ASSERT(jit->m_jit.graph(), jit->m_currentNode, canExit);
}
Ejemplo n.º 2
0
    bool attemptHoist(BasicBlock* fromBlock, Node*& nodeRef, const NaturalLoop* loop)
    {
        Node* node = nodeRef;
        LoopData& data = m_data[loop->index()];

        if (!data.preHeader) {
            if (verbose)
                dataLog("    Not hoisting ", node, " because the pre-header is invalid.\n");
            return false;
        }
        
        if (!data.preHeader->cfaDidFinish) {
            if (verbose)
                dataLog("    Not hoisting ", node, " because CFA is invalid.\n");
            return false;
        }
        
        if (!edgesDominate(m_graph, node, data.preHeader)) {
            if (verbose) {
                dataLog(
                    "    Not hoisting ", node, " because it isn't loop invariant.\n");
            }
            return false;
        }
        
        // FIXME: At this point if the hoisting of the full node fails but the node has type checks,
        // we could still hoist just the checks.
        // https://bugs.webkit.org/show_bug.cgi?id=144525
        
        if (readsOverlap(m_graph, node, data.writes)) {
            if (verbose) {
                dataLog(
                    "    Not hoisting ", node,
                    " because it reads things that the loop writes.\n");
            }
            return false;
        }
        
        m_state.initializeTo(data.preHeader);
        if (!safeToExecute(m_state, m_graph, node)) {
            if (verbose) {
                dataLog(
                    "    Not hoisting ", node, " because it isn't safe to execute.\n");
            }
            return false;
        }
        
        NodeOrigin originalOrigin = node->origin;

        // NOTE: We could just use BackwardsDominators here directly, since we already know that the
        // preHeader dominates fromBlock. But we wouldn't get anything from being so clever, since
        // dominance checks are O(1) and only a few integer compares.
        bool addsBlindSpeculation = mayExit(m_graph, node, m_state)
            && !m_graph.m_controlEquivalenceAnalysis->dominatesEquivalently(data.preHeader, fromBlock);
        
        if (addsBlindSpeculation
            && m_graph.baselineCodeBlockFor(originalOrigin.semantic)->hasExitSite(FrequentExitSite(HoistingFailed))) {
            if (verbose) {
                dataLog(
                    "    Not hoisting ", node, " because it may exit and the pre-header (",
                    *data.preHeader, ") is not control equivalent to the node's original block (",
                    *fromBlock, ") and hoisting had previously failed.\n");
            }
            return false;
        }
        
        if (verbose) {
            dataLog(
                "    Hoisting ", node, " from ", *fromBlock, " to ", *data.preHeader,
                "\n");
        }

        // FIXME: We should adjust the Check: flags on the edges of node. There are phases that assume
        // that those flags are correct even if AI is stale.
        // https://bugs.webkit.org/show_bug.cgi?id=148544
        data.preHeader->insertBeforeTerminal(node);
        node->owner = data.preHeader;
        NodeOrigin terminalOrigin = data.preHeader->terminal()->origin;
        node->origin = terminalOrigin.withSemantic(node->origin.semantic);
        node->origin.wasHoisted |= addsBlindSpeculation;
        
        // Modify the states at the end of the preHeader of the loop we hoisted to,
        // and all pre-headers inside the loop. This isn't a stability bottleneck right now
        // because most loops are small and most blocks belong to few loops.
        for (unsigned bodyIndex = loop->size(); bodyIndex--;) {
            BasicBlock* subBlock = loop->at(bodyIndex);
            const NaturalLoop* subLoop = m_graph.m_naturalLoops->headerOf(subBlock);
            if (!subLoop)
                continue;
            BasicBlock* subPreHeader = m_data[subLoop->index()].preHeader;
            // We may not have given this loop a pre-header because either it didn't have exitOK
            // or the header had multiple predecessors that it did not dominate. In that case the
            // loop wouldn't be a hoisting candidate anyway, so we don't have to do anything.
            if (!subPreHeader)
                continue;
            // The pre-header's tail may be unreachable, in which case we have nothing to do.
            if (!subPreHeader->cfaDidFinish)
                continue;
            m_state.initializeTo(subPreHeader);
            m_interpreter.execute(node);
        }
        
        // It just so happens that all of the nodes we currently know how to hoist
        // don't have var-arg children. That may change and then we can fix this
        // code. But for now we just assert that's the case.
        DFG_ASSERT(m_graph, node, !(node->flags() & NodeHasVarArgs));
        
        nodeRef = m_graph.addNode(Check, originalOrigin, node->children);
        
        return true;
    }