]> 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 8f20bbeff8a60b512c506fd4bf9e240e17fa062b..9bcf37586c6003edaf39aaf834619ace4edf247d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -10,7 +10,7 @@
  * 2.  Redistributions in binary form must reproduce the above copyright
  *     notice, this list of conditions and the following disclaimer in the
  *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
  *     its contributors may be used to endorse or promote products derived
  *     from this software without specific prior written permission.
  *
 #include "config.h"
 #include "ProfileNode.h"
 
-#include "Profiler.h"
-#include <stdio.h>
+#include "LegacyProfiler.h"
 #include <wtf/DateMath.h>
+#include <wtf/DataLog.h>
 #include <wtf/text/StringHash.h>
 
-#if OS(WINDOWS)
-#include <windows.h>
-#endif
-
 using namespace WTF;
 
 namespace JSC {
 
-static double getCount()
-{
-#if OS(WINDOWS)
-    static LARGE_INTEGER frequency;
-    if (!frequency.QuadPart)
-        QueryPerformanceFrequency(&frequency);
-    LARGE_INTEGER counter;
-    QueryPerformanceCounter(&counter);
-    return static_cast<double>(counter.QuadPart) / frequency.QuadPart;
-#else
-    return currentTimeMS();
-#endif
-}
-
-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)
-    , m_nextSibling(0)
-    , m_startTime(0.0)
-    , m_actualTotalTime(0.0)
-    , m_visibleTotalTime(0.0)
-    , m_actualSelfTime(0.0)
-    , m_visibleSelfTime(0.0)
-    , m_numberOfCalls(0)
-    , m_visible(true)
+#ifndef NDEBUG
+    , m_nextSibling(nullptr)
+#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_startTime(0.0)
-    , m_actualTotalTime(nodeToCopy->actualTotalTime())
-    , m_visibleTotalTime(nodeToCopy->totalTime())
-    , m_actualSelfTime(nodeToCopy->actualSelfTime())
-    , m_visibleSelfTime(nodeToCopy->selfTime())
-    , m_numberOfCalls(nodeToCopy->numberOfCalls())
-    , m_visible(nodeToCopy->visible())
-{
-}
-
-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()
+    , m_calls(nodeToCopy->calls())
+#ifndef NDEBUG
+    , m_nextSibling(nullptr)
+#endif
 {
-    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());
 }
 
-ProfileNode* ProfileNode::findChild(ProfileNode* node) const
-{
-    if (!node)
-        return 0;
-
-    for (size_t i = 0; i < m_children.size(); ++i) {
-        if (*node == m_children[i].get())
-            return m_children[i].get();
-    }
-
-    return 0;
-}
-
 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;
 
@@ -159,24 +97,7 @@ void ProfileNode::insertNode(PassRefPtr<ProfileNode> prpNode)
     m_children.append(node.release());
 }
 
-void ProfileNode::stopProfiling()
-{
-    if (m_startTime)
-        endAndRecordCall();
-
-    m_visibleTotalTime = m_actualTotalTime;
-
-    ASSERT(m_actualSelfTime == 0.0 && m_startTime == 0.0);
-
-    // 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_actualSelfTime += m_children[i]->totalTime();
-
-    ASSERT(m_actualSelfTime <= m_actualTotalTime);
-    m_actualSelfTime = m_actualTotalTime - m_actualSelfTime;
-    m_visibleSelfTime = m_actualSelfTime;
-}
-
+#ifndef NDEBUG
 ProfileNode* ProfileNode::traverseNextNodePostOrder() const
 {
     ProfileNode* next = m_nextSibling;
@@ -187,164 +108,91 @@ ProfileNode* ProfileNode::traverseNextNodePostOrder() const
     return next;
 }
 
