2008-05-22 Kevin McCullough <kmccullough@apple.com>
authorkmccullough@apple.com <kmccullough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 May 2008 22:09:43 +0000 (22:09 +0000)
committerkmccullough@apple.com <kmccullough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 May 2008 22:09:43 +0000 (22:09 +0000)
        Reviewed by Sam.

        <rdar://problem/5951561> Turn on JavaScript Profiler
        Get basic JS profiling working.
        Even with this patch the profiler will not be compiled in because we do
        not know the extend, if any, of the performance regression it would cause
        when it is not in use. However with these changes, if the profiler were
        on, it would not crash and show good profiling data.

        * VM/Machine.cpp: Instrument the calls sites that are needed for profiling.
        (KJS::callEval):
        (KJS::Machine::unwindCallFrame):
        (KJS::Machine::execute):
        (KJS::Machine::privateExecute):
        * kjs/function.cpp: Ditto.
        (KJS::globalFuncEval):
        * kjs/interpreter.cpp: Ditto.
        (KJS::Interpreter::evaluate):
        * profiler/Profile.cpp:
        (KJS::Profile::willExecute):
        (KJS::Profile::didExecute): Because we do not get a good context when
        startProfiling is called it is possible that m_currentNode will be at the
        top of the known stack when a didExecute() is called.  What we then do is
        create a new node that represents the function being exited and insert
        it between the head and the currently known children, since they should
        be children of this new node.
        * profiler/ProfileNode.cpp:
        (KJS::ProfileNode::ProfileNode):
        (KJS::ProfileNode::willExecute): Rename the add function for consistency.
        (KJS::ProfileNode::addChild): Appends the child to this node but also
        sets the parent pointer of the children to this node.
        (KJS::ProfileNode::insertNode): Insert a node between this node and its
        children.  Also set the time for the new node since it is now exiting
        and we don't really know when it started.
        (KJS::ProfileNode::stopProfiling):
        (KJS::ProfileNode::startTimer):
        * profiler/ProfileNode.h:
        (KJS::CallIdentifier::toString): Added for debugging.
        (KJS::ProfileNode::setParent):
        (KJS::ProfileNode::setSelfTime): Fixed an old bug where we set the
        visibleTotalTime not the visibleSelfTime.
        (KJS::ProfileNode::children):
        (KJS::ProfileNode::toString): Added for debugging.
        * profiler/Profiler.cpp: remove unecessary calls.
        (KJS::Profiler::startProfiling):

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

JavaScriptCore/ChangeLog
JavaScriptCore/VM/Machine.cpp
JavaScriptCore/kjs/function.cpp
JavaScriptCore/kjs/interpreter.cpp
JavaScriptCore/profiler/Profile.cpp
JavaScriptCore/profiler/ProfileNode.cpp
JavaScriptCore/profiler/ProfileNode.h
JavaScriptCore/profiler/Profiler.cpp

index 0f21ec5..28a2df4 100644 (file)
@@ -1,3 +1,51 @@
+2008-05-22  Kevin McCullough  <kmccullough@apple.com>
+
+        Reviewed by Sam.
+
+        <rdar://problem/5951561> Turn on JavaScript Profiler
+        Get basic JS profiling working.
+        Even with this patch the profiler will not be compiled in because we do
+        not know the extend, if any, of the performance regression it would cause
+        when it is not in use. However with these changes, if the profiler were
+        on, it would not crash and show good profiling data.
+
+        * VM/Machine.cpp: Instrument the calls sites that are needed for profiling.
+        (KJS::callEval):
+        (KJS::Machine::unwindCallFrame):
+        (KJS::Machine::execute):
+        (KJS::Machine::privateExecute):
+        * kjs/function.cpp: Ditto.
+        (KJS::globalFuncEval):
+        * kjs/interpreter.cpp: Ditto.
+        (KJS::Interpreter::evaluate):
+        * profiler/Profile.cpp: 
+        (KJS::Profile::willExecute):
+        (KJS::Profile::didExecute): Because we do not get a good context when
+        startProfiling is called it is possible that m_currentNode will be at the
+        top of the known stack when a didExecute() is called.  What we then do is
+        create a new node that represents the function being exited and insert
+        it between the head and the currently known children, since they should
+        be children of this new node.
+        * profiler/ProfileNode.cpp:
+        (KJS::ProfileNode::ProfileNode):
+        (KJS::ProfileNode::willExecute): Rename the add function for consistency.
+        (KJS::ProfileNode::addChild): Appends the child to this node but also
+        sets the parent pointer of the children to this node.
+        (KJS::ProfileNode::insertNode): Insert a node between this node and its
+        children.  Also set the time for the new node since it is now exiting
+        and we don't really know when it started.
+        (KJS::ProfileNode::stopProfiling):
+        (KJS::ProfileNode::startTimer):
+        * profiler/ProfileNode.h:
+        (KJS::CallIdentifier::toString): Added for debugging.
+        (KJS::ProfileNode::setParent):
+        (KJS::ProfileNode::setSelfTime): Fixed an old bug where we set the
+        visibleTotalTime not the visibleSelfTime.
+        (KJS::ProfileNode::children):
+        (KJS::ProfileNode::toString): Added for debugging.
+        * profiler/Profiler.cpp: remove unecessary calls.
+        (KJS::Profiler::startProfiling):
+
 2008-05-22  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Oliver Hunt.
