]>
Commit | Line | Data |
---|---|---|
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 |
37 | using namespace WTF; |
38 | ||
9dae56ea A |
39 | namespace JSC { |
40 | ||
ed1e77d3 | 41 | ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode) |
14957cd0 A |
42 | : m_callerCallFrame(callerCallFrame) |
43 | , m_callIdentifier(callIdentifier) | |
9dae56ea | 44 | , m_parent(parentNode) |
ed1e77d3 | 45 | #ifndef NDEBUG |
81345200 | 46 | , m_nextSibling(nullptr) |
ed1e77d3 | 47 | #endif |
9dae56ea | 48 | { |
9dae56ea A |
49 | } |
50 | ||
ed1e77d3 | 51 | ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy) |
14957cd0 A |
52 | : m_callerCallFrame(callerCallFrame) |
53 | , m_callIdentifier(nodeToCopy->callIdentifier()) | |
9dae56ea | 54 | , m_parent(nodeToCopy->parent()) |
81345200 | 55 | , m_calls(nodeToCopy->calls()) |
ed1e77d3 A |
56 | #ifndef NDEBUG |
57 | , m_nextSibling(nullptr) | |
58 | #endif | |
9dae56ea A |
59 | { |
60 | } | |
61 | ||
9dae56ea A |
62 | void ProfileNode::addChild(PassRefPtr<ProfileNode> prpChild) |
63 | { | |
64 | RefPtr<ProfileNode> child = prpChild; | |
65 | child->setParent(this); | |
ed1e77d3 | 66 | #ifndef NDEBUG |
9dae56ea A |
67 | if (m_children.size()) |
68 | m_children.last()->setNextSibling(child.get()); | |
ed1e77d3 | 69 | #endif |
9dae56ea A |
70 | m_children.append(child.release()); |
71 | } | |
72 | ||
9dae56ea A |
73 | void ProfileNode::removeChild(ProfileNode* node) |
74 | { | |
75 | if (!node) | |
76 | return; | |
77 | ||
ed1e77d3 A |
78 | m_children.removeFirstMatching([node] (const RefPtr<ProfileNode>& current) { |
79 | return *node == current.get(); | |
80 | }); | |
81 | ||
82 | #ifndef NDEBUG | |
83 | size_t size = m_children.size(); | |
84 | for (size_t i = 0; i < size; ++i) | |
85 | m_children[i]->setNextSibling(i + 1 == size ? nullptr : m_children[i + 1].get()); | |
86 | #endif | |
9dae56ea A |
87 | } |
88 | ||
ed1e77d3 | 89 | void ProfileNode::spliceNode(PassRefPtr<ProfileNode> prpNode) |
9dae56ea A |
90 | { |
91 | RefPtr<ProfileNode> node = prpNode; | |
92 | ||
93 | for (unsigned i = 0; i < m_children.size(); ++i) | |
94 | node->addChild(m_children[i].release()); | |
95 | ||
96 | m_children.clear(); | |
97 | m_children.append(node.release()); | |
98 | } | |
99 | ||
ed1e77d3 | 100 | #ifndef NDEBUG |
9dae56ea A |
101 | ProfileNode* ProfileNode::traverseNextNodePostOrder() const |
102 | { | |
103 | ProfileNode* next = m_nextSibling; | |
104 | if (!next) | |
105 | return m_parent; | |
106 | while (ProfileNode* firstChild = next->firstChild()) | |
107 | next = firstChild; | |
108 | return next; | |
109 | } | |
110 | ||
ed1e77d3 | 111 | void ProfileNode::debugPrint() |
9dae56ea | 112 | { |
ed1e77d3 A |
113 | CalculateProfileSubtreeDataFunctor functor; |
114 | forEachNodePostorder(functor); | |
115 | ProfileNode::ProfileSubtreeData data = functor.returnValue(); | |
9dae56ea | 116 | |
ed1e77d3 | 117 | debugPrintRecursively(0, data); |
9dae56ea A |
118 | } |
119 | ||
ed1e77d3 | 120 | void ProfileNode::debugPrintSampleStyle() |
9dae56ea | 121 | { |
ed1e77d3 | 122 | FunctionCallHashCount countedFunctions; |
9dae56ea | 123 | |
ed1e77d3 A |
124 | CalculateProfileSubtreeDataFunctor functor; |
125 | forEachNodePostorder(functor); | |
126 | ProfileNode::ProfileSubtreeData data = functor.returnValue(); | |
127 | ||
128 | debugPrintSampleStyleRecursively(0, countedFunctions, data); | |
9dae56ea A |
129 | } |
130 | ||
ed1e77d3 | 131 | void ProfileNode::debugPrintRecursively(int indentLevel, const ProfileSubtreeData& data) |
9dae56ea A |
132 | { |
133 | // Print function names | |
134 | for (int i = 0; i < indentLevel; ++i) | |
93a37866 | 135 | dataLogF(" "); |
9dae56ea | 136 | |
ed1e77d3 A |
137 | auto it = data.selfAndTotalTimes.find(this); |
138 | ASSERT(it != data.selfAndTotalTimes.end()); | |
139 | ||
140 | double nodeSelfTime = it->value.first; | |
141 | double nodeTotalTime = it->value.second; | |
142 | double rootTotalTime = data.rootTotalTime; | |
143 | ||
81345200 A |
144 | dataLogF("Function Name %s %zu SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% Next Sibling %s\n", |
145 | functionName().utf8().data(), | |
ed1e77d3 | 146 | m_calls.size(), nodeSelfTime, nodeSelfTime / rootTotalTime * 100.0, nodeTotalTime, nodeTotalTime / rootTotalTime * 100.0, |
14957cd0 | 147 | m_nextSibling ? m_nextSibling->functionName().utf8().data() : ""); |
9dae56ea A |
148 | |
149 | ++indentLevel; | |
150 | ||
151 | // Print children's names and information | |
152 | for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) | |
ed1e77d3 | 153 | (*currentChild)->debugPrintRecursively(indentLevel, data); |
9dae56ea A |
154 | } |
155 | ||
156 | // print the profiled data in a format that matches the tool sample's output. | |
ed1e77d3 | 157 | double ProfileNode::debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount& countedFunctions, const ProfileSubtreeData& data) |
9dae56ea | 158 | { |
93a37866 | 159 | dataLogF(" "); |
9dae56ea | 160 | |
ed1e77d3 A |
161 | auto it = data.selfAndTotalTimes.find(this); |
162 | ASSERT(it != data.selfAndTotalTimes.end()); | |
163 | double nodeTotalTime = it->value.second; | |
164 | ||
9dae56ea | 165 | // Print function names |
14957cd0 | 166 | const char* name = functionName().utf8().data(); |
ed1e77d3 | 167 | double sampleCount = nodeTotalTime * 1000; |
9dae56ea A |
168 | if (indentLevel) { |
169 | for (int i = 0; i < indentLevel; ++i) | |
93a37866 | 170 | dataLogF(" "); |
9dae56ea | 171 | |
14957cd0 | 172 | countedFunctions.add(functionName().impl()); |
9dae56ea | 173 | |
93a37866 | 174 | dataLogF("%.0f %s\n", sampleCount ? sampleCount : 1, name); |
9dae56ea | 175 | } else |
93a37866 | 176 | dataLogF("%s\n", name); |
9dae56ea A |
177 | |
178 | ++indentLevel; | |
179 | ||
180 | // Print children's names and information | |
181 | double sumOfChildrensCount = 0.0; | |
182 | for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) | |
ed1e77d3 | 183 | sumOfChildrensCount += (*currentChild)->debugPrintSampleStyleRecursively(indentLevel, countedFunctions, data); |
9dae56ea A |
184 | |
185 | sumOfChildrensCount *= 1000; // | |
186 | // Print remainder of samples to match sample's output | |
187 | if (sumOfChildrensCount < sampleCount) { | |
93a37866 | 188 | dataLogF(" "); |
9dae56ea | 189 | while (indentLevel--) |
93a37866 | 190 | dataLogF(" "); |
9dae56ea | 191 | |
93a37866 | 192 | dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data()); |
9dae56ea A |
193 | } |
194 | ||
ed1e77d3 | 195 | return nodeTotalTime; |
9dae56ea A |
196 | } |
197 | #endif | |
198 | ||
199 | } // namespace JSC |