/*
- * 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
* 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>
-
-#if OS(WINDOWS)
-#include <windows.h>
-#endif
+#include <wtf/DataLog.h>
+#include <wtf/text/StringHash.h>
using namespace WTF;
namespace JSC {
-static double getCount()
-{
-#if OS(WINDOWS)
- static LARGE_INTEGER frequency = {0};
- if (!frequency.QuadPart)
- QueryPerformanceFrequency(&frequency);
- LARGE_INTEGER counter;
- QueryPerformanceCounter(&counter);
- return static_cast<double>(counter.QuadPart) / frequency.QuadPart;
-#else
- return currentTimeMS();
-#endif
-}
-
-ProfileNode::ProfileNode(const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
- : m_callIdentifier(callIdentifier)
+ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* headNode, 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)
+ , m_nextSibling(nullptr)
+ , m_totalTime(0)
+ , m_selfTime(0)
{
startTimer();
}
-ProfileNode::ProfileNode(ProfileNode* headNode, ProfileNode* nodeToCopy)
- : m_callIdentifier(nodeToCopy->callIdentifier())
+ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, 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())
+ , m_totalTime(nodeToCopy->totalTime())
+ , m_selfTime(nodeToCopy->selfTime())
+ , m_calls(nodeToCopy->calls())
{
}
-ProfileNode* ProfileNode::willExecute(const CallIdentifier& callIdentifier)
+ProfileNode* ProfileNode::willExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
{
for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) {
if ((*currentChild)->callIdentifier() == callIdentifier) {
}
}
- RefPtr<ProfileNode> newChild = ProfileNode::create(callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head.
+ 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());
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)
void ProfileNode::stopProfiling()
{
- if (m_startTime)
- endAndRecordCall();
+ ASSERT(!m_calls.isEmpty());
- m_visibleTotalTime = m_actualTotalTime;
-
- ASSERT(m_actualSelfTime == 0.0 && m_startTime == 0.0);
+ 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_actualSelfTime += m_children[i]->totalTime();
+ m_selfTime += m_children[i]->totalTime();
- ASSERT(m_actualSelfTime <= m_actualTotalTime);
- m_actualSelfTime = m_actualTotalTime - m_actualSelfTime;
- m_visibleSelfTime = m_actualSelfTime;
+ ASSERT(m_selfTime <= m_totalTime);
+ m_selfTime = m_totalTime - m_selfTime;
}
ProfileNode* ProfileNode::traverseNextNodePostOrder() const
return next;
}
-ProfileNode* ProfileNode::traverseNextNodePreOrder(bool processChildren) const
-{
- if (processChildren && m_children.size())
- return m_children[0].get();
-
- 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;
-}
-
void ProfileNode::endAndRecordCall()
{
- m_actualTotalTime += m_startTime ? getCount() - m_startTime : 0.0;
- m_startTime = 0.0;
+ Call& last = lastCall();
+ ASSERT(isnan(last.totalTime()));
+
+ last.setTotalTime(currentTime() - last.startTime());
- ++m_numberOfCalls;
+ m_totalTime += last.totalTime();
}
void ProfileNode::startTimer()
{
- if (!m_startTime)
- m_startTime = getCount();
+ m_calls.append(Call(currentTime()));
}
void ProfileNode::resetChildrensSiblings()
{
// Print function names
for (int i = 0; i < indentLevel; ++i)
- printf(" ");
+ dataLogF(" ");
- printf("Function Name %s %d SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% VSelf %.3fms VTotal %.3fms Visible %s Next Sibling %s\n",
- functionName().UTF8String().c_str(),
- m_numberOfCalls, m_actualSelfTime, selfPercent(), m_actualTotalTime, totalPercent(),
- m_visibleSelfTime, m_visibleTotalTime,
- (m_visible ? "True" : "False"),
- m_nextSibling ? m_nextSibling->functionName().UTF8String().c_str() : "");
+ 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_nextSibling ? m_nextSibling->functionName().utf8().data() : "");
++indentLevel;
// print the profiled data in a format that matches the tool sample's output.
double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount& countedFunctions) const
{
- printf(" ");
+ dataLogF(" ");
// Print function names
- const char* name = functionName().UTF8String().c_str();
- double sampleCount = m_actualTotalTime * 1000;
+ const char* name = functionName().utf8().data();
+ double sampleCount = m_totalTime * 1000;
if (indentLevel) {
for (int i = 0; i < indentLevel; ++i)
- printf(" ");
+ dataLogF(" ");
- countedFunctions.add(functionName().rep());
+ 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;
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().UTF8String().c_str());
+ dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
}
- return m_actualTotalTime;
+ return m_totalTime;
}
#endif