]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - profiler/ProfileNode.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / profiler / ProfileNode.cpp
index cb8678724acdde8674cb6261ee2639331219728d..9bcf37586c6003edaf39aaf834619ace4edf247d 100644 (file)
@@ -38,58 +38,35 @@ using namespace WTF;
 
 namespace JSC {
 
-ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
+ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode)
     : m_callerCallFrame(callerCallFrame)
     , m_callIdentifier(callIdentifier)
-    , m_head(headNode)
     , m_parent(parentNode)
+#ifndef NDEBUG
     , m_nextSibling(nullptr)
-    , m_totalTime(0)
-    , m_selfTime(0)
+#endif
 {
-    startTimer();
 }
 
-ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy)
+ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy)
     : m_callerCallFrame(callerCallFrame)
     , m_callIdentifier(nodeToCopy->callIdentifier())
-    , m_head(headNode)
     , m_parent(nodeToCopy->parent())
-    , m_nextSibling(0)
-    , m_totalTime(nodeToCopy->totalTime())
-    , m_selfTime(nodeToCopy->selfTime())
     , m_calls(nodeToCopy->calls())
+#ifndef NDEBUG
+    , m_nextSibling(nullptr)
+#endif
 {
 }
 
-ProfileNode* ProfileNode::willExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
-{
-    for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) {
-        if ((*currentChild)->callIdentifier() == callIdentifier) {
-            (*currentChild)->startTimer();
-            return (*currentChild).get();
-        }
-    }
-
-    RefPtr<ProfileNode> newChild = ProfileNode::create(callerCallFrame, callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head.
-    if (m_children.size())
-        m_children.last()->setNextSibling(newChild.get());
-    m_children.append(newChild.release());
-    return m_children.last().get();
-}
-
-ProfileNode* ProfileNode::didExecute()
-{
-    endAndRecordCall();
-    return m_parent;
-}
-
 void ProfileNode::addChild(PassRefPtr<ProfileNode> prpChild)
 {
     RefPtr<ProfileNode> child = prpChild;
     child->setParent(this);
+#ifndef NDEBUG
     if (m_children.size())
         m_children.last()->setNextSibling(child.get());
+#endif
     m_children.append(child.release());
 }
 
@@ -98,17 +75,18 @@ void ProfileNode::removeChild(ProfileNode* node)
     if (!node)
         return;
 
-    for (size_t i = 0; i < m_children.size(); ++i) {
-        if (*node == m_children[i].get()) {
-            m_children.remove(i);
-            break;
-        }
-    }
-    
-    resetChildrensSiblings();
+    m_children.removeFirstMatching([node] (const RefPtr<ProfileNode>& current) {
+        return *node == current.get();
+    });
+
+#ifndef NDEBUG
+    size_t size = m_children.size();
+    for (size_t i = 0; i < size; ++i)
+        m_children[i]->setNextSibling(i + 1 == size ? nullptr : m_children[i + 1].get());
+#endif
 }
 
-void ProfileNode::insertNode(PassRefPtr<ProfileNode> prpNode)
+void ProfileNode::spliceNode(PassRefPtr<ProfileNode> prpNode)
 {
     RefPtr<ProfileNode> node = prpNode;
 
@@ -119,21 +97,7 @@ void ProfileNode::insertNode(PassRefPtr<ProfileNode> prpNode)
     m_children.append(node.release());
 }
 
-void ProfileNode::stopProfiling()
-{
-    ASSERT(!m_calls.isEmpty());
-
-    if (isnan(m_calls.last().totalTime()))
-        endAndRecordCall();
-
-    // Because we iterate in post order all of our children have been stopped before us.
-    for (unsigned i = 0; i < m_children.size(); ++i)
-        m_selfTime += m_children[i]->totalTime();
-
-    ASSERT(m_selfTime <= m_totalTime);
-    m_selfTime = m_totalTime - m_selfTime;
-}
-
+#ifndef NDEBUG
 ProfileNode* ProfileNode::traverseNextNodePostOrder() const
 {
     ProfileNode* next = m_nextSibling;
@@ -144,55 +108,63 @@ ProfileNode* ProfileNode::traverseNextNodePostOrder() const
     return next;
 }
 