index 7ef1f73..0293c1d 100644 (file)
@@ -38,6 +38,7 @@
 #include "JSLock.h"
 #include "JSPropertyNameIterator.h"
 #include "Parser.h"
+#include "Profiler.h"
 #include "Register.h"
 #include "array_object.h"
 #include "debugger.h"
@@ -436,8 +437,15 @@ static NEVER_INLINE bool isNotObject(ExecState* exec, const Instruction*, CodeBl
     return true;
 }
 
-static NEVER_INLINE JSValue* eval(ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
+#if JAVASCRIPT_PROFILING
+static NEVER_INLINE JSValue* callEval(ExecState* exec, JSObject* evalFunction, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
 {
+    Profiler::profiler()->willExecute(exec, evalFunction);
+#else
+static NEVER_INLINE JSValue* callEval(ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
+{
+#endif
+
     JSValue* x = argc >= 2 ? r[argv + 1].u.jsValue : jsUndefined();
     
     if (!x->isString())
@@ -460,7 +468,15 @@ static NEVER_INLINE JSValue* eval(ExecState* exec, JSObject* thisObj, ScopeChain
         return 0;
     }
 
+#if JAVASCRIPT_PROFILING
+    JSValue* result = machine().execute(evalNode.get(), exec, thisObj, registerFile, r - (*registerFile->basePointer()) + argv + argc, scopeChain, &exceptionValue);
+
+    Profiler::profiler()->didExecute(exec, evalFunction);
+
+    return result;
+#else
     return machine().execute(evalNode.get(), exec, thisObj, registerFile, r - (*registerFile->basePointer()) + argv + argc, scopeChain, &exceptionValue);
+#endif
 }
 
 Machine& machine()
@@ -589,6 +605,10 @@ NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionVa
     r = (*registerBase) + callerRegisterOffset;
     exec->m_callFrameOffset = callerRegisterOffset - codeBlock->numLocals - CallFrameHeaderSize;
     vPC = callFrame[ReturnVPC].u.vPC;
+
+#if JAVASCRIPT_PROFILING
+    Profiler::profiler()->didExecute(exec, callFrame[Callee].u.jsObject);
+#endif
     return true;
 }
 
@@ -637,6 +657,10 @@ JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainN
         return 0;
     }
 
+#if JAVASCRIPT_PROFILING
+    Profiler::profiler()->willExecute(exec, programNode->sourceURL(), programNode->lineNo());
+#endif
+
     RegisterFile* registerFile = registerFileStack->pushGlobalRegisterFile();
     ASSERT(registerFile->numGlobalSlots());
     CodeBlock* codeBlock = &programNode->code(scopeChain, !registerFileStack->inImplicitCall());
@@ -657,6 +681,11 @@ JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainN
     m_reentryDepth--;
 
     registerFileStack->popGlobalRegisterFile();
+
+#if JAVASCRIPT_PROFILING
+    Profiler::profiler()->didExecute(exec, programNode->sourceURL(), programNode->lineNo());
+#endif
+
     return result;
 }
 
@@ -667,6 +696,10 @@ JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, F
         return 0;
     }
 
+#if JAVASCRIPT_PROFILING
+    Profiler::profiler()->willExecute(exec, function);
+#endif
+
     RegisterFile* registerFile = registerFileStack->current();
 
     int argv = CallFrameHeaderSize;
