Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: src/profile-generator.cc

Issue 910002: Start migrating profiles processing to C++. (Closed)
Patch Set: Comments addressed Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "v8.h"
29
30 #include "profile-generator-inl.h"
31
32
33 namespace v8 {
34 namespace internal {
35
36
37 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
38 HashMap::Entry* map_entry =
39 children_.Lookup(entry, CodeEntryHash(entry), false);
40 return map_entry != NULL ?
41 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL;
42 }
43
44
45 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) {
46 HashMap::Entry* map_entry =
47 children_.Lookup(entry, CodeEntryHash(entry), true);
48 if (map_entry->value == NULL) {
49 // New node added.
50 map_entry->value = new ProfileNode(entry);
51 }
52 return reinterpret_cast<ProfileNode*>(map_entry->value);
53 }
54
55
56 void ProfileNode::Print(int indent) {
57 OS::Print("%4u %4u %*c %s\n",
58 total_ticks_, self_ticks_,
59 indent, ' ',
60 entry_ != NULL ? entry_->name() : "");
61 for (HashMap::Entry* p = children_.Start();
62 p != NULL;
63 p = children_.Next(p)) {
64 reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2);
65 }
66 }
67
68
69 namespace {
70
71 class DeleteNodesCallback {
72 public:
73 void AfterAllChildrenTraversed(ProfileNode* node) {
74 delete node;
75 }
76
77 void AfterChildTraversed(ProfileNode*, ProfileNode*) { }
78 };
79
80 } // namespace
81
82
83 ProfileTree::~ProfileTree() {
84 DeleteNodesCallback cb;
85 TraverseBreadthFirstPostOrder(&cb);
86 }
87
88
89 void ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) {
90 ProfileNode* node = root_;
91 for (CodeEntry** entry = path.start() + path.length() - 1;
92 entry != path.start() - 1;
93 --entry) {
94 if (*entry != NULL) {
95 node = node->FindOrAddChild(*entry);
96 }
97 }
98 node->IncrementSelfTicks();
99 }
100
101
102 void ProfileTree::AddPathFromStart(const Vector<CodeEntry*>& path) {
103 ProfileNode* node = root_;
104 for (CodeEntry** entry = path.start();
105 entry != path.start() + path.length();
106 ++entry) {
107 if (*entry != NULL) {
108 node = node->FindOrAddChild(*entry);
109 }
110 }
111 node->IncrementSelfTicks();
112 }
113
114
115 namespace {
116
117 struct Position {
118 Position(ProfileNode* a_node, HashMap::Entry* a_p)
119 : node(a_node), p(a_p) { }
120 INLINE(ProfileNode* current_child()) {
121 return reinterpret_cast<ProfileNode*>(p->value);
122 }
123 ProfileNode* node;
124 HashMap::Entry* p;
125 };
126
127 } // namespace
128
129
130 template <typename Callback>
131 void ProfileTree::TraverseBreadthFirstPostOrder(Callback* callback) {
132 List<Position> stack(10);
133 stack.Add(Position(root_, root_->children_.Start()));
134 do {
135 Position& current = stack.last();
136 if (current.p != NULL) {
137 stack.Add(Position(current.current_child(),
138 current.current_child()->children_.Start()));
139 } else {
140 callback->AfterAllChildrenTraversed(current.node);
141 if (stack.length() > 1) {
142 Position& parent = stack[stack.length() - 2];
143 callback->AfterChildTraversed(parent.node, current.node);
Finnur 2011/03/25 15:18:48 If the callback is a DeleteNodesCallback, then we'
mnaganov (inactive) 2011/03/28 08:16:37 You are right. But in DeleteNodesCallback, AfterCh
144 parent.p = parent.node->children_.Next(parent.p);
145 // Remove child from the stack.
146 stack.RemoveLast();
147 }
148 }
149 } while (stack.length() > 1 || stack.last().p != NULL);
150 }
151
152
153 namespace {
154
155 class CalculateTotalTicksCallback {
156 public:
157 void AfterAllChildrenTraversed(ProfileNode* node) {
158 node->IncreaseTotalTicks(node->self_ticks());
159 }
160
161 void AfterChildTraversed(ProfileNode* parent, ProfileNode* child) {
162 parent->IncreaseTotalTicks(child->total_ticks());
163 }
164 };
165
166 } // namespace
167
168
169 // Non-recursive implementation of breadth-first tree traversal.
170 void ProfileTree::CalculateTotalTicks() {
171 CalculateTotalTicksCallback cb;
172 TraverseBreadthFirstPostOrder(&cb);
173 }
174
175
176 void ProfileTree::ShortPrint() {
177 OS::Print("root: %u %u\n", root_->total_ticks(), root_->self_ticks());
178 }
179
180
181 void CpuProfile::AddPath(const Vector<CodeEntry*>& path) {
182 top_down_.AddPathFromEnd(path);
183 bottom_up_.AddPathFromStart(path);
184 }
185
186
187 void CpuProfile::CalculateTotalTicks() {
188 top_down_.CalculateTotalTicks();
189 bottom_up_.CalculateTotalTicks();
190 }
191
192
193 void CpuProfile::ShortPrint() {
194 OS::Print("top down ");
195 top_down_.ShortPrint();
196 OS::Print("bottom up ");
197 bottom_up_.ShortPrint();
198 }
199
200
201 void CpuProfile::Print() {
202 OS::Print("[Top down]:\n");
203 top_down_.Print();
204 OS::Print("[Bottom up]:\n");
205 bottom_up_.Print();
206 }
207
208
209 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL;
210 const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue =
211 CodeMap::CodeEntryInfo(NULL, 0);
212
213
214 void CodeMap::AddAlias(Address alias, Address addr) {
215 CodeTree::Locator locator;
216 if (tree_.Find(addr, &locator)) {
217 const CodeEntryInfo& entry_info = locator.value();
218 tree_.Insert(alias, &locator);
219 locator.set_value(entry_info);
220 }
221 }
222
223
224 CodeEntry* CodeMap::FindEntry(Address addr) {
225 CodeTree::Locator locator;
226 if (tree_.FindGreatestLessThan(addr, &locator)) {
227 // locator.key() <= addr. Need to check that addr is within entry.
228 const CodeEntryInfo& entry = locator.value();
229 if (addr < (locator.key() + entry.size))
230 return entry.entry;
231 }
232 return NULL;
233 }
234
235
236 ProfileGenerator::ProfileGenerator()
237 : resource_names_(StringsMatch) {
238 }
239
240
241 static void CodeEntriesDeleter(CodeEntry** entry_ptr) {
242 delete *entry_ptr;
243 }
244
245
246 ProfileGenerator::~ProfileGenerator() {
247 for (HashMap::Entry* p = resource_names_.Start();
248 p != NULL;
249 p = resource_names_.Next(p)) {
250 DeleteArray(reinterpret_cast<const char*>(p->value));
251 }
252
253 code_entries_.Iterate(CodeEntriesDeleter);
254 }
255
256
257 CodeEntry* ProfileGenerator::NewCodeEntry(
258 Logger::LogEventsAndTags tag,
259 String* name,
260 String* resource_name, int line_number) {
261 const char* cached_resource_name = NULL;
262 if (resource_name->IsString()) {
263 // As we copy contents of resource names, and usually they are repeated,
264 // we cache names by string hashcode.
265 HashMap::Entry* cache_entry =
266 resource_names_.Lookup(resource_name,
267 StringEntryHash(resource_name),
268 true);
269 if (cache_entry->value == NULL) {
270 // New entry added.
271 cache_entry->value =
272 resource_name->ToCString(DISALLOW_NULLS,
273 ROBUST_STRING_TRAVERSAL).Detach();
274 }
275 cached_resource_name = reinterpret_cast<const char*>(cache_entry->value);
276 }
277
278 CodeEntry* entry = new ManagedNameCodeEntry(tag,
279 name,
280 cached_resource_name,
281 line_number);
282 code_entries_.Add(entry);
283 return entry;
284 }
285
286
287 CodeEntry* ProfileGenerator::NewCodeEntry(
288 Logger::LogEventsAndTags tag,
289 const char* name) {
290 CodeEntry* entry = new StaticNameCodeEntry(tag, name);
291 code_entries_.Add(entry);
292 return entry;
293 }
294
295 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698