-void ProfileNode::endAndRecordCall()
+void ProfileNode::debugPrint()
 {
-    Call& last = lastCall();
-    ASSERT(isnan(last.totalTime()));
-
-    last.setTotalTime(currentTime() - last.startTime());
+    CalculateProfileSubtreeDataFunctor functor;
+    forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
 
-    m_totalTime += last.totalTime();
+    debugPrintRecursively(0, data);
 }
 
-void ProfileNode::startTimer()
+void ProfileNode::debugPrintSampleStyle()
 {
-    m_calls.append(Call(currentTime()));
-}
+    FunctionCallHashCount countedFunctions;
 
-void ProfileNode::resetChildrensSiblings()
-{
-    unsigned size = m_children.size();
-    for (unsigned i = 0; i < size; ++i)
-        m_children[i]->setNextSibling(i + 1 == size ? 0 : m_children[i + 1].get());
+    CalculateProfileSubtreeDataFunctor functor;
+    forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+    debugPrintSampleStyleRecursively(0, countedFunctions, data);
 }
 
-#ifndef NDEBUG
-void ProfileNode::debugPrintData(int indentLevel) const
+void ProfileNode::debugPrintRecursively(int indentLevel, const ProfileSubtreeData& data)
 {
     // Print function names
     for (int i = 0; i < indentLevel; ++i)
         dataLogF("  ");
 
+    auto it = data.selfAndTotalTimes.find(this);
+    ASSERT(it != data.selfAndTotalTimes.end());
+
+    double nodeSelfTime = it->value.first;
+    double nodeTotalTime = it->value.second;
+    double rootTotalTime = data.rootTotalTime;
+
     dataLogF("Function Name %s %zu SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% Next Sibling %s\n",
         functionName().utf8().data(),
-        numberOfCalls(), m_selfTime, selfPercent(), m_totalTime, totalPercent(),
+        m_calls.size(), nodeSelfTime, nodeSelfTime / rootTotalTime * 100.0, nodeTotalTime, nodeTotalTime / rootTotalTime * 100.0,
         m_nextSibling ? m_nextSibling->functionName().utf8().data() : "");
 
     ++indentLevel;
 
     // Print children's names and information
     for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
-        (*currentChild)->debugPrintData(indentLevel);
+        (*currentChild)->debugPrintRecursively(indentLevel, data);
 }
 
 // print the profiled data in a format that matches the tool sample's output.
-double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount& countedFunctions) const
+double ProfileNode::debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount& countedFunctions, const ProfileSubtreeData& data)
 {
     dataLogF("    ");
 
+    auto it = data.selfAndTotalTimes.find(this);
+    ASSERT(it != data.selfAndTotalTimes.end());
+    double nodeTotalTime = it->value.second;
+
     // Print function names
     const char* name = functionName().utf8().data();
-    double sampleCount = m_totalTime * 1000;
+    double sampleCount = nodeTotalTime * 1000;
     if (indentLevel) {
         for (int i = 0; i < indentLevel; ++i)
             dataLogF("  ");
@@ -208,7 +180,7 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC
     // Print children's names and information
     double sumOfChildrensCount = 0.0;
     for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
-        sumOfChildrensCount += (*currentChild)->debugPrintDataSampleStyle(indentLevel, countedFunctions);
+        sumOfChildrensCount += (*currentChild)->debugPrintSampleStyleRecursively(indentLevel, countedFunctions, data);
 
     sumOfChildrensCount *= 1000;    //
     // Print remainder of samples to match sample's output
@@ -220,7 +192,7 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC
         dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
     }
 
-    return m_totalTime;
+    return nodeTotalTime;
 }
 #endif