1 | /* |
2 | * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
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 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #include "config.h" |
27 | #include "Profile.h" |
28 | |
29 | #include "ProfileNode.h" |
30 | #include <stdio.h> |
31 | |
32 | namespace JSC { |
33 | |
34 | PassRefPtr<Profile> Profile::create(const UString& title, unsigned uid) |
35 | { |
36 | return adoptRef(p: new Profile(title, uid)); |
37 | } |
38 | |
39 | Profile::Profile(const UString& title, unsigned uid) |
40 | : m_title(title) |
41 | , m_uid(uid) |
42 | { |
43 | // FIXME: When multi-threading is supported this will be a vector and calls |
44 | // into the profiler will need to know which thread it is executing on. |
45 | m_head = ProfileNode::create(callIdentifier: CallIdentifier("Thread_1" , 0, 0), headNode: 0, parentNode: 0); |
46 | } |
47 | |
48 | Profile::~Profile() |
49 | { |
50 | } |
51 | |
52 | void Profile::forEach(void (ProfileNode::*function)()) |
53 | { |
54 | ProfileNode* currentNode = m_head->firstChild(); |
55 | for (ProfileNode* nextNode = currentNode; nextNode; nextNode = nextNode->firstChild()) |
56 | currentNode = nextNode; |
57 | |
58 | if (!currentNode) |
59 | currentNode = m_head.get(); |
60 | |
61 | ProfileNode* endNode = m_head->traverseNextNodePostOrder(); |
62 | while (currentNode && currentNode != endNode) { |
63 | (currentNode->*function)(); |
64 | currentNode = currentNode->traverseNextNodePostOrder(); |
65 | } |
66 | } |
67 | |
68 | void Profile::focus(const ProfileNode* profileNode) |
69 | { |
70 | if (!profileNode || !m_head) |
71 | return; |
72 | |
73 | bool processChildren; |
74 | const CallIdentifier& callIdentifier = profileNode->callIdentifier(); |
75 | for (ProfileNode* currentNode = m_head.get(); currentNode; currentNode = currentNode->traverseNextNodePreOrder(processChildren)) |
76 | processChildren = currentNode->focus(callIdentifier); |
77 | |
78 | // Set the visible time of all nodes so that the %s display correctly. |
79 | forEach(function: &ProfileNode::calculateVisibleTotalTime); |
80 | } |
81 | |
82 | void Profile::exclude(const ProfileNode* profileNode) |
83 | { |
84 | if (!profileNode || !m_head) |
85 | return; |
86 | |
87 | const CallIdentifier& callIdentifier = profileNode->callIdentifier(); |
88 | |
89 | for (ProfileNode* currentNode = m_head.get(); currentNode; currentNode = currentNode->traverseNextNodePreOrder()) |
90 | currentNode->exclude(callIdentifier); |
91 | |
92 | // Set the visible time of the head so the %s display correctly. |
93 | m_head->setVisibleTotalTime(m_head->totalTime() - m_head->selfTime()); |
94 | m_head->setVisibleSelfTime(0.0); |
95 | } |
96 | |
97 | void Profile::restoreAll() |
98 | { |
99 | forEach(function: &ProfileNode::restore); |
100 | } |
101 | |
102 | #ifndef NDEBUG |
103 | void Profile::debugPrintData() const |
104 | { |
105 | printf(format: "Call graph:\n" ); |
106 | m_head->debugPrintData(indentLevel: 0); |
107 | } |
108 | |
109 | typedef pair<UString::Rep*, unsigned> NameCountPair; |
110 | |
111 | static inline bool functionNameCountPairComparator(const NameCountPair& a, const NameCountPair& b) |
112 | { |
113 | return a.second > b.second; |
114 | } |
115 | |
116 | void Profile::debugPrintDataSampleStyle() const |
117 | { |
118 | typedef Vector<NameCountPair> NameCountPairVector; |
119 | |
120 | FunctionCallHashCount countedFunctions; |
121 | printf(format: "Call graph:\n" ); |
122 | m_head->debugPrintDataSampleStyle(indentLevel: 0, countedFunctions); |
123 | |
124 | printf(format: "\nTotal number in stack:\n" ); |
125 | NameCountPairVector sortedFunctions(countedFunctions.size()); |
126 | copyToVector(collection: countedFunctions, vector&: sortedFunctions); |
127 | |
128 | std::sort(first: sortedFunctions.begin(), last: sortedFunctions.end(), comp: functionNameCountPairComparator); |
129 | for (NameCountPairVector::iterator it = sortedFunctions.begin(); it != sortedFunctions.end(); ++it) |
130 | printf(format: " %-12d%s\n" , (*it).second, UString((*it).first).UTF8String().c_str()); |
131 | |
132 | printf(format: "\nSort by top of stack, same collapsed (when >= 5):\n" ); |
133 | } |
134 | #endif |
135 | |
136 | } // namespace JSC |
137 | |