]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - profiler/Profiler.cpp
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / profiler / Profiler.cpp
index fe8727a4bf3b9f29029c5c156fd6b5e95d144db6..bcaaaacbf217b08425f4327ca8bd37bf23a14a26 100644 (file)
 #include "CommonIdentifiers.h"
 #include "CallFrame.h"
 #include "CodeBlock.h"
+#include "InternalFunction.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "Nodes.h"
 #include "Profile.h"
 #include "ProfileGenerator.h"
 #include "ProfileNode.h"
+#include "UStringConcatenate.h"
 #include <stdio.h>
 
 namespace JSC {
@@ -64,25 +66,25 @@ void Profiler::startProfiling(ExecState* exec, const UString& title)
 
     // Check if we currently have a Profile for this global ExecState and title.
     // If so return early and don't create a new Profile.
-    ExecState* globalExec = exec ? exec->lexicalGlobalObject()->globalExec() : 0;
+    JSGlobalObject* origin = exec ? exec->lexicalGlobalObject() : 0;
 
     for (size_t i = 0; i < m_currentProfiles.size(); ++i) {
         ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
-        if (profileGenerator->originatingGlobalExec() == globalExec && profileGenerator->title() == title)
+        if (profileGenerator->origin() == origin && profileGenerator->title() == title)
             return;
     }
 
     s_sharedEnabledProfilerReference = this;
-    RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(title, exec, ++ProfilesUID);
+    RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID);
     m_currentProfiles.append(profileGenerator);
 }
 
 PassRefPtr<Profile> Profiler::stopProfiling(ExecState* exec, const UString& title)
 {
-    ExecState* globalExec = exec ? exec->lexicalGlobalObject()->globalExec() : 0;
+    JSGlobalObject* origin = exec ? exec->lexicalGlobalObject() : 0;
     for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) {
         ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
-        if (profileGenerator->originatingGlobalExec() == globalExec && (title.isNull() || profileGenerator->title() == title)) {
+        if (profileGenerator->origin() == origin && (title.isNull() || profileGenerator->title() == title)) {
             profileGenerator->stopProfiling();
             RefPtr<Profile> returnProfile = profileGenerator->profile();
 
@@ -97,42 +99,62 @@ PassRefPtr<Profile> Profiler::stopProfiling(ExecState* exec, const UString& titl
     return 0;
 }
 
-static inline void dispatchFunctionToProfiles(const Vector<RefPtr<ProfileGenerator> >& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup)
+void Profiler::stopProfiling(JSGlobalObject* origin)
+{
+    for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) {
+        ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
+        if (profileGenerator->origin() == origin) {
+            profileGenerator->stopProfiling();
+            m_currentProfiles.remove(i);
+            if (!m_currentProfiles.size())
+                s_sharedEnabledProfilerReference = 0;
+        }
+    }
+}
+
+static inline void dispatchFunctionToProfiles(ExecState* callerOrHandlerCallFrame, const Vector<RefPtr<ProfileGenerator> >& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup)
 {
     for (size_t i = 0; i < profiles.size(); ++i) {
-        if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->originatingGlobalExec())
-            (profiles[i].get()->*function)(callIdentifier);
+        if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->origin())
+            (profiles[i].get()->*function)(callerOrHandlerCallFrame, callIdentifier);
     }
 }
 
-void Profiler::willExecute(ExecState* exec, JSValue function)
+void Profiler::willExecute(ExecState* callerCallFrame, JSValue function)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(callerCallFrame, function, "", 0), callerCallFrame->lexicalGlobalObject()->profileGroup());
 }
 
-void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
+void Profiler::willExecute(ExecState* callerCallFrame, const UString& sourceURL, int startingLineNumber)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    CallIdentifier callIdentifier = createCallIdentifier(exec, JSValue(), sourceURL, startingLineNumber);
+    CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber);
+
+    dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, callerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+void Profiler::didExecute(ExecState* callerCallFrame, JSValue function)
+{
+    ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(callerCallFrame, function, "", 0), callerCallFrame->lexicalGlobalObject()->profileGroup());
 }
 
-void Profiler::didExecute(ExecState* exec, JSValue function)
+void Profiler::didExecute(ExecState* callerCallFrame, const UString& sourceURL, int startingLineNumber)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber), callerCallFrame->lexicalGlobalObject()->profileGroup());
 }
 
-void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
+void Profiler::exceptionUnwind(ExecState* handlerCallFrame)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, JSValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(handlerCallFrame, m_currentProfiles, &ProfileGenerator::exceptionUnwind, createCallIdentifier(handlerCallFrame, JSValue(), "", 0), handlerCallFrame->lexicalGlobalObject()->profileGroup());
 }
 
 CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const UString& defaultSourceURL, int defaultLineNumber)
@@ -141,14 +163,16 @@ CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionV
         return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber);
     if (!functionValue.isObject())
         return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber);
-    if (asObject(functionValue)->inherits(&JSFunction::info)) {
+    if (asObject(functionValue)->inherits(&JSFunction::s_info)) {
         JSFunction* function = asFunction(functionValue);
         if (!function->executable()->isHostFunction())
             return createCallIdentifierFromFunctionImp(exec, function);
     }
-    if (asObject(functionValue)->inherits(&InternalFunction::info))
+    if (asObject(functionValue)->inherits(&JSFunction::s_info))
+        return CallIdentifier(static_cast<JSFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber);
+    if (asObject(functionValue)->inherits(&InternalFunction::s_info))
         return CallIdentifier(static_cast<InternalFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber);
-    return CallIdentifier(makeString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber);
+    return CallIdentifier(makeUString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber);
 }
 
 CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSFunction* function)