]> git.saurik.com Git - apple/javascriptcore.git/blame - profiler/ProfileNode.cpp
JavaScriptCore-7600.1.4.11.8.tar.gz
[apple/javascriptcore.git] / profiler / ProfileNode.cpp
CommitLineData
9dae56ea 1/*
81345200 2 * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
9dae56ea
A
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
81345200 13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
9dae56ea
A
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config.h"
30#include "ProfileNode.h"
31
93a37866 32#include "LegacyProfiler.h"
ba379fdc 33#include <wtf/DateMath.h>
6fe7ccc8 34#include <wtf/DataLog.h>
4e4e5a6f 35#include <wtf/text/StringHash.h>
9dae56ea 36
f9bf01c6
A
37using namespace WTF;
38
9dae56ea
A
39namespace JSC {
40
14957cd0
A
41ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
42 : m_callerCallFrame(callerCallFrame)
43 , m_callIdentifier(callIdentifier)
9dae56ea
A
44 , m_head(headNode)
45 , m_parent(parentNode)
81345200
A
46 , m_nextSibling(nullptr)
47 , m_totalTime(0)
48 , m_selfTime(0)
9dae56ea
A
49{
50 startTimer();
51}
52
14957cd0
A
53ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy)
54 : m_callerCallFrame(callerCallFrame)
55 , m_callIdentifier(nodeToCopy->callIdentifier())
9dae56ea
A
56 , m_head(headNode)
57 , m_parent(nodeToCopy->parent())
58 , m_nextSibling(0)
81345200
A
59 , m_totalTime(nodeToCopy->totalTime())
60 , m_selfTime(nodeToCopy->selfTime())
61 , m_calls(nodeToCopy->calls())
9dae56ea
A
62{
63}
64
14957cd0 65ProfileNode* ProfileNode::willExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
9dae56ea
A
66{
67 for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) {
68 if ((*currentChild)->callIdentifier() == callIdentifier) {
69 (*currentChild)->startTimer();
70 return (*currentChild).get();
71 }
72 }
73
14957cd0 74 RefPtr<ProfileNode> newChild = ProfileNode::create(callerCallFrame, callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head.
9dae56ea
A
75 if (m_children.size())
76 m_children.last()->setNextSibling(newChild.get());
77 m_children.append(newChild.release());
78 return m_children.last().get();
79}
80
81ProfileNode* ProfileNode::didExecute()
82{
83 endAndRecordCall();
84 return m_parent;
85}
86
87void ProfileNode::addChild(PassRefPtr<ProfileNode> prpChild)
88{
89 RefPtr<ProfileNode> child = prpChild;
90 child->setParent(this);
91 if (m_children.size())
92 m_children.last()->setNextSibling(child.get());
93 m_children.append(child.release());
94}
95
9dae56ea
A
96void ProfileNode::removeChild(ProfileNode* node)
97{
98 if (!node)
99 return;
100
101 for (size_t i = 0; i < m_children.size(); ++i) {
102 if (*node == m_children[i].get()) {
103 m_children.remove(i);
104 break;
105 }
106 }
107
108 resetChildrensSiblings();
109}
110
111void ProfileNode::insertNode(PassRefPtr<ProfileNode> prpNode)
112{
113 RefPtr<ProfileNode> node = prpNode;
114
115 for (unsigned i = 0; i < m_children.size(); ++i)
116 node->addChild(m_children[i].release());
117
118 m_children.clear();
119 m_children.append(node.release());
120}
121
122void ProfileNode::stopProfiling()
123{
81345200 124 ASSERT(!m_calls.isEmpty());
9dae56ea 125
81345200
A
126 if (isnan(m_calls.last().totalTime()))
127 endAndRecordCall();
9dae56ea
A
128
129 // Because we iterate in post order all of our children have been stopped before us.
130 for (unsigned i = 0; i < m_children.size(); ++i)
81345200 131 m_selfTime += m_children[i]->totalTime();
9dae56ea 132
81345200
A
133 ASSERT(m_selfTime <= m_totalTime);
134 m_selfTime = m_totalTime - m_selfTime;
9dae56ea
A
135}
136
137ProfileNode* ProfileNode::traverseNextNodePostOrder() const
138{
139 ProfileNode* next = m_nextSibling;
140 if (!next)
141 return m_parent;
142 while (ProfileNode* firstChild = next->firstChild())
143 next = firstChild;
144 return next;
145}
146
9dae56ea
A
147void ProfileNode::endAndRecordCall()
148{
81345200
A
149 Call& last = lastCall();
150 ASSERT(isnan(last.totalTime()));
151
152 last.setTotalTime(currentTime() - last.startTime());
9dae56ea 153
81345200 154 m_totalTime += last.totalTime();
9dae56ea
A
155}
156
157void ProfileNode::startTimer()
158{
81345200 159 m_calls.append(Call(currentTime()));
9dae56ea
A
160}
161
162void ProfileNode::resetChildrensSiblings()
163{
164 unsigned size = m_children.size();
165 for (unsigned i = 0; i < size; ++i)
166 m_children[i]->setNextSibling(i + 1 == size ? 0 : m_children[i + 1].get());
167}
168
169#ifndef NDEBUG
170void ProfileNode::debugPrintData(int indentLevel) const
171{
172 // Print function names
173 for (int i = 0; i < indentLevel; ++i)
93a37866 174 dataLogF(" ");
9dae56ea 175
81345200
A
176 dataLogF("Function Name %s %zu SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% Next Sibling %s\n",
177 functionName().utf8().data(),
178 numberOfCalls(), m_selfTime, selfPercent(), m_totalTime, totalPercent(),
14957cd0 179 m_nextSibling ? m_nextSibling->functionName().utf8().data() : "");
9dae56ea
A
180
181 ++indentLevel;
182
183 // Print children's names and information
184 for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
185 (*currentChild)->debugPrintData(indentLevel);
186}
187
188// print the profiled data in a format that matches the tool sample's output.
189double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount& countedFunctions) const
190{
93a37866 191 dataLogF(" ");
9dae56ea
A
192
193 // Print function names
14957cd0 194 const char* name = functionName().utf8().data();
81345200 195 double sampleCount = m_totalTime * 1000;
9dae56ea
A
196 if (indentLevel) {
197 for (int i = 0; i < indentLevel; ++i)
93a37866 198 dataLogF(" ");
9dae56ea 199
14957cd0 200 countedFunctions.add(functionName().impl());
9dae56ea 201
93a37866 202 dataLogF("%.0f %s\n", sampleCount ? sampleCount : 1, name);
9dae56ea 203 } else
93a37866 204 dataLogF("%s\n", name);
9dae56ea
A
205
206 ++indentLevel;
207
208 // Print children's names and information
209 double sumOfChildrensCount = 0.0;
210 for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
211 sumOfChildrensCount += (*currentChild)->debugPrintDataSampleStyle(indentLevel, countedFunctions);
212
213 sumOfChildrensCount *= 1000; //
214 // Print remainder of samples to match sample's output
215 if (sumOfChildrensCount < sampleCount) {
93a37866 216 dataLogF(" ");
9dae56ea 217 while (indentLevel--)
93a37866 218 dataLogF(" ");
9dae56ea 219
93a37866 220 dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
9dae56ea
A
221 }
222
81345200 223 return m_totalTime;
9dae56ea
A
224}
225#endif
226
227} // namespace JSC