]>
Commit | Line | Data |
---|---|---|
6fe7ccc8 A |
1 | /* |
2 | * Copyright (C) 2012 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 | #ifndef ProfileTreeNode_h | |
27 | #define ProfileTreeNode_h | |
28 | ||
29 | namespace JSC { | |
30 | ||
31 | class ProfileTreeNode { | |
32 | typedef HashMap<String, ProfileTreeNode> Map; | |
33 | typedef std::pair<String, ProfileTreeNode> MapEntry; | |
34 | ||
35 | public: | |
36 | ProfileTreeNode() | |
37 | : m_count(0) | |
38 | , m_children(0) | |
39 | { | |
40 | } | |
41 | ||
42 | ~ProfileTreeNode() | |
43 | { | |
44 | delete m_children; | |
45 | } | |
46 | ||
47 | ProfileTreeNode* sampleChild(const char* name) | |
48 | { | |
49 | if (!m_children) | |
50 | m_children = new Map(); | |
51 | ||
52 | ProfileTreeNode newEntry; | |
53 | Map::AddResult result = m_children->add(String(name), newEntry); | |
54 | ProfileTreeNode* childInMap = &result.iterator->second; | |
55 | ++childInMap->m_count; | |
56 | return childInMap; | |
57 | } | |
58 | ||
59 | void dump() | |
60 | { | |
61 | dumpInternal(0); | |
62 | } | |
63 | ||
64 | uint64_t count() | |
65 | { | |
66 | return m_count; | |
67 | } | |
68 | ||
69 | uint64_t childCount() | |
70 | { | |
71 | if (!m_children) | |
72 | return 0; | |
73 | uint64_t childCount = 0; | |
74 | for (Map::iterator it = m_children->begin(); it != m_children->end(); ++it) | |
75 | childCount += it->second.count(); | |
76 | return childCount; | |
77 | } | |
78 | ||
79 | private: | |
80 | void dumpInternal(unsigned indent) | |
81 | { | |
82 | if (!m_children) | |
83 | return; | |
84 | ||
85 | // Copy pointers to all children into a vector, and sort the vector by sample count. | |
86 | Vector<MapEntry*> entries; | |
87 | for (Map::iterator it = m_children->begin(); it != m_children->end(); ++it) | |
88 | entries.append(&*it); | |
89 | qsort(entries.begin(), entries.size(), sizeof(MapEntry*), compareEntries); | |
90 | ||
91 | // Iterate over the children in sample-frequency order. | |
92 | for (size_t e = 0; e < entries.size(); ++e) { | |
93 | MapEntry* entry = entries[e]; | |
94 | ||
95 | // Print the number of samples, the name of this node, and the number of samples that are stack-top | |
96 | // in this node (samples directly within this node, excluding samples in children. | |
97 | for (unsigned i = 0; i < indent; ++i) | |
98 | dataLog(" "); | |
99 | dataLog("% 8lld: %s (%lld stack top)\n", | |
100 | static_cast<long long>(entry->second.count()), | |
101 | entry->first.utf8().data(), | |
102 | static_cast<long long>(entry->second.count() - entry->second.childCount())); | |
103 | ||
104 | // Recursively dump the child nodes. | |
105 | entry->second.dumpInternal(indent + 1); | |
106 | } | |
107 | } | |
108 | ||
109 | static int compareEntries(const void* a, const void* b) | |
110 | { | |
111 | uint64_t da = (*static_cast<MapEntry* const *>(a))->second.count(); | |
112 | uint64_t db = (*static_cast<MapEntry* const *>(b))->second.count(); | |
113 | return (da < db) - (da > db); | |
114 | } | |
115 | ||
116 | uint64_t m_count; | |
117 | Map* m_children; | |
118 | }; | |
119 | ||
120 | } | |
121 | ||
122 | #endif // ProfileTreeNode_h | |
123 |