Rationalize exit site profiling for calls
https://bugs.webkit.org/show_bug.cgi?id=106150

Reviewed by Sam Weinig.
        
This adds two new exit kinds for calls: BadFunction and BadExecutable. The latter is not used
yet, but is already integrated with profiling. CheckFunction uses a BadFunction speculation
instead of BadCache, now. This allows CallLinkStatus to turn itself into a closure call status
if we had a BadFunction exit site but the CallLinkInfo told us to use a non-closure call. This
might happen if we had call unlinking that led to information loss along the way.
        
No performance impact. This is meant as another step towards inlining closure calls.

* bytecode/CallLinkStatus.cpp:
* bytecode/CallLinkStatus.h:
(JSC::CallLinkStatus::setIsProved):
(JSC::CallLinkStatus::setHasBadFunctionExitSite):
(CallLinkStatus):
(JSC::CallLinkStatus::setHasBadCacheExitSite):
(JSC::CallLinkStatus::setHasBadExecutableExitSite):
* bytecode/ExitKind.cpp:
(JSC::exitKindToString):
* bytecode/ExitKind.h:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleCall):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@138871 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/bytecode/CallLinkStatus.h b/Source/JavaScriptCore/bytecode/CallLinkStatus.h
index 071aa1db..ef1bcb4 100644
--- a/Source/JavaScriptCore/bytecode/CallLinkStatus.h
+++ b/Source/JavaScriptCore/bytecode/CallLinkStatus.h
@@ -65,10 +65,40 @@
     {
     }
     
-    CallLinkStatus& setIsProved(bool);
+    CallLinkStatus& setIsProved(bool isProved)
+    {
+        m_isProved = isProved;
+        return *this;
+    }
     
     static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex);
     
+    CallLinkStatus& setHasBadFunctionExitSite(bool didHaveExitSite)
+    {
+        ASSERT(!m_isProved);
+        if (didHaveExitSite) {
+            // Turn this into a closure call.
+            m_callTarget = JSValue();
+        }
+        return *this;
+    }
+    
+    CallLinkStatus& setHasBadCacheExitSite(bool didHaveExitSite)
+    {
+        ASSERT(!m_isProved);
+        if (didHaveExitSite)
+            *this = takesSlowPath();
+        return *this;
+    }
+    
+    CallLinkStatus& setHasBadExecutableExitSite(bool didHaveExitSite)
+    {
+        ASSERT(!m_isProved);
+        if (didHaveExitSite)
+            *this = takesSlowPath();
+        return *this;
+    }
+    
     bool isSet() const { return m_callTarget || m_executable || m_couldTakeSlowPath; }
     
     bool operator!() const { return !isSet(); }