2008-04-18 Kevin McCullough <kmccullough@apple.com>
authorkmccullough@apple.com <kmccullough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Apr 2008 21:49:56 +0000 (21:49 +0000)
committerkmccullough@apple.com <kmccullough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Apr 2008 21:49:56 +0000 (21:49 +0000)
        Reviewed by Sam and Adam.

        -<rdar://problem/5770054> JavaScript profiler (10928)
        - Cleaned up the header file and made some functions static, added
        a new, sane, printing function, and fixed a few minor bugs.

        * JavaScriptCore.exp:
        * JavaScriptCore.xcodeproj/project.pbxproj:
        * profiler/FunctionCallProfile.cpp:
        (KJS::FunctionCallProfile::didExecute): Removed assertion that time is
        > 0 because at ms resolution that may not be true and only cross-
        platform way to get time differences is in ms.
        (KJS::FunctionCallProfile::printDataInspectorStyle): Added a new
        printing function for dumping data in a sane style.
        (KJS::FunctionCallProfile::printDataSampleStyle): Fixed a bug where we
        displayed too much precision when printing our floats. Also added logic
        to make sure we don't display 0 because that doesn't make sense for a
        sampling profile.
        * profiler/FunctionCallProfile.h:
        * profiler/Profiler.cpp: Moved functions that could be static into the
        implementation, and chaned the ASSERTs to early returns.  I did this
        because console.profile() is a JS function and so was being profiled
        but asserting because the profiler had not been started! In the future
        I would like to put the ASSERTs back and not profile the calls to
        console.profile() and console.profileEnd().
        (KJS::Profiler::willExecute):
        (KJS::Profiler::didExecute):
        (KJS::getStackNames): Fixed a bug where the wrong ExecState was being
        used.
        (KJS::getFunctionName):
        (KJS::Profiler::printDataInspectorStyle):
        * profiler/Profiler.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@32228 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/profiler/FunctionCallProfile.cpp
JavaScriptCore/profiler/FunctionCallProfile.h
JavaScriptCore/profiler/Profiler.cpp
JavaScriptCore/profiler/Profiler.h

index 48fe856..f548905 100644 (file)
@@ -1,3 +1,38 @@
+2008-04-18  Kevin McCullough  <kmccullough@apple.com>
+
+        Reviewed by Sam and Adam.
+
+        -<rdar://problem/5770054> JavaScript profiler (10928)
+        - Cleaned up the header file and made some functions static, added
+        a new, sane, printing function, and fixed a few minor bugs.
+
+        * JavaScriptCore.exp:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * profiler/FunctionCallProfile.cpp:
+        (KJS::FunctionCallProfile::didExecute): Removed assertion that time is
+        > 0 because at ms resolution that may not be true and only cross-
+        platform way to get time differences is in ms.
+        (KJS::FunctionCallProfile::printDataInspectorStyle): Added a new
+        printing function for dumping data in a sane style.
+        (KJS::FunctionCallProfile::printDataSampleStyle): Fixed a bug where we
+        displayed too much precision when printing our floats. Also added logic
+        to make sure we don't display 0 because that doesn't make sense for a
+        sampling profile.
+        * profiler/FunctionCallProfile.h:
+        * profiler/Profiler.cpp: Moved functions that could be static into the
+        implementation, and chaned the ASSERTs to early returns.  I did this
+        because console.profile() is a JS function and so was being profiled
+        but asserting because the profiler had not been started! In the future
+        I would like to put the ASSERTs back and not profile the calls to
+        console.profile() and console.profileEnd().
+        (KJS::Profiler::willExecute):
+        (KJS::Profiler::didExecute):
+        (KJS::getStackNames): Fixed a bug where the wrong ExecState was being
+        used.
+        (KJS::getFunctionName):
+        (KJS::Profiler::printDataInspectorStyle):
+        * profiler/Profiler.h:
+
 2008-04-18  Alexey Proskuryakov  <ap@webkit.org>
 
         Reviewed by Darin.
index b10484f..74e0a58 100644 (file)
@@ -194,6 +194,9 @@ __ZN3KJS8JSObject9putDirectERKNS_10IdentifierEPNS_7JSValueEi
 __ZN3KJS8JSObject9putDirectERKNS_10IdentifierEii
 __ZN3KJS8jsStringEPKc
 __ZN3KJS8jsStringERKNS_7UStringE
+__ZN3KJS8Profiler13stopProfilingEv
+__ZN3KJS8Profiler14startProfilingEv
+__ZN3KJS8Profiler8profilerEv
 __ZN3KJS9Collector15recordExtraCostEm
 __ZN3KJS9Collector17globalObjectCountEv
 __ZN3KJS9Collector20protectedObjectCountEv
@@ -282,6 +285,8 @@ __ZNK3KJS8JSObject8toStringEPNS_9ExecStateE
 __ZNK3KJS8JSObject9classInfoEv
 __ZNK3KJS8JSObject9classNameEv
 __ZNK3KJS8JSObject9toBooleanEPNS_9ExecStateE