@@ -711,7 +744,6 @@ JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, F
 
     registerFile->shrink(oldSize);
     return result;
-    
 }
 
 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, RegisterFile* registerFile, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
@@ -720,6 +752,11 @@ JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj
         *exception = createStackOverflowError(exec);
         return 0;
     }
+
+#if JAVASCRIPT_PROFILING
+    Profiler::profiler()->willExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
+#endif
+
     EvalCodeBlock* codeBlock = &evalNode->code(scopeChain);
     
     JSVariableObject* variableObject;
@@ -767,6 +804,11 @@ JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj
     m_reentryDepth--;
 
     registerFile->shrink(oldSize);
+
+#if JAVASCRIPT_PROFILING
+    Profiler::profiler()->didExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
+#endif
+
     return result;
 }
 
@@ -1813,7 +1855,11 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
             JSObject* thisObject = r[codeBlock->thisRegister].u.jsObject;
 
             registerFile->setSafeForReentry(true);
-            JSValue* result = eval(exec, thisObject, scopeChain, registerFile, r, argv, argc, exceptionValue);
+#if JAVASCRIPT_PROFILING
+            JSValue* result = callEval(exec, static_cast<JSObject*>(v), thisObject, scopeChain, registerFile, r, argv, argc, exceptionValue);
+#else
+            JSValue* result = callEval(exec, thisObject, scopeChain, registerFile, r, argv, argc, exceptionValue);
+#endif
             registerFile->setSafeForReentry(false);
             r = (*registerBase) + registerOffset;
 
