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); }
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); } }
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); }
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)); }
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; }
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)); }