summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/profiler/ProfileNode.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2015-10-15 09:45:50 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2015-10-15 09:45:50 +0000
commite15dd966d523731101f70ccf768bba12435a0208 (patch)
treeae9cb828a24ded2585a41af3f21411523b47897d /Source/JavaScriptCore/profiler/ProfileNode.cpp
downloadWebKitGtk-tarball-e15dd966d523731101f70ccf768bba12435a0208.tar.gz
webkitgtk-2.10.2webkitgtk-2.10.2
Diffstat (limited to 'Source/JavaScriptCore/profiler/ProfileNode.cpp')
-rw-r--r--Source/JavaScriptCore/profiler/ProfileNode.cpp199
1 files changed, 199 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/profiler/ProfileNode.cpp b/Source/JavaScriptCore/profiler/ProfileNode.cpp
new file mode 100644
index 000000000..9bcf37586
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfileNode.cpp
@@ -0,0 +1,199 @@
+/*
+ * 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfileNode.h"
+
+#include "LegacyProfiler.h"
+#include <wtf/DateMath.h>
+#include <wtf/DataLog.h>
+#include <wtf/text/StringHash.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode)
+ : m_callerCallFrame(callerCallFrame)
+ , m_callIdentifier(callIdentifier)
+ , m_parent(parentNode)
+#ifndef NDEBUG
+ , m_nextSibling(nullptr)
+#endif
+{
+}
+
+ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy)
+ : m_callerCallFrame(callerCallFrame)
+ , m_callIdentifier(nodeToCopy->callIdentifier())
+ , m_parent(nodeToCopy->parent())
+ , m_calls(nodeToCopy->calls())
+#ifndef NDEBUG
+ , m_nextSibling(nullptr)
+#endif
+{
+}
+
+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());
+}
+
+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
+}
+
+void ProfileNode::spliceNode(PassRefPtr<ProfileNode> prpNode)
+{
+ RefPtr<ProfileNode> node = prpNode;
+
+ for (unsigned i = 0; i < m_children.size(); ++i)
+ node->addChild(m_children[i].release());
+
+ m_children.clear();
+ m_children.append(node.release());
+}
+
+#ifndef NDEBUG
+ProfileNode* ProfileNode::traverseNextNodePostOrder() const
+{
+ ProfileNode* next = m_nextSibling;
+ if (!next)
+ return m_parent;
+ while (ProfileNode* firstChild = next->firstChild())
+ next = firstChild;
+ return next;
+}
+
+void ProfileNode::debugPrint()
+{
+ CalculateProfileSubtreeDataFunctor functor;
+ forEachNodePostorder(functor);
+ ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+ debugPrintRecursively(0, data);
+}
+
+void ProfileNode::debugPrintSampleStyle()
+{
+ FunctionCallHashCount countedFunctions;
+
+ CalculateProfileSubtreeDataFunctor functor;
+ forEachNodePostorder(functor);
+ ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+ debugPrintSampleStyleRecursively(0, countedFunctions, data);
+}
+
+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(),
+ 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)->debugPrintRecursively(indentLevel, data);
+}
+
+// print the profiled data in a format that matches the tool sample's output.
+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 = nodeTotalTime * 1000;
+ if (indentLevel) {
+ for (int i = 0; i < indentLevel; ++i)
+ dataLogF(" ");
+
+ countedFunctions.add(functionName().impl());
+
+ dataLogF("%.0f %s\n", sampleCount ? sampleCount : 1, name);
+ } else
+ 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)->debugPrintSampleStyleRecursively(indentLevel, countedFunctions, data);
+
+ sumOfChildrensCount *= 1000; //
+ // Print remainder of samples to match sample's output
+ if (sumOfChildrensCount < sampleCount) {
+ dataLogF(" ");
+ while (indentLevel--)
+ dataLogF(" ");
+
+ dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
+ }
+
+ return nodeTotalTime;
+}
+#endif
+
+} // namespace JSC