@@ -1853,6 +1899,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         CallType callType = v->getCallData(callData);
         
         if (callType == CallTypeJS) {
+#if JAVASCRIPT_PROFILING
+            Profiler::profiler()->willExecute(exec, static_cast<JSObject*>(v));
+#endif
             int registerOffset = r - (*registerBase);
             Register* callFrame = r + argv - CallFrameHeaderSize;
             int callFrameOffset = registerOffset + argv - CallFrameHeaderSize;
@@ -1878,8 +1927,11 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         }
 
         if (callType == CallTypeNative) {
+#if JAVASCRIPT_PROFILING
+            Profiler::profiler()->willExecute(exec, static_cast<JSObject*>(v));
+#endif
             int registerOffset = r - (*registerBase);
-            
+
             r[argv].u.jsValue = base == missingThisObjectMarker() ? exec->globalThisValue() : (r[base].u.jsValue)->toObject(exec); // "this" value
             JSObject* thisObj = static_cast<JSObject*>(r[argv].u.jsValue);
 
@@ -1892,6 +1944,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
             r = (*registerBase) + registerOffset;
             r[dst].u.jsValue = returnValue;
 
+#if JAVASCRIPT_PROFILING
+            Profiler::profiler()->didExecute(exec, static_cast<JSObject*>(v));
+#endif
             VM_CHECK_EXCEPTION();
 
             ++vPC;
@@ -1938,6 +1993,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         int r0 = callFrame[ReturnValueRegister].u.i;
         r[r0].u.jsValue = returnValue;
         
+#if JAVASCRIPT_PROFILING
+        Profiler::profiler()->didExecute(exec, callFrame[Callee].u.jsObject);
+#endif
         NEXT_OPCODE;
     }
     BEGIN_OPCODE(op_construct) {
@@ -1955,6 +2013,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         JSObject* constructor = static_cast<JSObject*>(funcVal);
 
         if (constructType == ConstructTypeJS) {
+#if JAVASCRIPT_PROFILING
+            Profiler::profiler()->willExecute(exec, constructor);
+#endif
             int registerOffset = r - (*registerBase);
             Register* callFrame = r + argv - CallFrameHeaderSize;
             int callFrameOffset = registerOffset + argv - CallFrameHeaderSize;
@@ -1988,6 +2049,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         }
 
         if (constructType == ConstructTypeNative) {
+#if JAVASCRIPT_PROFILING
+            Profiler::profiler()->willExecute(exec, constructor);
+#endif
             int registerOffset = r - (*registerBase);
 
             List args(&r[argv + 1].u.jsValue, argc - 1);
@@ -1999,6 +2063,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
             VM_CHECK_EXCEPTION();
             r[dst].u.jsValue = returnValue;
 
+#if JAVASCRIPT_PROFILING
+            Profiler::profiler()->didExecute(exec, constructor);
+#endif
             ++vPC;
             NEXT_OPCODE;
         }
index 8a970e4..68d1108 100644 (file)
@@ -574,10 +574,6 @@ JSValue* globalFuncEval(ExecState* exec, PrototypeReflexiveFunction* function, J
     int errLine;
     UString errMsg;
 
-#if JAVASCRIPT_PROFILING
-    Profiler::profiler()->willExecute(exec, UString(), 0);
-#endif
-
     RefPtr<EvalNode> evalNode = parser().parse<EvalNode>(exec, UString(), 0, UStringSourceProvider::create(s), &sourceId, &errLine, &errMsg);
     
     if (!evalNode)
@@ -586,10 +582,6 @@ JSValue* globalFuncEval(ExecState* exec, PrototypeReflexiveFunction* function, J
     JSValue* exception = 0;
     JSValue* value = machine().execute(evalNode.get(), exec, thisObj, &exec->dynamicGlobalObject()->registerFileStack(), globalObject->globalScopeChain().node(), &exception);
 
-#if JAVASCRIPT_PROFILING
-    Profiler::profiler()->didExecute(exec, UString(), 0);
-#endif
-
     if (exception) {
         exec->setException(exception);
         return value;
index ebf614e..51dd2ca 100644 (file)
@@ -69,10 +69,6 @@ Completion Interpreter::evaluate(ExecState* exec, ScopeChain& scopeChain, const
     int errLine;
     UString errMsg;
 
-#if JAVASCRIPT_PROFILING
-    Profiler::profiler()->willExecute(exec, sourceURL, startingLineNumber);
-#endif
-
     RefPtr<ProgramNode> programNode = parser().parse<ProgramNode>(exec, sourceURL, startingLineNumber, source, &sourceId, &errLine, &errMsg);
 
     // no program node means a syntax error occurred
@@ -84,10 +80,6 @@ Completion Interpreter::evaluate(ExecState* exec, ScopeChain& scopeChain, const
     JSValue* exception = 0;
     JSValue* result = machine().execute(programNode.get(), exec, scopeChain.node(), thisObj, &exec->dynamicGlobalObject()->registerFileStack(), &exception);
 
-#if JAVASCRIPT_PROFILING
-    Profiler::profiler()->didExecute(exec, sourceURL, startingLineNumber);
-#endif
-
     return exception ? Completion(Throw, exception) : Completion(Normal, result);
 }
 
index ff822f4..475bc2b 100644 (file)
@@ -55,11 +55,19 @@ void Profile::stopProfiling()
 
 void Profile::willExecute(const CallIdentifier& callIdentifier)
 {
-    m_currentNode = m_currentNode->addOrStartChild(callIdentifier);
+    ASSERT(m_currentNode);
+
+    m_currentNode = m_currentNode->willExecute(callIdentifier);
 }
 
-void Profile::didExecute(const CallIdentifier&)
+void Profile::didExecute(const CallIdentifier& callIdentifier)
 {
+    if (m_currentNode == m_callTree) {
+        m_currentNode = ProfileNode::create(callIdentifier, m_callTree.get(), m_callTree.get());
+        m_callTree->insertNode(m_currentNode.release());
+        m_currentNode = m_callTree;
+        return;
+    }
 
     m_currentNode = m_currentNode->didExecute();
 }
index fd2c35c..586917d 100644 (file)
@@ -42,6 +42,7 @@ ProfileNode::ProfileNode(const CallIdentifier& callIdentifier, ProfileNode* head
     : m_callIdentifier(callIdentifier)
     , m_headNode(headNode)
     , m_parentNode(parentNode)
+    , m_startTime(0.0)
     , m_actualTotalTime (0.0)
     , m_visibleTotalTime (0.0)
     , m_actualSelfTime (0.0)
@@ -52,13 +53,20 @@ ProfileNode::ProfileNode(const CallIdentifier& callIdentifier, ProfileNode* head
     if (!m_headNode)
         m_headNode = this;
 
-    m_startTime = getCurrentUTCTimeWithMicroseconds();
+    startTimer();
 }
 
-void ProfileNode::willExecute()
+ProfileNode* ProfileNode::willExecute(const CallIdentifier& callIdentifier)
 {
-    if (!m_startTime)
-        m_startTime = getCurrentUTCTimeWithMicroseconds();
+    for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) {
+        if ((*currentChild)->callIdentifier() == callIdentifier) {
+            (*currentChild)->startTimer();
+            return (*currentChild).get();
+        }
+    }
+
+    m_children.append(ProfileNode::create(callIdentifier, m_headNode, this));
+    return m_children.last().get();
 }
 
 ProfileNode* ProfileNode::didExecute()
@@ -67,17 +75,29 @@ ProfileNode* ProfileNode::didExecute()
     return m_parentNode;
 }
 
-ProfileNode* ProfileNode::addOrStartChild(const CallIdentifier& callIdentifier)
+void ProfileNode::addChild(PassRefPtr<ProfileNode> prpChild)
 {
-    for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) {
-        if ((*currentChild)->callIdentifier() == callIdentifier) {
-            (*currentChild)->willExecute();
-            return (*currentChild).get();
-        }
+    RefPtr<ProfileNode> child = prpChild;
+    child->setParent(this);
+    m_children.append(child.release());
+}
+        
+void ProfileNode::insertNode(PassRefPtr<ProfileNode> prpNode)
+{
+    RefPtr<ProfileNode> node = prpNode;
+
+    double sumOfChildrensTime = 0.0;
+    for (unsigned i = 0; i < m_children.size(); ++i) {
+        sumOfChildrensTime += m_children[i]->totalTime();
+        node->addChild(m_children[i].release());
     }
 
-    m_children.append(ProfileNode::create(callIdentifier, m_headNode, this));
-    return m_children.last().get();
+    m_children.clear();
+
+    node->didExecute();
+    node->setTotalTime(sumOfChildrensTime);
+    node->setSelfTime(0.0);
+    m_children.append(node.release());
 }
 
 void ProfileNode::stopProfiling()
@@ -87,7 +107,7 @@ void ProfileNode::stopProfiling()
 
     m_visibleTotalTime = m_actualTotalTime;
 
-    ASSERT(m_actualSelfTime == 0.0);
+    ASSERT(m_actualSelfTime == 0.0 && m_startTime == 0.0);
 
     // Calculate Self time and the percentages once we stop profiling.
     StackIterator endOfChildren = m_children.end();
@@ -100,7 +120,7 @@ void ProfileNode::stopProfiling()
     m_actualSelfTime = m_actualTotalTime - m_actualSelfTime;
 
     if (m_headNode == this && m_actualSelfTime) {
-        ProfileNode* idleNode = addOrStartChild(CallIdentifier(NonJSExecution, 0, 0));
+        ProfileNode* idleNode = willExecute(CallIdentifier(NonJSExecution, 0, 0));
 
         idleNode->setTotalTime(m_actualSelfTime);
         idleNode->setSelfTime(m_actualSelfTime);
@@ -258,6 +278,12 @@ void ProfileNode::endAndRecordCall()
     ++m_numberOfCalls;
 }
 
+void ProfileNode::startTimer()
+{
+    if (!m_startTime)
+        m_startTime = getCurrentUTCTimeWithMicroseconds();
+}
+
 #ifndef NDEBUG
 void ProfileNode::debugPrintData(int indentLevel) const
 {
index 849ef8f..f83294a 100644 (file)
@@ -51,6 +51,9 @@ namespace KJS {
         CallIdentifier(const CallIdentifier& ci) : name(ci.name), url(ci.url), lineNumber(ci.lineNumber) {}
 
         inline bool operator== (const CallIdentifier& ci) const { return ci.lineNumber == lineNumber && ci.name == name && ci.url == url; }
+#ifndef NDEBUG
+        const char* toString() const { return name.UTF8String().c_str(); }
+#endif
     };
 
     class ProfileNode : public RefCounted<ProfileNode> {
@@ -58,15 +61,14 @@ namespace KJS {
         static PassRefPtr<ProfileNode> create(const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode) {
             return adoptRef(new ProfileNode(callIdentifier, headNode, parentNode)); }
 
-        void willExecute();
+        ProfileNode* willExecute(const CallIdentifier&);
         ProfileNode* didExecute();
 
-        ProfileNode* addOrStartChild(const CallIdentifier&);
-
         void stopProfiling();
 
         const CallIdentifier& callIdentifier() const { return m_callIdentifier; }
         ProfileNode* parent() const { return m_parentNode; }
+        void setParent(ProfileNode* parent) { m_parentNode = parent; }
         UString functionName() const { return m_callIdentifier.name; }
         UString url() const { return m_callIdentifier.url; }
         unsigned lineNumber() const { return m_callIdentifier.lineNumber; }
@@ -74,12 +76,14 @@ namespace KJS {
         double totalTime() const { return m_visibleTotalTime; }
         void setTotalTime(double time) { m_actualTotalTime = time; m_visibleTotalTime = time; }
         double selfTime() const { return m_visibleSelfTime; }
-        void setSelfTime(double time) { m_actualSelfTime = time; m_visibleTotalTime = time; }
+        void setSelfTime(double time) { m_actualSelfTime = time; m_visibleSelfTime = time; }
         double totalPercent() const { return (m_visibleTotalTime / m_headNode->totalTime()) * 100.0; }
         double selfPercent() const { return (m_visibleSelfTime / m_headNode->totalTime()) * 100.0; }
         unsigned numberOfCalls() const { return m_numberOfCalls; }
         void setNumberOfCalls(unsigned number) { m_numberOfCalls = number; }
-        const Vector<RefPtr<ProfileNode> >& children() { return m_children; }
+        const Vector<RefPtr<ProfileNode> >& children() const { return m_children; }
+        void addChild(PassRefPtr<ProfileNode> prpChild);
+        void insertNode(PassRefPtr<ProfileNode> prpNode);
         bool visible() const { return m_visible; }
         void setVisible(bool visible) { m_visible = visible; }
 
@@ -99,11 +103,13 @@ namespace KJS {
         void endAndRecordCall();
         
 #ifndef NDEBUG
+        const char* toString() const { return m_callIdentifier.toString(); }
         void debugPrintData(int indentLevel) const;
         double debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount&) const;
 #endif
     private:
         ProfileNode(const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode);
+        void startTimer();
 
         CallIdentifier m_callIdentifier;
         ProfileNode* m_headNode;
index b766745..9c20a95 100644 (file)
@@ -43,7 +43,6 @@ static Profiler* sharedProfiler = 0;
 static const char* GlobalCodeExecution = "(program)";
 static const char* AnonymousFunction = "(anonymous function)";
 
-static void getCallIdentifiers(ExecState*, Vector<CallIdentifier>& callIdentifiers);
 static CallIdentifier createCallIdentifier(JSObject*);
 static CallIdentifier createCallIdentifier(const UString& sourceURL, int startingLineNumber);
 static CallIdentifier createCallIdentifierFromFunctionImp(FunctionImp*);
@@ -77,12 +76,6 @@ void Profiler::startProfiling(ExecState* exec, const UString& title)
 
     RefPtr<Profile> profile = Profile::create(title, globalExec, exec->lexicalGlobalObject()->pageGroupIdentifier());
     m_currentProfiles.append(profile);
-
-    // Update the profile with the current call identifiers that started the profiling.
-    Vector<CallIdentifier> callIdentifiers;
-    getCallIdentifiers(exec, callIdentifiers);
-    for (unsigned i = 0; i< callIdentifiers.size(); ++i)
-        profile->willExecute(callIdentifiers[i]);
 }
 
 PassRefPtr<Profile> Profiler::stopProfiling(ExecState* exec, const UString& title)
@@ -160,19 +153,6 @@ void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startin
     dispatchFunctionToProfiles(m_currentProfiles, &Profile::didExecute, createCallIdentifier(sourceURL, startingLineNumber), exec->lexicalGlobalObject()->pageGroupIdentifier());
 }
 
-void getCallIdentifiers(ExecState*, Vector<CallIdentifier>&)
-{
-    ASSERT_NOT_REACHED();
-#if 0
-    for (ExecState* currentState = exec; currentState; currentState = currentState->callingExecState()) {
-        if (FunctionImp* functionImp = currentState->function())
-            getCallIdentifierFromFunctionImp(functionImp, callIdentifiers);
-        else if (ScopeNode* scopeNode = currentState->scopeNode())
-            callIdentifiers.append(CallIdentifier(GlobalCodeExecution, scopeNode->sourceURL(), (scopeNode->lineNo() + 1)) );   // FIXME: Why is the line number always off by one?
-    }
-#endif
-}
-
 CallIdentifier createCallIdentifier(JSObject* calledFunction)
 {
     if (calledFunction->inherits(&FunctionImp::info))