void CallLinkStatus::computeDFGStatuses( CodeBlock* dfgCodeBlock, CallLinkStatus::ContextMap& map) { #if ENABLE(DFG_JIT) RELEASE_ASSERT(dfgCodeBlock->jitType() == JITCode::DFGJIT); CodeBlock* baselineCodeBlock = dfgCodeBlock->alternative(); for (auto iter = dfgCodeBlock->callLinkInfosBegin(); !!iter; ++iter) { CallLinkInfo& info = **iter; CodeOrigin codeOrigin = info.codeOrigin; bool takeSlowPath; bool badFunction; // Check if we had already previously made a terrible mistake in the FTL for this // code origin. Note that this is approximate because we could have a monovariant // inline in the FTL that ended up failing. We should fix that at some point by // having data structures to track the context of frequent exits. This is currently // challenging because it would require creating a CodeOrigin-based database in // baseline CodeBlocks, but those CodeBlocks don't really have a place to put the // InlineCallFrames. CodeBlock* currentBaseline = baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, baselineCodeBlock); { ConcurrentJITLocker locker(currentBaseline->m_lock); takeSlowPath = currentBaseline->hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadCache, ExitFromFTL)) || currentBaseline->hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadCacheWatchpoint, ExitFromFTL)) || currentBaseline->hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadExecutable, ExitFromFTL)); badFunction = currentBaseline->hasExitSite(locker, DFG::FrequentExitSite(codeOrigin.bytecodeIndex, BadFunction, ExitFromFTL)); } { ConcurrentJITLocker locker(dfgCodeBlock->m_lock); if (takeSlowPath) map.add(info.codeOrigin, takesSlowPath()); else { CallLinkStatus status = computeFor(locker, info); if (status.isSet()) { if (badFunction) status.makeClosureCall(); map.add(info.codeOrigin, status); } } } } #else UNUSED_PARAM(dfgCodeBlock); #endif // ENABLE(DFG_JIT) if (verbose) { dataLog("Context map:\n"); ContextMap::iterator iter = map.begin(); ContextMap::iterator end = map.end(); for (; iter != end; ++iter) { dataLog(" ", iter->key, ":\n"); dataLog(" ", iter->value, "\n"); } } }
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)); }
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 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 CallLinkStatus::computeDFGStatuses( CodeBlock* dfgCodeBlock, CallLinkStatus::ContextMap& map) { #if ENABLE(DFG_JIT) RELEASE_ASSERT(dfgCodeBlock->jitType() == JITCode::DFGJIT); CodeBlock* baselineCodeBlock = dfgCodeBlock->alternative(); for (auto iter = dfgCodeBlock->callLinkInfosBegin(); !!iter; ++iter) { CallLinkInfo& info = **iter; CodeOrigin codeOrigin = info.codeOrigin(); // Check if we had already previously made a terrible mistake in the FTL for this // code origin. Note that this is approximate because we could have a monovariant // inline in the FTL that ended up failing. We should fix that at some point by // having data structures to track the context of frequent exits. This is currently // challenging because it would require creating a CodeOrigin-based database in // baseline CodeBlocks, but those CodeBlocks don't really have a place to put the // InlineCallFrames. CodeBlock* currentBaseline = baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, baselineCodeBlock); ExitSiteData exitSiteData; { ConcurrentJITLocker locker(currentBaseline->m_lock); exitSiteData = computeExitSiteData( locker, currentBaseline, codeOrigin.bytecodeIndex); } { ConcurrentJITLocker locker(dfgCodeBlock->m_lock); map.add(info.codeOrigin(), computeFor(locker, dfgCodeBlock, info, exitSiteData)); } } #else UNUSED_PARAM(dfgCodeBlock); #endif // ENABLE(DFG_JIT) if (verbose) { dataLog("Context map:\n"); ContextMap::iterator iter = map.begin(); ContextMap::iterator end = map.end(); for (; iter != end; ++iter) { dataLog(" ", iter->key, ":\n"); dataLog(" ", iter->value, "\n"); } } }
void ProfiledCodeBlockJettisoningWatchpoint::fireInternal() { if (DFG::shouldShowDisassembly()) { dataLog( "Firing profiled watchpoint ", RawPointer(this), " on ", *m_codeBlock, " due to ", m_exitKind, " at ", m_codeOrigin, "\n"); } baselineCodeBlockForOriginAndBaselineCodeBlock( m_codeOrigin, m_codeBlock->baselineVersion())->addFrequentExitSite( DFG::FrequentExitSite(m_codeOrigin.bytecodeIndex, m_exitKind)); #if ENABLE(JIT) m_codeBlock->jettison(CountReoptimization); #endif if (isOnList()) remove(); }