+
+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");
+ }
+ }
+}
+
+CallLinkStatus CallLinkStatus::computeFor(
+ CodeBlock* profiledBlock, CodeOrigin codeOrigin,
+ const CallLinkInfoMap& baselineMap, const CallLinkStatus::ContextMap& dfgMap)
+{
+ auto iter = dfgMap.find(codeOrigin);
+ if (iter != dfgMap.end())
+ return iter->value;
+
+ return computeFor(profiledBlock, codeOrigin.bytecodeIndex, baselineMap);