-ProfileNode* ProfileNode::traverseNextNodePreOrder(bool processChildren) const
+void ProfileNode::debugPrint()
 {
-    if (processChildren && m_children.size())
-        return m_children[0].get();
+    CalculateProfileSubtreeDataFunctor functor;
+    forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
 
-    if (m_nextSibling)
-        return m_nextSibling;
-
-    ProfileNode* nextParent = m_parent;
-    if (!nextParent)
-        return 0;
-
-    ProfileNode* next;
-    for (next = m_parent->nextSibling(); !next; next = nextParent->nextSibling()) {
-        nextParent = nextParent->parent();
-        if (!nextParent)
-            return 0;
-    }
-
-    return next;
-}
-
-void ProfileNode::setTreeVisible(ProfileNode* node, bool visible)
-{
-    ProfileNode* nodeParent = node->parent();
-    ProfileNode* nodeSibling = node->nextSibling();
-    node->setParent(0);
-    node->setNextSibling(0);
-
-    for (ProfileNode* currentNode = node; currentNode; currentNode = currentNode->traverseNextNodePreOrder())
-        currentNode->setVisible(visible);
-
-    node->setParent(nodeParent);
-    node->setNextSibling(nodeSibling);
-}
-
-void ProfileNode::calculateVisibleTotalTime()
-{
-    double sumOfVisibleChildrensTime = 0.0;
-
-    for (unsigned i = 0; i < m_children.size(); ++i) {
-        if (m_children[i]->visible())
-            sumOfVisibleChildrensTime += m_children[i]->totalTime();
-    }
-
-    m_visibleTotalTime = m_visibleSelfTime + sumOfVisibleChildrensTime;
-}
-
-bool ProfileNode::focus(const CallIdentifier& callIdentifier)
-{
-    if (!m_visible)
-        return false;
-
-    if (m_callIdentifier != callIdentifier) {
-        m_visible = false;
-        return true;
-    }
-
-    for (ProfileNode* currentParent = m_parent; currentParent; currentParent = currentParent->parent())
-        currentParent->setVisible(true);
-
-    return false;
-}
-
-void ProfileNode::exclude(const CallIdentifier& callIdentifier)
-{
-    if (m_visible && m_callIdentifier == callIdentifier) {
-        setTreeVisible(this, false);
-
-        m_parent->setVisibleSelfTime(m_parent->selfTime() + m_visibleTotalTime);
-    }
-}
-
-void ProfileNode::restore()
-{
-    m_visibleTotalTime = m_actualTotalTime;
-    m_visibleSelfTime = m_actualSelfTime;
-    m_visible = true;
+    debugPrintRecursively(0, data);
 }
 
-void ProfileNode::endAndRecordCall()
+void ProfileNode::debugPrintSampleStyle()
 {
-    m_actualTotalTime += m_startTime ? getCount() - m_startTime : 0.0;
-    m_startTime = 0.0;
-
-    ++m_numberOfCalls;
-}
+    FunctionCallHashCount countedFunctions;
 
-void ProfileNode::startTimer()
-{
-    if (!m_startTime)
-        m_startTime = getCount();
-}
+    CalculateProfileSubtreeDataFunctor functor;
+    forEachNodePostorder(functor);
+    ProfileNode::ProfileSubtreeData data = functor.returnValue();
 
-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());
+    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)
-        printf("  ");
+        dataLogF("  ");
+
+    auto it = data.selfAndTotalTimes.find(this);
+    ASSERT(it != data.selfAndTotalTimes.end());
 
-    printf("Function Name %s %d SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% VSelf %.3fms VTotal %.3fms Visible %s Next Sibling %s\n",
-        functionName().utf8().data(), 
-        m_numberOfCalls, m_actualSelfTime, selfPercent(), m_actualTotalTime, totalPercent(),
-        m_visibleSelfTime, m_visibleTotalTime, 
-        (m_visible ? "True" : "False"),
+    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(),
+        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)
 {
-    printf("    ");
+    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_actualTotalTime * 1000;
+    double sampleCount = nodeTotalTime * 1000;
     if (indentLevel) {
         for (int i = 0; i < indentLevel; ++i)
-            printf("  ");
+            dataLogF("  ");
 
          countedFunctions.add(functionName().impl());
 
-        printf("%.0f %s\n", sampleCount ? sampleCount : 1, name);
+        dataLogF("%.0f %s\n", sampleCount ? sampleCount : 1, name);
     } else
-        printf("%s\n", name);
+        dataLogF("%s\n", name);
 
     ++indentLevel;
 
     // 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
     if (sumOfChildrensCount < sampleCount) {
-        printf("    ");
+        dataLogF("    ");
         while (indentLevel--)
-            printf("  ");
+            dataLogF("  ");
 
-        printf("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
+        dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
     }
 
-    return m_actualTotalTime;
+    return nodeTotalTime;
 }
 #endif