2008-05-09 Kevin McCullough <kmccullough@apple.com>
[WebKit-https.git] / JavaScriptCore / profiler / Profiler.cpp
index 1b9bc82..c752070 100644 (file)
 #include "config.h"
 #include "Profiler.h"
 
-#include "FunctionCallProfile.h"
-#include "JSGlobalObject.h"
 #include "ExecState.h"
 #include "function.h"
+#include "FunctionCallProfile.h"
+#include "JSGlobalObject.h"
+#include "Profile.h"
 
 #include <stdio.h>
 
@@ -53,23 +54,26 @@ Profiler* Profiler::profiler()
     return sharedProfiler;
 }
 
-void Profiler::startProfiling(unsigned pageGroupIdentifier)
+void Profiler::startProfiling(unsigned pageGroupIdentifier, const UString& title)
 {
     if (m_profiling)
         return;
 
     m_pageGroupIdentifier = pageGroupIdentifier;
 
-    // FIXME: When multi-threading is supported this will be a vector and calls
-    // into the profiler will need to know which thread it is executing on.
-    m_callTree.set(new FunctionCallProfile("Thread_1"));
+    m_currentProfile.set(new Profile(title));
     m_profiling = true;
 }
 
 void Profiler::stopProfiling()
 {
     m_profiling = false;
-    m_callTree->stopProfiling();
+
+    if (!m_currentProfile)
+        return;
+
+    m_currentProfile->stopProfiling();
+    m_allProfiles.append(m_currentProfile.release());
 }
 
 void Profiler::willExecute(ExecState* exec, JSObject* calledFunction)
@@ -79,7 +83,7 @@ void Profiler::willExecute(ExecState* exec, JSObject* calledFunction)
 
     Vector<UString> callStackNames;
     getStackNames(callStackNames, exec, calledFunction);
-    insertStackNamesInTree(callStackNames);
+    m_currentProfile->willExecute(callStackNames);
 }
 
 void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
@@ -89,7 +93,7 @@ void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int starti
 
     Vector<UString> callStackNames;
     getStackNames(callStackNames, exec, sourceURL, startingLineNumber);
-    insertStackNamesInTree(callStackNames);
+    m_currentProfile->willExecute(callStackNames);
 }
 
 void Profiler::didExecute(ExecState* exec, JSObject* calledFunction)
@@ -99,7 +103,7 @@ void Profiler::didExecute(ExecState* exec, JSObject* calledFunction)
 
     Vector<UString> callStackNames;
     getStackNames(callStackNames, exec, calledFunction);
-    m_callTree->didExecute(callStackNames, 0);
+    m_currentProfile->didExecute(callStackNames);
 }
 
 void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
@@ -109,30 +113,7 @@ void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startin
 
     Vector<UString> callStackNames;
     getStackNames(callStackNames, exec, sourceURL, startingLineNumber);
-    m_callTree->didExecute(callStackNames, 0);
-}
-
-void Profiler::insertStackNamesInTree(const Vector<UString>& callStackNames)
-{
-    FunctionCallProfile* callTreeInsertionPoint = 0;
-    FunctionCallProfile* foundNameInTree = m_callTree.get();
-    NameIterator callStackLocation = callStackNames.begin();
-
-    while (callStackLocation != callStackNames.end() && foundNameInTree) {
-        callTreeInsertionPoint = foundNameInTree;
-        foundNameInTree = callTreeInsertionPoint->findChild(*callStackLocation);
-        ++callStackLocation;
-    }
-
-    if (!foundNameInTree) {   // Insert remains of the stack into the call tree.
-        --callStackLocation;
-        for (FunctionCallProfile* next; callStackLocation != callStackNames.end(); ++callStackLocation) {
-            next = new FunctionCallProfile(*callStackLocation);
-            callTreeInsertionPoint->addChild(next);
-            callTreeInsertionPoint = next;
-        }
-    } else    // We are calling a function that is already in the call tree.
-        foundNameInTree->willExecute();
+    m_currentProfile->didExecute(callStackNames);
 }
 
 void getStackNames(Vector<UString>& names, ExecState* exec)
@@ -171,36 +152,14 @@ UString getFunctionName(FunctionImp* functionImp)
     return (name.isEmpty() ? "[anonymous function]" : name) + " " + URL + ": " + UString::from(lineNumber);
 }
 
-void Profiler::printDataInspectorStyle() const
-{
-    printf("Profiler Call graph:\n");
-    m_callTree->printDataInspectorStyle(0);
-}
-
-typedef pair<UString::Rep*, unsigned> NameCountPair;
-
-static inline bool functionNameCountPairComparator(const NameCountPair a, const NameCountPair b)
+void Profiler::printDataInspectorStyle(unsigned whichProfile) const
 {
-    return a.second > b.second;
+    m_allProfiles[whichProfile]->printDataInspectorStyle();
 }
 
-void Profiler::printDataSampleStyle() const
+void Profiler::printDataSampleStyle(unsigned whichProfile) const
 {
-    typedef Vector<NameCountPair> NameCountPairVector;
-
-    FunctionCallHashCount countedFunctions;
-    printf("Call graph:\n");
-    m_callTree->printDataSampleStyle(0, countedFunctions);
-
-    printf("\nTotal number in stack:\n");
-    NameCountPairVector sortedFunctions(countedFunctions.size());
-    copyToVector(countedFunctions, sortedFunctions);
-
-    std::sort(sortedFunctions.begin(), sortedFunctions.end(), functionNameCountPairComparator);
-    for (NameCountPairVector::iterator it = sortedFunctions.begin(); it != sortedFunctions.end(); ++it)
-        printf("        %-12d%s\n", (*it).second, UString((*it).first).UTF8String().c_str());
-
-    printf("\nSort by top of stack, same collapsed (when >= 5):\n");
+    m_allProfiles[whichProfile]->printDataSampleStyle();
 }
 
 void Profiler::debugLog(UString message)