+__ZNK3KJS8Profiler20printDataSampleStyleEv
+__ZNK3KJS8Profiler23printDataInspectorStyleEv
 __ZNK3KJS9ExecState19lexicalGlobalObjectEv
 __ZNK3KJS9HashTable11createTableEv
 __ZNK3WTF8Collator7collateEPKtmS2_m
index c3ef850..c154050 100644 (file)
                93E26BFE08B151D400F85226 /* ucpinternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 93E26BFC08B151D400F85226 /* ucpinternal.h */; };
                93F0B3AC09BB4DC00068FCE3 /* Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F0B3AA09BB4DC00068FCE3 /* Parser.h */; settings = {ATTRIBUTES = (Private, ); }; };
                95AB83420DA4322500BC83F3 /* Profiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95AB832E0DA42CAD00BC83F3 /* Profiler.cpp */; };
-               95AB83480DA432EB00BC83F3 /* Profiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 95AB832F0DA42CAD00BC83F3 /* Profiler.h */; };
+               95AB83480DA432EB00BC83F3 /* Profiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 95AB832F0DA42CAD00BC83F3 /* Profiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                95AB83560DA43C3000BC83F3 /* FunctionCallProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95AB83540DA43B4400BC83F3 /* FunctionCallProfile.cpp */; };
-               95AB83570DA43C3000BC83F3 /* FunctionCallProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 95AB83550DA43B4400BC83F3 /* FunctionCallProfile.h */; };
+               95AB83570DA43C3000BC83F3 /* FunctionCallProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 95AB83550DA43B4400BC83F3 /* FunctionCallProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
                95C18D490C90E82600E72F73 /* JSRetainPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 95C18D3E0C90E7EF00E72F73 /* JSRetainPtr.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A8E894320CD0602400367179 /* JSCallbackObjectFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */; };
                A8E894340CD0603F00367179 /* JSGlobalObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A8E894330CD0603F00367179 /* JSGlobalObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
index ec15739..034a587 100644 (file)
@@ -61,7 +61,7 @@ void FunctionCallProfile::didExecute(Vector<UString> stackNames, unsigned int st
 
         m_timeSum += getCurrentUTCTime() - m_startTime;
 
-        ASSERT(m_timeSum > 0);
+        // FIXME: We may need something with higher resolution than ms as some functions will take 0ms.
         return;
     }
 
@@ -96,8 +96,26 @@ FunctionCallProfile* FunctionCallProfile::findChild(const UString& name)
     return 0;
 }
 
+void FunctionCallProfile::printDataInspectorStyle(int indentLevel) const
+{
+    // Print function names
+    if (indentLevel) {
+        for (int i = 0; i < indentLevel; ++i)
+            printf("  ");
+
+        printf("%.0fms %s\n", m_timeSum, m_functionName.UTF8String().c_str());
+    } else
+        printf("%s\n", m_functionName.UTF8String().c_str());
+
+    ++indentLevel;
+
+    // Print children's names and information
+    for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
+        (*currentChild)->printDataInspectorStyle(indentLevel);
+}
+
 // print the profiled data in a format that matches the tool sample's output.
-double FunctionCallProfile::printDataSampleStyle(int indentLevel)
+double FunctionCallProfile::printDataSampleStyle(int indentLevel) const
 {
     printf("    ");
 
@@ -107,7 +125,7 @@ double FunctionCallProfile::printDataSampleStyle(int indentLevel)
             printf("  ");
 
         // We've previously asserted that m_timeSum will always be >= 1
-        printf("%f %s\n", m_timeSum, m_functionName.UTF8String().c_str());
+        printf("%.0f %s\n", m_timeSum ? m_timeSum : 1, m_functionName.UTF8String().c_str());
     } else
         printf("%s\n", m_functionName.UTF8String().c_str());
 
index e95cfa7..c3ae367 100644 (file)
@@ -51,7 +51,8 @@ namespace KJS {
         UString functionName() const { return m_functionName; }
         double microSecs() const { return m_timeSum; }
 
-        double printDataSampleStyle(int indentLevel);
+        void printDataInspectorStyle(int indentLevel) const;
+        double printDataSampleStyle(int indentLevel) const;
 
     private:
         UString m_functionName;
index 20b4a3c..96dfa05 100644 (file)
@@ -40,6 +40,11 @@ namespace KJS {
 static Profiler* sharedProfiler = 0;
 static const char* Script = "[SCRIPT] ";
 
+static void getStackNames(Vector<UString>&, ExecState*);
+static void getStackNames(Vector<UString>&, ExecState*, JSObject*);
+static void getStackNames(Vector<UString>&, ExecState*, const UString& sourceURL, int startingLineNumber);
+static UString getFunctionName(FunctionImp*);
+
 Profiler* Profiler::profiler()
 {
     if (!sharedProfiler)
@@ -65,7 +70,8 @@ void Profiler::stopProfiling()
 
 void Profiler::willExecute(ExecState* exec, JSObject* calledFunction)
 {
-    ASSERT(m_profiling);
+    if (!m_profiling)
+        return;
 
     Vector<UString> callStackNames;
     getStackNames(callStackNames, exec, calledFunction);
@@ -74,7 +80,8 @@ void Profiler::willExecute(ExecState* exec, JSObject* calledFunction)
 
 void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
 {
-    ASSERT(m_profiling);
+    if (!m_profiling)
+        return;
 
     Vector<UString> callStackNames;
     getStackNames(callStackNames, exec, sourceURL, startingLineNumber);
@@ -83,7 +90,8 @@ void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int starti
 
 void Profiler::didExecute(ExecState* exec, JSObject* calledFunction)
 {
-    ASSERT(m_profiling);
+    if (!m_profiling)
+        return;
 
     Vector<UString> callStackNames;
     getStackNames(callStackNames, exec, calledFunction);
@@ -92,7 +100,8 @@ void Profiler::didExecute(ExecState* exec, JSObject* calledFunction)
 
 void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
 {
-    ASSERT(m_profiling);
+    if (!m_profiling)
+        return;
 
     Vector<UString> callStackNames;
     getStackNames(callStackNames, exec, sourceURL, startingLineNumber);
@@ -122,21 +131,20 @@ void Profiler::insertStackNamesInTree(const Vector<UString>& callStackNames)
         foundNameInTree->willExecute();
 }
 
-void Profiler::getStackNames(Vector<UString>& names, ExecState* exec) const
+void getStackNames(Vector<UString>& names, ExecState* exec)
 {
-    UString currentName;
     for (ExecState* currentState = exec; currentState; currentState = currentState->callingExecState()) {
-        if (FunctionImp* functionImp = exec->function())
+
+        if (FunctionImp* functionImp = currentState->function())
             names.prepend(getFunctionName(functionImp));
-        else if (ScopeNode* scopeNode = exec->scopeNode())
+        else if (ScopeNode* scopeNode = currentState->scopeNode())
             names.prepend(Script + scopeNode->sourceURL() + ": " + UString::from(scopeNode->lineNo() + 1));   // FIXME: Why is the line number always off by one?
     }
 }
 
-void Profiler::getStackNames(Vector<UString>& names, ExecState* exec, JSObject* calledFunction) const
+void getStackNames(Vector<UString>& names, ExecState* exec, JSObject* calledFunction)
 {
     getStackNames(names, exec);
-
     if (calledFunction->inherits(&FunctionImp::info))
         names.append(getFunctionName(static_cast<FunctionImp*>(calledFunction)));
     else if (calledFunction->inherits(&InternalFunctionImp::info))
@@ -144,13 +152,13 @@ void Profiler::getStackNames(Vector<UString>& names, ExecState* exec, JSObject*
 }
 
 
-void Profiler::getStackNames(Vector<UString>& names, ExecState* exec, const UString& sourceURL, int startingLineNumber) const
+void getStackNames(Vector<UString>& names, ExecState* exec, const UString& sourceURL, int startingLineNumber)
 {
     getStackNames(names, exec);
     names.append(Script + sourceURL + ": " + UString::from(startingLineNumber + 1));
 }
 
-UString Profiler::getFunctionName(FunctionImp* functionImp) const
+UString getFunctionName(FunctionImp* functionImp)
 {
     UString name = functionImp->functionName().ustring();
     int lineNumber = functionImp->body->lineNo();
@@ -159,6 +167,12 @@ UString Profiler::getFunctionName(FunctionImp* functionImp) const
     return (name.isEmpty() ? "[anonymous function]" : name) + " " + URL + ": " + UString::from(lineNumber);
 }
 
+void Profiler::printDataInspectorStyle() const
+{
+    printf("Profiler Call graph:\n");
+    m_callTree->printDataInspectorStyle(0);
+}
+
 void Profiler::printDataSampleStyle() const
 {
     printf("Call graph:\n");
index ae7e342..0b23185 100644 (file)
@@ -51,7 +51,8 @@ namespace KJS {
         void willExecute(ExecState*, const UString& sourceURL, int startingLineNumber);
         void didExecute(ExecState*, JSObject* calledFunction);
         void didExecute(ExecState*, const UString& sourceURL, int startingLineNumber);
-        
+
+        void printDataInspectorStyle() const;
         void printDataSampleStyle() const;
 
     private:
@@ -60,15 +61,10 @@ namespace KJS {
         {
         }
 
-        void getStackNames(Vector<UString>&, ExecState*) const;
-        void getStackNames(Vector<UString>&, ExecState*, JSObject*) const;
-        void getStackNames(Vector<UString>&, ExecState*, const UString& sourceURL, int startingLineNumber) const;
-
         void insertStackNamesInTree(const Vector<UString>& callStackNames);
 
-        UString getFunctionName(FunctionImp*) const;
-
         bool m_profiling;
+
         // FIXME: Make this a vector of FunctionCallProfiles where each one is the
         // root of a new thread.
         OwnPtr<FunctionCallProfile> m_callTree;