diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/profiler/ProfileNode.cpp | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/profiler/ProfileNode.cpp')
-rw-r--r-- | Source/JavaScriptCore/profiler/ProfileNode.cpp | 160 |
1 files changed, 104 insertions, 56 deletions
diff --git a/Source/JavaScriptCore/profiler/ProfileNode.cpp b/Source/JavaScriptCore/profiler/ProfileNode.cpp index 9bcf37586..fe2342ea4 100644 --- a/Source/JavaScriptCore/profiler/ProfileNode.cpp +++ b/Source/JavaScriptCore/profiler/ProfileNode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2008 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 Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Computer, 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. * @@ -34,39 +34,83 @@ #include <wtf/DataLog.h> #include <wtf/text/StringHash.h> +#if OS(WINDOWS) +#include <windows.h> +#endif + using namespace WTF; namespace JSC { -ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode) +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) : m_callerCallFrame(callerCallFrame) , m_callIdentifier(callIdentifier) + , m_head(headNode) , m_parent(parentNode) -#ifndef NDEBUG - , m_nextSibling(nullptr) -#endif + , m_nextSibling(0) + , m_startTime(0.0) + , m_totalTime(0.0) + , m_selfTime(0.0) + , m_numberOfCalls(0) { + startTimer(); } -ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy) +ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy) : m_callerCallFrame(callerCallFrame) , m_callIdentifier(nodeToCopy->callIdentifier()) + , m_head(headNode) , m_parent(nodeToCopy->parent()) - , m_calls(nodeToCopy->calls()) -#ifndef NDEBUG - , m_nextSibling(nullptr) -#endif + , m_nextSibling(0) + , m_startTime(0.0) + , m_totalTime(nodeToCopy->totalTime()) + , m_selfTime(nodeToCopy->selfTime()) + , m_numberOfCalls(nodeToCopy->numberOfCalls()) { } +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()); } @@ -75,18 +119,17 @@ void ProfileNode::removeChild(ProfileNode* node) if (!node) return; - 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 + for (size_t i = 0; i < m_children.size(); ++i) { + if (*node == m_children[i].get()) { + m_children.remove(i); + break; + } + } + + resetChildrensSiblings(); } -void ProfileNode::spliceNode(PassRefPtr<ProfileNode> prpNode) +void ProfileNode::insertNode(PassRefPtr<ProfileNode> prpNode) { RefPtr<ProfileNode> node = prpNode; @@ -97,7 +140,21 @@ void ProfileNode::spliceNode(PassRefPtr<ProfileNode> prpNode) m_children.append(node.release()); } -#ifndef NDEBUG +void ProfileNode::stopProfiling() +{ + if (m_startTime) + endAndRecordCall(); + + ASSERT(m_selfTime == 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_selfTime += m_children[i]->totalTime(); + + ASSERT(m_selfTime <= m_totalTime); + m_selfTime = m_totalTime - m_selfTime; +} + ProfileNode* ProfileNode::traverseNextNodePostOrder() const { ProfileNode* next = m_nextSibling; @@ -108,63 +165,54 @@ ProfileNode* ProfileNode::traverseNextNodePostOrder() const return next; } -void ProfileNode::debugPrint() +void ProfileNode::endAndRecordCall() { - CalculateProfileSubtreeDataFunctor functor; - forEachNodePostorder(functor); - ProfileNode::ProfileSubtreeData data = functor.returnValue(); + m_totalTime += m_startTime ? getCount() - m_startTime : 0.0; + m_startTime = 0.0; - debugPrintRecursively(0, data); + ++m_numberOfCalls; } -void ProfileNode::debugPrintSampleStyle() +void ProfileNode::startTimer() { - FunctionCallHashCount countedFunctions; - - CalculateProfileSubtreeDataFunctor functor; - forEachNodePostorder(functor); - ProfileNode::ProfileSubtreeData data = functor.returnValue(); + if (!m_startTime) + m_startTime = getCount(); +} - debugPrintSampleStyleRecursively(0, countedFunctions, data); +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()); } -void ProfileNode::debugPrintRecursively(int indentLevel, const ProfileSubtreeData& data) +#ifndef NDEBUG +void ProfileNode::debugPrintData(int indentLevel) const { // 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(), - m_calls.size(), nodeSelfTime, nodeSelfTime / rootTotalTime * 100.0, nodeTotalTime, nodeTotalTime / rootTotalTime * 100.0, + dataLogF("Function Name %s %d SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% Next Sibling %s\n", + functionName().utf8().data(), + m_numberOfCalls, m_selfTime, selfPercent(), m_totalTime, totalPercent(), 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)->debugPrintRecursively(indentLevel, data); + (*currentChild)->debugPrintData(indentLevel); } // print the profiled data in a format that matches the tool sample's output. -double ProfileNode::debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount& countedFunctions, const ProfileSubtreeData& data) +double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount& countedFunctions) const { 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 = nodeTotalTime * 1000; + double sampleCount = m_totalTime * 1000; if (indentLevel) { for (int i = 0; i < indentLevel; ++i) dataLogF(" "); @@ -180,7 +228,7 @@ double ProfileNode::debugPrintSampleStyleRecursively(int indentLevel, FunctionCa // Print children's names and information double sumOfChildrensCount = 0.0; for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) - sumOfChildrensCount += (*currentChild)->debugPrintSampleStyleRecursively(indentLevel, countedFunctions, data); + sumOfChildrensCount += (*currentChild)->debugPrintDataSampleStyle(indentLevel, countedFunctions); sumOfChildrensCount *= 1000; // // Print remainder of samples to match sample's output @@ -192,7 +240,7 @@ double ProfileNode::debugPrintSampleStyleRecursively(int indentLevel, FunctionCa dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data()); } - return nodeTotalTime; + return m_totalTime; } #endif |