예제 #1
0
bool OSRExit::considerAddingAsFrequentExitSiteSlow(CodeBlock* profiledCodeBlock)
{
    FrequentExitSite exitSite;
    
    if (m_kind == ArgumentsEscaped) {
        // Count this one globally. It doesn't matter where in the code block the arguments excaped;
        // the fact that they did is not associated with any particular instruction.
        exitSite = FrequentExitSite(m_kind);
    } else
        exitSite = FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind);
    
    return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOriginForExitProfile, profiledCodeBlock)->addFrequentExitSite(exitSite);
}
예제 #2
0
void OSRExitBase::considerAddingAsFrequentExitSiteSlow(CodeBlock* profiledCodeBlock, ExitingJITType jitType)
{
    CodeBlock* sourceProfiledCodeBlock =
        baselineCodeBlockForOriginAndBaselineCodeBlock(
            m_codeOriginForExitProfile, profiledCodeBlock);
    if (sourceProfiledCodeBlock) {
        FrequentExitSite site;
        if (m_wasHoisted)
            site = FrequentExitSite(HoistingFailed, jitType);
        else
            site = FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind, jitType);
        sourceProfiledCodeBlock->addFrequentExitSite(site);
    }
}
예제 #3
0
bool OSRExit::considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock)
{
    if (static_cast<double>(m_count) / dfgCodeBlock->osrExitCounter() <= Options::osrExitProminenceForFrequentExitSite())
        return false;
    
    FrequentExitSite exitSite;
    
    if (m_kind == ArgumentsEscaped) {
        // Count this one globally. It doesn't matter where in the code block the arguments excaped;
        // the fact that they did is not associated with any particular instruction.
        exitSite = FrequentExitSite(m_kind);
    } else
        exitSite = FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind);
    
    return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOrigin, profiledCodeBlock)->addFrequentExitSite(exitSite);
}
예제 #4
0
void OSRExitBase::considerAddingAsFrequentExitSiteSlow(CodeBlock* profiledCodeBlock, ExitingJITType jitType)
{
    CodeBlock* sourceProfiledCodeBlock =
        baselineCodeBlockForOriginAndBaselineCodeBlock(
            m_codeOriginForExitProfile, profiledCodeBlock);
    if (sourceProfiledCodeBlock)
        sourceProfiledCodeBlock->addFrequentExitSite(FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind, jitType));
}
bool OSRExitBase::considerAddingAsFrequentExitSiteSlow(CodeBlock* profiledCodeBlock)
{
    CodeBlock* sourceProfiledCodeBlock =
        baselineCodeBlockForOriginAndBaselineCodeBlock(
            m_codeOriginForExitProfile, profiledCodeBlock);
    if (!sourceProfiledCodeBlock)
        return false;
    return sourceProfiledCodeBlock->addFrequentExitSite(
            FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind));
}
예제 #6
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;
    }
예제 #7
0
bool OSRExit::considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock)
{
    if (static_cast<double>(m_count) / dfgCodeBlock->speculativeFailCounter() <= Options::osrExitProminenceForFrequentExitSite)
        return false;
    
    return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOrigin, profiledCodeBlock)->addFrequentExitSite(FrequentExitSite(m_codeOrigin.bytecodeIndex, m_kind));
}