OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/profiler_service.h" | 5 #include "vm/profiler_service.h" |
6 | 6 |
7 #include "vm/growable_array.h" | 7 #include "vm/growable_array.h" |
8 #include "vm/hash_map.h" | 8 #include "vm/hash_map.h" |
9 #include "vm/log.h" | 9 #include "vm/log.h" |
10 #include "vm/malloc_hooks.h" | 10 #include "vm/malloc_hooks.h" |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 } | 84 } |
85 return size; | 85 return size; |
86 } | 86 } |
87 | 87 |
88 // Array holding code that is being kept around only for the profiler. | 88 // Array holding code that is being kept around only for the profiler. |
89 const GrowableObjectArray& previous_; | 89 const GrowableObjectArray& previous_; |
90 // Array holding code that should continue to be kept around for the profiler. | 90 // Array holding code that should continue to be kept around for the profiler. |
91 const GrowableObjectArray& current_; | 91 const GrowableObjectArray& current_; |
92 }; | 92 }; |
93 | 93 |
94 | |
95 ProfileFunctionSourcePosition::ProfileFunctionSourcePosition( | 94 ProfileFunctionSourcePosition::ProfileFunctionSourcePosition( |
96 TokenPosition token_pos) | 95 TokenPosition token_pos) |
97 : token_pos_(token_pos), exclusive_ticks_(0), inclusive_ticks_(0) {} | 96 : token_pos_(token_pos), exclusive_ticks_(0), inclusive_ticks_(0) {} |
98 | 97 |
99 | |
100 void ProfileFunctionSourcePosition::Tick(bool exclusive) { | 98 void ProfileFunctionSourcePosition::Tick(bool exclusive) { |
101 if (exclusive) { | 99 if (exclusive) { |
102 exclusive_ticks_++; | 100 exclusive_ticks_++; |
103 } else { | 101 } else { |
104 inclusive_ticks_++; | 102 inclusive_ticks_++; |
105 } | 103 } |
106 } | 104 } |
107 | 105 |
108 | |
109 ProfileFunction::ProfileFunction(Kind kind, | 106 ProfileFunction::ProfileFunction(Kind kind, |
110 const char* name, | 107 const char* name, |
111 const Function& function, | 108 const Function& function, |
112 const intptr_t table_index) | 109 const intptr_t table_index) |
113 : kind_(kind), | 110 : kind_(kind), |
114 name_(name), | 111 name_(name), |
115 function_(Function::ZoneHandle(function.raw())), | 112 function_(Function::ZoneHandle(function.raw())), |
116 table_index_(table_index), | 113 table_index_(table_index), |
117 profile_codes_(0), | 114 profile_codes_(0), |
118 source_position_ticks_(0), | 115 source_position_ticks_(0), |
119 exclusive_ticks_(0), | 116 exclusive_ticks_(0), |
120 inclusive_ticks_(0), | 117 inclusive_ticks_(0), |
121 inclusive_serial_(-1) { | 118 inclusive_serial_(-1) { |
122 ASSERT((kind_ != kDartFunction) || !function_.IsNull()); | 119 ASSERT((kind_ != kDartFunction) || !function_.IsNull()); |
123 ASSERT((kind_ != kDartFunction) || (table_index_ >= 0)); | 120 ASSERT((kind_ != kDartFunction) || (table_index_ >= 0)); |
124 ASSERT(profile_codes_.length() == 0); | 121 ASSERT(profile_codes_.length() == 0); |
125 } | 122 } |
126 | 123 |
127 | |
128 const char* ProfileFunction::Name() const { | 124 const char* ProfileFunction::Name() const { |
129 if (name_ != NULL) { | 125 if (name_ != NULL) { |
130 return name_; | 126 return name_; |
131 } | 127 } |
132 ASSERT(!function_.IsNull()); | 128 ASSERT(!function_.IsNull()); |
133 const String& func_name = | 129 const String& func_name = |
134 String::Handle(function_.QualifiedUserVisibleName()); | 130 String::Handle(function_.QualifiedUserVisibleName()); |
135 return func_name.ToCString(); | 131 return func_name.ToCString(); |
136 } | 132 } |
137 | 133 |
138 | |
139 bool ProfileFunction::is_visible() const { | 134 bool ProfileFunction::is_visible() const { |
140 if (function_.IsNull()) { | 135 if (function_.IsNull()) { |
141 // Some synthetic function. | 136 // Some synthetic function. |
142 return true; | 137 return true; |
143 } | 138 } |
144 return FLAG_show_invisible_frames || function_.is_visible(); | 139 return FLAG_show_invisible_frames || function_.is_visible(); |
145 } | 140 } |
146 | 141 |
147 | |
148 void ProfileFunction::Tick(bool exclusive, | 142 void ProfileFunction::Tick(bool exclusive, |
149 intptr_t inclusive_serial, | 143 intptr_t inclusive_serial, |
150 TokenPosition token_position) { | 144 TokenPosition token_position) { |
151 if (exclusive) { | 145 if (exclusive) { |
152 exclusive_ticks_++; | 146 exclusive_ticks_++; |
153 TickSourcePosition(token_position, exclusive); | 147 TickSourcePosition(token_position, exclusive); |
154 } | 148 } |
155 // Fall through and tick inclusive count too. | 149 // Fall through and tick inclusive count too. |
156 if (inclusive_serial_ == inclusive_serial) { | 150 if (inclusive_serial_ == inclusive_serial) { |
157 // Already ticked. | 151 // Already ticked. |
158 return; | 152 return; |
159 } | 153 } |
160 inclusive_serial_ = inclusive_serial; | 154 inclusive_serial_ = inclusive_serial; |
161 inclusive_ticks_++; | 155 inclusive_ticks_++; |
162 TickSourcePosition(token_position, false); | 156 TickSourcePosition(token_position, false); |
163 } | 157 } |
164 | 158 |
165 | |
166 void ProfileFunction::TickSourcePosition(TokenPosition token_position, | 159 void ProfileFunction::TickSourcePosition(TokenPosition token_position, |
167 bool exclusive) { | 160 bool exclusive) { |
168 intptr_t i = 0; | 161 intptr_t i = 0; |
169 for (; i < source_position_ticks_.length(); i++) { | 162 for (; i < source_position_ticks_.length(); i++) { |
170 ProfileFunctionSourcePosition& position = source_position_ticks_[i]; | 163 ProfileFunctionSourcePosition& position = source_position_ticks_[i]; |
171 if (position.token_pos().value() == token_position.value()) { | 164 if (position.token_pos().value() == token_position.value()) { |
172 if (FLAG_trace_profiler_verbose) { | 165 if (FLAG_trace_profiler_verbose) { |
173 OS::Print("Ticking source position %s %s\n", | 166 OS::Print("Ticking source position %s %s\n", |
174 exclusive ? "exclusive" : "inclusive", | 167 exclusive ? "exclusive" : "inclusive", |
175 token_position.ToCString()); | 168 token_position.ToCString()); |
(...skipping 16 matching lines...) Expand all Loading... |
192 } | 185 } |
193 pfsp.Tick(exclusive); | 186 pfsp.Tick(exclusive); |
194 | 187 |
195 if (i < source_position_ticks_.length()) { | 188 if (i < source_position_ticks_.length()) { |
196 source_position_ticks_.InsertAt(i, pfsp); | 189 source_position_ticks_.InsertAt(i, pfsp); |
197 } else { | 190 } else { |
198 source_position_ticks_.Add(pfsp); | 191 source_position_ticks_.Add(pfsp); |
199 } | 192 } |
200 } | 193 } |
201 | 194 |
202 | |
203 const char* ProfileFunction::KindToCString(Kind kind) { | 195 const char* ProfileFunction::KindToCString(Kind kind) { |
204 switch (kind) { | 196 switch (kind) { |
205 case kDartFunction: | 197 case kDartFunction: |
206 return "Dart"; | 198 return "Dart"; |
207 case kNativeFunction: | 199 case kNativeFunction: |
208 return "Native"; | 200 return "Native"; |
209 case kTagFunction: | 201 case kTagFunction: |
210 return "Tag"; | 202 return "Tag"; |
211 case kStubFunction: | 203 case kStubFunction: |
212 return "Stub"; | 204 return "Stub"; |
213 case kUnknownFunction: | 205 case kUnknownFunction: |
214 return "Collected"; | 206 return "Collected"; |
215 default: | 207 default: |
216 UNIMPLEMENTED(); | 208 UNIMPLEMENTED(); |
217 return ""; | 209 return ""; |
218 } | 210 } |
219 } | 211 } |
220 | 212 |
221 | |
222 void ProfileFunction::PrintToJSONObject(JSONObject* func) { | 213 void ProfileFunction::PrintToJSONObject(JSONObject* func) { |
223 func->AddProperty("type", "@Function"); | 214 func->AddProperty("type", "@Function"); |
224 func->AddProperty("name", name()); | 215 func->AddProperty("name", name()); |
225 func->AddProperty("_kind", KindToCString(kind())); | 216 func->AddProperty("_kind", KindToCString(kind())); |
226 } | 217 } |
227 | 218 |
228 | |
229 void ProfileFunction::PrintToJSONArray(JSONArray* functions) { | 219 void ProfileFunction::PrintToJSONArray(JSONArray* functions) { |
230 JSONObject obj(functions); | 220 JSONObject obj(functions); |
231 obj.AddProperty("kind", KindToCString(kind())); | 221 obj.AddProperty("kind", KindToCString(kind())); |
232 obj.AddProperty("inclusiveTicks", inclusive_ticks()); | 222 obj.AddProperty("inclusiveTicks", inclusive_ticks()); |
233 obj.AddProperty("exclusiveTicks", exclusive_ticks()); | 223 obj.AddProperty("exclusiveTicks", exclusive_ticks()); |
234 if (kind() == kDartFunction) { | 224 if (kind() == kDartFunction) { |
235 ASSERT(!function_.IsNull()); | 225 ASSERT(!function_.IsNull()); |
236 obj.AddProperty("function", function_); | 226 obj.AddProperty("function", function_); |
237 } else { | 227 } else { |
238 JSONObject func(&obj, "function"); | 228 JSONObject func(&obj, "function"); |
239 PrintToJSONObject(&func); | 229 PrintToJSONObject(&func); |
240 } | 230 } |
241 { | 231 { |
242 JSONArray codes(&obj, "codes"); | 232 JSONArray codes(&obj, "codes"); |
243 for (intptr_t i = 0; i < profile_codes_.length(); i++) { | 233 for (intptr_t i = 0; i < profile_codes_.length(); i++) { |
244 intptr_t code_index = profile_codes_[i]; | 234 intptr_t code_index = profile_codes_[i]; |
245 codes.AddValue(code_index); | 235 codes.AddValue(code_index); |
246 } | 236 } |
247 } | 237 } |
248 } | 238 } |
249 | 239 |
250 | |
251 void ProfileFunction::AddProfileCode(intptr_t code_table_index) { | 240 void ProfileFunction::AddProfileCode(intptr_t code_table_index) { |
252 for (intptr_t i = 0; i < profile_codes_.length(); i++) { | 241 for (intptr_t i = 0; i < profile_codes_.length(); i++) { |
253 if (profile_codes_[i] == code_table_index) { | 242 if (profile_codes_[i] == code_table_index) { |
254 return; | 243 return; |
255 } | 244 } |
256 } | 245 } |
257 profile_codes_.Add(code_table_index); | 246 profile_codes_.Add(code_table_index); |
258 } | 247 } |
259 | 248 |
260 | |
261 bool ProfileFunction::GetSinglePosition(ProfileFunctionSourcePosition* pfsp) { | 249 bool ProfileFunction::GetSinglePosition(ProfileFunctionSourcePosition* pfsp) { |
262 if (pfsp == NULL) { | 250 if (pfsp == NULL) { |
263 return false; | 251 return false; |
264 } | 252 } |
265 if (source_position_ticks_.length() != 1) { | 253 if (source_position_ticks_.length() != 1) { |
266 return false; | 254 return false; |
267 } | 255 } |
268 *pfsp = source_position_ticks_[0]; | 256 *pfsp = source_position_ticks_[0]; |
269 return true; | 257 return true; |
270 } | 258 } |
271 | 259 |
272 | |
273 ProfileCodeAddress::ProfileCodeAddress(uword pc) | 260 ProfileCodeAddress::ProfileCodeAddress(uword pc) |
274 : pc_(pc), exclusive_ticks_(0), inclusive_ticks_(0) {} | 261 : pc_(pc), exclusive_ticks_(0), inclusive_ticks_(0) {} |
275 | 262 |
276 | |
277 void ProfileCodeAddress::Tick(bool exclusive) { | 263 void ProfileCodeAddress::Tick(bool exclusive) { |
278 if (exclusive) { | 264 if (exclusive) { |
279 exclusive_ticks_++; | 265 exclusive_ticks_++; |
280 } else { | 266 } else { |
281 inclusive_ticks_++; | 267 inclusive_ticks_++; |
282 } | 268 } |
283 } | 269 } |
284 | 270 |
285 | |
286 ProfileCode::ProfileCode(Kind kind, | 271 ProfileCode::ProfileCode(Kind kind, |
287 uword start, | 272 uword start, |
288 uword end, | 273 uword end, |
289 int64_t timestamp, | 274 int64_t timestamp, |
290 const Code& code) | 275 const Code& code) |
291 : kind_(kind), | 276 : kind_(kind), |
292 start_(start), | 277 start_(start), |
293 end_(end), | 278 end_(end), |
294 exclusive_ticks_(0), | 279 exclusive_ticks_(0), |
295 inclusive_ticks_(0), | 280 inclusive_ticks_(0), |
296 inclusive_serial_(-1), | 281 inclusive_serial_(-1), |
297 code_(code), | 282 code_(code), |
298 name_(NULL), | 283 name_(NULL), |
299 compile_timestamp_(0), | 284 compile_timestamp_(0), |
300 function_(NULL), | 285 function_(NULL), |
301 code_table_index_(-1), | 286 code_table_index_(-1), |
302 address_ticks_(0) {} | 287 address_ticks_(0) {} |
303 | 288 |
304 | |
305 void ProfileCode::TruncateLower(uword start) { | 289 void ProfileCode::TruncateLower(uword start) { |
306 if (start > start_) { | 290 if (start > start_) { |
307 start_ = start; | 291 start_ = start; |
308 } | 292 } |
309 ASSERT(start_ < end_); | 293 ASSERT(start_ < end_); |
310 } | 294 } |
311 | 295 |
312 | |
313 void ProfileCode::TruncateUpper(uword end) { | 296 void ProfileCode::TruncateUpper(uword end) { |
314 if (end < end_) { | 297 if (end < end_) { |
315 end_ = end; | 298 end_ = end; |
316 } | 299 } |
317 ASSERT(start_ < end_); | 300 ASSERT(start_ < end_); |
318 } | 301 } |
319 | 302 |
320 | |
321 void ProfileCode::ExpandLower(uword start) { | 303 void ProfileCode::ExpandLower(uword start) { |
322 if (start < start_) { | 304 if (start < start_) { |
323 start_ = start; | 305 start_ = start; |
324 } | 306 } |
325 ASSERT(start_ < end_); | 307 ASSERT(start_ < end_); |
326 } | 308 } |
327 | 309 |
328 | |
329 void ProfileCode::ExpandUpper(uword end) { | 310 void ProfileCode::ExpandUpper(uword end) { |
330 if (end > end_) { | 311 if (end > end_) { |
331 end_ = end; | 312 end_ = end; |
332 } | 313 } |
333 ASSERT(start_ < end_); | 314 ASSERT(start_ < end_); |
334 } | 315 } |
335 | 316 |
336 | |
337 bool ProfileCode::Overlaps(const ProfileCode* other) const { | 317 bool ProfileCode::Overlaps(const ProfileCode* other) const { |
338 ASSERT(other != NULL); | 318 ASSERT(other != NULL); |
339 return other->Contains(start_) || other->Contains(end_ - 1) || | 319 return other->Contains(start_) || other->Contains(end_ - 1) || |
340 Contains(other->start()) || Contains(other->end() - 1); | 320 Contains(other->start()) || Contains(other->end() - 1); |
341 } | 321 } |
342 | 322 |
343 | |
344 bool ProfileCode::IsOptimizedDart() const { | 323 bool ProfileCode::IsOptimizedDart() const { |
345 return !code_.IsNull() && code_.is_optimized(); | 324 return !code_.IsNull() && code_.is_optimized(); |
346 } | 325 } |
347 | 326 |
348 | |
349 void ProfileCode::SetName(const char* name) { | 327 void ProfileCode::SetName(const char* name) { |
350 if (name == NULL) { | 328 if (name == NULL) { |
351 name_ = NULL; | 329 name_ = NULL; |
352 } | 330 } |
353 intptr_t len = strlen(name); | 331 intptr_t len = strlen(name); |
354 name_ = Thread::Current()->zone()->Alloc<char>(len + 1); | 332 name_ = Thread::Current()->zone()->Alloc<char>(len + 1); |
355 strncpy(name_, name, len); | 333 strncpy(name_, name, len); |
356 name_[len] = '\0'; | 334 name_[len] = '\0'; |
357 } | 335 } |
358 | 336 |
359 | |
360 void ProfileCode::GenerateAndSetSymbolName(const char* prefix) { | 337 void ProfileCode::GenerateAndSetSymbolName(const char* prefix) { |
361 const intptr_t kBuffSize = 512; | 338 const intptr_t kBuffSize = 512; |
362 char buff[kBuffSize]; | 339 char buff[kBuffSize]; |
363 OS::SNPrint(&buff[0], kBuffSize - 1, "%s [%" Px ", %" Px ")", prefix, start(), | 340 OS::SNPrint(&buff[0], kBuffSize - 1, "%s [%" Px ", %" Px ")", prefix, start(), |
364 end()); | 341 end()); |
365 SetName(buff); | 342 SetName(buff); |
366 } | 343 } |
367 | 344 |
368 | |
369 void ProfileCode::Tick(uword pc, bool exclusive, intptr_t serial) { | 345 void ProfileCode::Tick(uword pc, bool exclusive, intptr_t serial) { |
370 // If exclusive is set, tick it. | 346 // If exclusive is set, tick it. |
371 if (exclusive) { | 347 if (exclusive) { |
372 exclusive_ticks_++; | 348 exclusive_ticks_++; |
373 TickAddress(pc, true); | 349 TickAddress(pc, true); |
374 } | 350 } |
375 // Fall through and tick inclusive count too. | 351 // Fall through and tick inclusive count too. |
376 if (inclusive_serial_ == serial) { | 352 if (inclusive_serial_ == serial) { |
377 // Already gave inclusive tick for this sample. | 353 // Already gave inclusive tick for this sample. |
378 return; | 354 return; |
379 } | 355 } |
380 inclusive_serial_ = serial; | 356 inclusive_serial_ = serial; |
381 inclusive_ticks_++; | 357 inclusive_ticks_++; |
382 TickAddress(pc, false); | 358 TickAddress(pc, false); |
383 } | 359 } |
384 | 360 |
385 | |
386 void ProfileCode::TickAddress(uword pc, bool exclusive) { | 361 void ProfileCode::TickAddress(uword pc, bool exclusive) { |
387 const intptr_t length = address_ticks_.length(); | 362 const intptr_t length = address_ticks_.length(); |
388 | 363 |
389 intptr_t i = 0; | 364 intptr_t i = 0; |
390 for (; i < length; i++) { | 365 for (; i < length; i++) { |
391 ProfileCodeAddress& entry = address_ticks_[i]; | 366 ProfileCodeAddress& entry = address_ticks_[i]; |
392 if (entry.pc() == pc) { | 367 if (entry.pc() == pc) { |
393 // Tick the address entry. | 368 // Tick the address entry. |
394 entry.Tick(exclusive); | 369 entry.Tick(exclusive); |
395 return; | 370 return; |
(...skipping 10 matching lines...) Expand all Loading... |
406 | 381 |
407 if (i < length) { | 382 if (i < length) { |
408 // Insert at i. | 383 // Insert at i. |
409 address_ticks_.InsertAt(i, entry); | 384 address_ticks_.InsertAt(i, entry); |
410 } else { | 385 } else { |
411 // Add to end. | 386 // Add to end. |
412 address_ticks_.Add(entry); | 387 address_ticks_.Add(entry); |
413 } | 388 } |
414 } | 389 } |
415 | 390 |
416 | |
417 void ProfileCode::PrintNativeCode(JSONObject* profile_code_obj) { | 391 void ProfileCode::PrintNativeCode(JSONObject* profile_code_obj) { |
418 ASSERT(kind() == kNativeCode); | 392 ASSERT(kind() == kNativeCode); |
419 JSONObject obj(profile_code_obj, "code"); | 393 JSONObject obj(profile_code_obj, "code"); |
420 obj.AddProperty("type", "@Code"); | 394 obj.AddProperty("type", "@Code"); |
421 obj.AddProperty("kind", "Native"); | 395 obj.AddProperty("kind", "Native"); |
422 obj.AddProperty("name", name()); | 396 obj.AddProperty("name", name()); |
423 obj.AddProperty("_optimized", false); | 397 obj.AddProperty("_optimized", false); |
424 obj.AddPropertyF("start", "%" Px "", start()); | 398 obj.AddPropertyF("start", "%" Px "", start()); |
425 obj.AddPropertyF("end", "%" Px "", end()); | 399 obj.AddPropertyF("end", "%" Px "", end()); |
426 { | 400 { |
427 // Generate a fake function entry. | 401 // Generate a fake function entry. |
428 JSONObject func(&obj, "function"); | 402 JSONObject func(&obj, "function"); |
429 ASSERT(function_ != NULL); | 403 ASSERT(function_ != NULL); |
430 function_->PrintToJSONObject(&func); | 404 function_->PrintToJSONObject(&func); |
431 } | 405 } |
432 } | 406 } |
433 | 407 |
434 | |
435 void ProfileCode::PrintCollectedCode(JSONObject* profile_code_obj) { | 408 void ProfileCode::PrintCollectedCode(JSONObject* profile_code_obj) { |
436 ASSERT(kind() == kCollectedCode); | 409 ASSERT(kind() == kCollectedCode); |
437 JSONObject obj(profile_code_obj, "code"); | 410 JSONObject obj(profile_code_obj, "code"); |
438 obj.AddProperty("type", "@Code"); | 411 obj.AddProperty("type", "@Code"); |
439 obj.AddProperty("kind", "Collected"); | 412 obj.AddProperty("kind", "Collected"); |
440 obj.AddProperty("name", name()); | 413 obj.AddProperty("name", name()); |
441 obj.AddProperty("_optimized", false); | 414 obj.AddProperty("_optimized", false); |
442 obj.AddPropertyF("start", "%" Px "", start()); | 415 obj.AddPropertyF("start", "%" Px "", start()); |
443 obj.AddPropertyF("end", "%" Px "", end()); | 416 obj.AddPropertyF("end", "%" Px "", end()); |
444 { | 417 { |
445 // Generate a fake function entry. | 418 // Generate a fake function entry. |
446 JSONObject func(&obj, "function"); | 419 JSONObject func(&obj, "function"); |
447 ASSERT(function_ != NULL); | 420 ASSERT(function_ != NULL); |
448 function_->PrintToJSONObject(&func); | 421 function_->PrintToJSONObject(&func); |
449 } | 422 } |
450 } | 423 } |
451 | 424 |
452 | |
453 void ProfileCode::PrintOverwrittenCode(JSONObject* profile_code_obj) { | 425 void ProfileCode::PrintOverwrittenCode(JSONObject* profile_code_obj) { |
454 ASSERT(kind() == kReusedCode); | 426 ASSERT(kind() == kReusedCode); |
455 JSONObject obj(profile_code_obj, "code"); | 427 JSONObject obj(profile_code_obj, "code"); |
456 obj.AddProperty("type", "@Code"); | 428 obj.AddProperty("type", "@Code"); |
457 obj.AddProperty("kind", "Collected"); | 429 obj.AddProperty("kind", "Collected"); |
458 obj.AddProperty("name", name()); | 430 obj.AddProperty("name", name()); |
459 obj.AddProperty("_optimized", false); | 431 obj.AddProperty("_optimized", false); |
460 obj.AddPropertyF("start", "%" Px "", start()); | 432 obj.AddPropertyF("start", "%" Px "", start()); |
461 obj.AddPropertyF("end", "%" Px "", end()); | 433 obj.AddPropertyF("end", "%" Px "", end()); |
462 { | 434 { |
463 // Generate a fake function entry. | 435 // Generate a fake function entry. |
464 JSONObject func(&obj, "function"); | 436 JSONObject func(&obj, "function"); |
465 ASSERT(function_ != NULL); | 437 ASSERT(function_ != NULL); |
466 function_->PrintToJSONObject(&func); | 438 function_->PrintToJSONObject(&func); |
467 } | 439 } |
468 } | 440 } |
469 | 441 |
470 | |
471 void ProfileCode::PrintTagCode(JSONObject* profile_code_obj) { | 442 void ProfileCode::PrintTagCode(JSONObject* profile_code_obj) { |
472 ASSERT(kind() == kTagCode); | 443 ASSERT(kind() == kTagCode); |
473 JSONObject obj(profile_code_obj, "code"); | 444 JSONObject obj(profile_code_obj, "code"); |
474 obj.AddProperty("type", "@Code"); | 445 obj.AddProperty("type", "@Code"); |
475 obj.AddProperty("kind", "Tag"); | 446 obj.AddProperty("kind", "Tag"); |
476 obj.AddProperty("name", name()); | 447 obj.AddProperty("name", name()); |
477 obj.AddPropertyF("start", "%" Px "", start()); | 448 obj.AddPropertyF("start", "%" Px "", start()); |
478 obj.AddPropertyF("end", "%" Px "", end()); | 449 obj.AddPropertyF("end", "%" Px "", end()); |
479 obj.AddProperty("_optimized", false); | 450 obj.AddProperty("_optimized", false); |
480 { | 451 { |
481 // Generate a fake function entry. | 452 // Generate a fake function entry. |
482 JSONObject func(&obj, "function"); | 453 JSONObject func(&obj, "function"); |
483 ASSERT(function_ != NULL); | 454 ASSERT(function_ != NULL); |
484 function_->PrintToJSONObject(&func); | 455 function_->PrintToJSONObject(&func); |
485 } | 456 } |
486 } | 457 } |
487 | 458 |
488 | |
489 const char* ProfileCode::KindToCString(Kind kind) { | 459 const char* ProfileCode::KindToCString(Kind kind) { |
490 switch (kind) { | 460 switch (kind) { |
491 case kDartCode: | 461 case kDartCode: |
492 return "Dart"; | 462 return "Dart"; |
493 case kCollectedCode: | 463 case kCollectedCode: |
494 return "Collected"; | 464 return "Collected"; |
495 case kNativeCode: | 465 case kNativeCode: |
496 return "Native"; | 466 return "Native"; |
497 case kReusedCode: | 467 case kReusedCode: |
498 return "Overwritten"; | 468 return "Overwritten"; |
499 case kTagCode: | 469 case kTagCode: |
500 return "Tag"; | 470 return "Tag"; |
501 } | 471 } |
502 UNREACHABLE(); | 472 UNREACHABLE(); |
503 return NULL; | 473 return NULL; |
504 } | 474 } |
505 | 475 |
506 | |
507 void ProfileCode::PrintToJSONArray(JSONArray* codes) { | 476 void ProfileCode::PrintToJSONArray(JSONArray* codes) { |
508 JSONObject obj(codes); | 477 JSONObject obj(codes); |
509 obj.AddProperty("kind", ProfileCode::KindToCString(kind())); | 478 obj.AddProperty("kind", ProfileCode::KindToCString(kind())); |
510 obj.AddProperty("inclusiveTicks", inclusive_ticks()); | 479 obj.AddProperty("inclusiveTicks", inclusive_ticks()); |
511 obj.AddProperty("exclusiveTicks", exclusive_ticks()); | 480 obj.AddProperty("exclusiveTicks", exclusive_ticks()); |
512 if (kind() == kDartCode) { | 481 if (kind() == kDartCode) { |
513 ASSERT(!code_.IsNull()); | 482 ASSERT(!code_.IsNull()); |
514 obj.AddProperty("code", code_); | 483 obj.AddProperty("code", code_); |
515 } else if (kind() == kCollectedCode) { | 484 } else if (kind() == kCollectedCode) { |
516 PrintCollectedCode(&obj); | 485 PrintCollectedCode(&obj); |
517 } else if (kind() == kReusedCode) { | 486 } else if (kind() == kReusedCode) { |
518 PrintOverwrittenCode(&obj); | 487 PrintOverwrittenCode(&obj); |
519 } else if (kind() == kTagCode) { | 488 } else if (kind() == kTagCode) { |
520 PrintTagCode(&obj); | 489 PrintTagCode(&obj); |
521 } else { | 490 } else { |
522 ASSERT(kind() == kNativeCode); | 491 ASSERT(kind() == kNativeCode); |
523 PrintNativeCode(&obj); | 492 PrintNativeCode(&obj); |
524 } | 493 } |
525 { | 494 { |
526 JSONArray ticks(&obj, "ticks"); | 495 JSONArray ticks(&obj, "ticks"); |
527 for (intptr_t i = 0; i < address_ticks_.length(); i++) { | 496 for (intptr_t i = 0; i < address_ticks_.length(); i++) { |
528 const ProfileCodeAddress& entry = address_ticks_[i]; | 497 const ProfileCodeAddress& entry = address_ticks_[i]; |
529 ticks.AddValueF("%" Px "", entry.pc()); | 498 ticks.AddValueF("%" Px "", entry.pc()); |
530 ticks.AddValue(entry.exclusive_ticks()); | 499 ticks.AddValue(entry.exclusive_ticks()); |
531 ticks.AddValue(entry.inclusive_ticks()); | 500 ticks.AddValue(entry.inclusive_ticks()); |
532 } | 501 } |
533 } | 502 } |
534 } | 503 } |
535 | 504 |
536 | |
537 class ProfileFunctionTable : public ZoneAllocated { | 505 class ProfileFunctionTable : public ZoneAllocated { |
538 public: | 506 public: |
539 ProfileFunctionTable() | 507 ProfileFunctionTable() |
540 : null_function_(Function::ZoneHandle()), | 508 : null_function_(Function::ZoneHandle()), |
541 unknown_function_(NULL), | 509 unknown_function_(NULL), |
542 table_(8) { | 510 table_(8) { |
543 unknown_function_ = | 511 unknown_function_ = |
544 Add(ProfileFunction::kUnknownFunction, "<unknown Dart function>"); | 512 Add(ProfileFunction::kUnknownFunction, "<unknown Dart function>"); |
545 } | 513 } |
546 | 514 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
624 return kv->function()->raw() == key->raw(); | 592 return kv->function()->raw() == key->raw(); |
625 } | 593 } |
626 }; | 594 }; |
627 | 595 |
628 const Function& null_function_; | 596 const Function& null_function_; |
629 ProfileFunction* unknown_function_; | 597 ProfileFunction* unknown_function_; |
630 ZoneGrowableArray<ProfileFunction*> table_; | 598 ZoneGrowableArray<ProfileFunction*> table_; |
631 DirectChainedHashMap<ProfileFunctionTableTrait> function_hash_; | 599 DirectChainedHashMap<ProfileFunctionTableTrait> function_hash_; |
632 }; | 600 }; |
633 | 601 |
634 | |
635 ProfileFunction* ProfileCode::SetFunctionAndName(ProfileFunctionTable* table) { | 602 ProfileFunction* ProfileCode::SetFunctionAndName(ProfileFunctionTable* table) { |
636 ASSERT(function_ == NULL); | 603 ASSERT(function_ == NULL); |
637 | 604 |
638 ProfileFunction* function = NULL; | 605 ProfileFunction* function = NULL; |
639 if ((kind() == kReusedCode) || (kind() == kCollectedCode)) { | 606 if ((kind() == kReusedCode) || (kind() == kCollectedCode)) { |
640 if (name() == NULL) { | 607 if (name() == NULL) { |
641 // Lazily set generated name. | 608 // Lazily set generated name. |
642 GenerateAndSetSymbolName("[Collected]"); | 609 GenerateAndSetSymbolName("[Collected]"); |
643 } | 610 } |
644 // Map these to a canonical unknown function. | 611 // Map these to a canonical unknown function. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 UNREACHABLE(); | 675 UNREACHABLE(); |
709 } | 676 } |
710 ASSERT(function != NULL); | 677 ASSERT(function != NULL); |
711 | 678 |
712 function->AddProfileCode(code_table_index()); | 679 function->AddProfileCode(code_table_index()); |
713 | 680 |
714 function_ = function; | 681 function_ = function; |
715 return function_; | 682 return function_; |
716 } | 683 } |
717 | 684 |
718 | |
719 intptr_t ProfileCodeTable::FindCodeIndexForPC(uword pc) const { | 685 intptr_t ProfileCodeTable::FindCodeIndexForPC(uword pc) const { |
720 intptr_t length = table_.length(); | 686 intptr_t length = table_.length(); |
721 if (length == 0) { | 687 if (length == 0) { |
722 return -1; // Not found. | 688 return -1; // Not found. |
723 } | 689 } |
724 intptr_t lo = 0; | 690 intptr_t lo = 0; |
725 intptr_t hi = length - 1; | 691 intptr_t hi = length - 1; |
726 while (lo <= hi) { | 692 while (lo <= hi) { |
727 intptr_t mid = (hi - lo + 1) / 2 + lo; | 693 intptr_t mid = (hi - lo + 1) / 2 + lo; |
728 ASSERT(mid >= lo); | 694 ASSERT(mid >= lo); |
729 ASSERT(mid <= hi); | 695 ASSERT(mid <= hi); |
730 ProfileCode* code = At(mid); | 696 ProfileCode* code = At(mid); |
731 if (code->Contains(pc)) { | 697 if (code->Contains(pc)) { |
732 return mid; | 698 return mid; |
733 } else if (pc < code->start()) { | 699 } else if (pc < code->start()) { |
734 hi = mid - 1; | 700 hi = mid - 1; |
735 } else { | 701 } else { |
736 lo = mid + 1; | 702 lo = mid + 1; |
737 } | 703 } |
738 } | 704 } |
739 return -1; | 705 return -1; |
740 } | 706 } |
741 | 707 |
742 | |
743 intptr_t ProfileCodeTable::InsertCode(ProfileCode* new_code) { | 708 intptr_t ProfileCodeTable::InsertCode(ProfileCode* new_code) { |
744 const intptr_t length = table_.length(); | 709 const intptr_t length = table_.length(); |
745 if (length == 0) { | 710 if (length == 0) { |
746 table_.Add(new_code); | 711 table_.Add(new_code); |
747 return length; | 712 return length; |
748 } | 713 } |
749 | 714 |
750 // Determine the correct place to insert or merge |new_code| into table. | 715 // Determine the correct place to insert or merge |new_code| into table. |
751 intptr_t lo = -1; | 716 intptr_t lo = -1; |
752 intptr_t hi = -1; | 717 intptr_t hi = -1; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 insert = 0; | 757 insert = 0; |
793 } else if (hi == -1) { | 758 } else if (hi == -1) { |
794 insert = length; | 759 insert = length; |
795 } else { | 760 } else { |
796 insert = lo + 1; | 761 insert = lo + 1; |
797 } | 762 } |
798 table_.InsertAt(insert, new_code); | 763 table_.InsertAt(insert, new_code); |
799 return insert; | 764 return insert; |
800 } | 765 } |
801 | 766 |
802 | |
803 void ProfileCodeTable::FindNeighbors(uword pc, | 767 void ProfileCodeTable::FindNeighbors(uword pc, |
804 intptr_t* lo, | 768 intptr_t* lo, |
805 intptr_t* hi, | 769 intptr_t* hi, |
806 ProfileCode** lo_code, | 770 ProfileCode** lo_code, |
807 ProfileCode** hi_code) const { | 771 ProfileCode** hi_code) const { |
808 ASSERT(table_.length() >= 1); | 772 ASSERT(table_.length() >= 1); |
809 | 773 |
810 intptr_t length = table_.length(); | 774 intptr_t length = table_.length(); |
811 | 775 |
812 if (pc < At(0)->start()) { | 776 if (pc < At(0)->start()) { |
(...skipping 28 matching lines...) Expand all Loading... |
841 *lo = mid; | 805 *lo = mid; |
842 *lo_code = code; | 806 *lo_code = code; |
843 } | 807 } |
844 if (pc < code->end()) { | 808 if (pc < code->end()) { |
845 *hi = mid; | 809 *hi = mid; |
846 *hi_code = code; | 810 *hi_code = code; |
847 } | 811 } |
848 } | 812 } |
849 } | 813 } |
850 | 814 |
851 | |
852 void ProfileCodeTable::VerifyOrder() { | 815 void ProfileCodeTable::VerifyOrder() { |
853 const intptr_t length = table_.length(); | 816 const intptr_t length = table_.length(); |
854 if (length == 0) { | 817 if (length == 0) { |
855 return; | 818 return; |
856 } | 819 } |
857 uword last = table_[0]->end(); | 820 uword last = table_[0]->end(); |
858 for (intptr_t i = 1; i < length; i++) { | 821 for (intptr_t i = 1; i < length; i++) { |
859 ProfileCode* a = table_[i]; | 822 ProfileCode* a = table_[i]; |
860 ASSERT(last <= a->start()); | 823 ASSERT(last <= a->start()); |
861 last = a->end(); | 824 last = a->end(); |
862 } | 825 } |
863 } | 826 } |
864 | 827 |
865 void ProfileCodeTable::VerifyOverlap() { | 828 void ProfileCodeTable::VerifyOverlap() { |
866 const intptr_t length = table_.length(); | 829 const intptr_t length = table_.length(); |
867 for (intptr_t i = 0; i < length; i++) { | 830 for (intptr_t i = 0; i < length; i++) { |
868 ProfileCode* a = table_[i]; | 831 ProfileCode* a = table_[i]; |
869 for (intptr_t j = i + 1; j < length; j++) { | 832 for (intptr_t j = i + 1; j < length; j++) { |
870 ProfileCode* b = table_[j]; | 833 ProfileCode* b = table_[j]; |
871 ASSERT(!a->Contains(b->start()) && !a->Contains(b->end() - 1) && | 834 ASSERT(!a->Contains(b->start()) && !a->Contains(b->end() - 1) && |
872 !b->Contains(a->start()) && !b->Contains(a->end() - 1)); | 835 !b->Contains(a->start()) && !b->Contains(a->end() - 1)); |
873 } | 836 } |
874 } | 837 } |
875 } | 838 } |
876 | 839 |
877 | |
878 ProfileTrieNode::ProfileTrieNode(intptr_t table_index) | 840 ProfileTrieNode::ProfileTrieNode(intptr_t table_index) |
879 : table_index_(table_index), | 841 : table_index_(table_index), |
880 count_(0), | 842 count_(0), |
881 exclusive_allocations_(0), | 843 exclusive_allocations_(0), |
882 inclusive_allocations_(0), | 844 inclusive_allocations_(0), |
883 children_(0), | 845 children_(0), |
884 frame_id_(-1) { | 846 frame_id_(-1) { |
885 ASSERT(table_index_ >= 0); | 847 ASSERT(table_index_ >= 0); |
886 } | 848 } |
887 | 849 |
888 | |
889 ProfileTrieNode::~ProfileTrieNode() {} | 850 ProfileTrieNode::~ProfileTrieNode() {} |
890 | 851 |
891 | |
892 void ProfileTrieNode::Tick(ProcessedSample* sample, bool exclusive) { | 852 void ProfileTrieNode::Tick(ProcessedSample* sample, bool exclusive) { |
893 count_++; | 853 count_++; |
894 IncrementAllocation(sample->native_allocation_size_bytes(), exclusive); | 854 IncrementAllocation(sample->native_allocation_size_bytes(), exclusive); |
895 } | 855 } |
896 | 856 |
897 | |
898 void ProfileTrieNode::SortChildren() { | 857 void ProfileTrieNode::SortChildren() { |
899 children_.Sort(ProfileTrieNodeCompare); | 858 children_.Sort(ProfileTrieNodeCompare); |
900 // Recurse. | 859 // Recurse. |
901 for (intptr_t i = 0; i < children_.length(); i++) { | 860 for (intptr_t i = 0; i < children_.length(); i++) { |
902 children_[i]->SortChildren(); | 861 children_[i]->SortChildren(); |
903 } | 862 } |
904 } | 863 } |
905 | 864 |
906 | |
907 intptr_t ProfileTrieNode::IndexOf(ProfileTrieNode* node) { | 865 intptr_t ProfileTrieNode::IndexOf(ProfileTrieNode* node) { |
908 for (intptr_t i = 0; i < children_.length(); i++) { | 866 for (intptr_t i = 0; i < children_.length(); i++) { |
909 if (children_[i] == node) { | 867 if (children_[i] == node) { |
910 return i; | 868 return i; |
911 } | 869 } |
912 } | 870 } |
913 return -1; | 871 return -1; |
914 } | 872 } |
915 | 873 |
916 | |
917 class ProfileCodeTrieNode : public ProfileTrieNode { | 874 class ProfileCodeTrieNode : public ProfileTrieNode { |
918 public: | 875 public: |
919 explicit ProfileCodeTrieNode(intptr_t table_index) | 876 explicit ProfileCodeTrieNode(intptr_t table_index) |
920 : ProfileTrieNode(table_index) {} | 877 : ProfileTrieNode(table_index) {} |
921 | 878 |
922 void PrintToJSONArray(JSONArray* array) const { | 879 void PrintToJSONArray(JSONArray* array) const { |
923 ASSERT(array != NULL); | 880 ASSERT(array != NULL); |
924 // Write CodeRegion index. | 881 // Write CodeRegion index. |
925 array->AddValue(table_index()); | 882 array->AddValue(table_index()); |
926 // Write count. | 883 // Write count. |
(...skipping 30 matching lines...) Expand all Loading... |
957 // Insert at i. | 914 // Insert at i. |
958 children_.InsertAt(i, reinterpret_cast<ProfileTrieNode*>(child)); | 915 children_.InsertAt(i, reinterpret_cast<ProfileTrieNode*>(child)); |
959 } else { | 916 } else { |
960 // Add to end. | 917 // Add to end. |
961 children_.Add(reinterpret_cast<ProfileTrieNode*>(child)); | 918 children_.Add(reinterpret_cast<ProfileTrieNode*>(child)); |
962 } | 919 } |
963 return child; | 920 return child; |
964 } | 921 } |
965 }; | 922 }; |
966 | 923 |
967 | |
968 class ProfileFunctionTrieNodeCode { | 924 class ProfileFunctionTrieNodeCode { |
969 public: | 925 public: |
970 explicit ProfileFunctionTrieNodeCode(intptr_t index) | 926 explicit ProfileFunctionTrieNodeCode(intptr_t index) |
971 : code_index_(index), ticks_(0) {} | 927 : code_index_(index), ticks_(0) {} |
972 | 928 |
973 intptr_t index() const { return code_index_; } | 929 intptr_t index() const { return code_index_; } |
974 | 930 |
975 void Tick() { ticks_++; } | 931 void Tick() { ticks_++; } |
976 | 932 |
977 intptr_t ticks() const { return ticks_; } | 933 intptr_t ticks() const { return ticks_; } |
978 | 934 |
979 private: | 935 private: |
980 intptr_t code_index_; | 936 intptr_t code_index_; |
981 intptr_t ticks_; | 937 intptr_t ticks_; |
982 }; | 938 }; |
983 | 939 |
984 | |
985 class ProfileFunctionTrieNode : public ProfileTrieNode { | 940 class ProfileFunctionTrieNode : public ProfileTrieNode { |
986 public: | 941 public: |
987 explicit ProfileFunctionTrieNode(intptr_t table_index) | 942 explicit ProfileFunctionTrieNode(intptr_t table_index) |
988 : ProfileTrieNode(table_index), code_objects_(1) {} | 943 : ProfileTrieNode(table_index), code_objects_(1) {} |
989 | 944 |
990 void PrintToJSONArray(JSONArray* array) const { | 945 void PrintToJSONArray(JSONArray* array) const { |
991 ASSERT(array != NULL); | 946 ASSERT(array != NULL); |
992 // Write CodeRegion index. | 947 // Write CodeRegion index. |
993 array->AddValue(table_index()); | 948 array->AddValue(table_index()); |
994 // Write count. | 949 // Write count. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 } | 1005 } |
1051 ProfileFunctionTrieNodeCode code_object(index); | 1006 ProfileFunctionTrieNodeCode code_object(index); |
1052 code_object.Tick(); | 1007 code_object.Tick(); |
1053 code_objects_.Add(code_object); | 1008 code_objects_.Add(code_object); |
1054 } | 1009 } |
1055 | 1010 |
1056 private: | 1011 private: |
1057 ZoneGrowableArray<ProfileFunctionTrieNodeCode> code_objects_; | 1012 ZoneGrowableArray<ProfileFunctionTrieNodeCode> code_objects_; |
1058 }; | 1013 }; |
1059 | 1014 |
1060 | |
1061 class ProfileCodeInlinedFunctionsCache : public ValueObject { | 1015 class ProfileCodeInlinedFunctionsCache : public ValueObject { |
1062 public: | 1016 public: |
1063 ProfileCodeInlinedFunctionsCache() : cache_cursor_(0), last_hit_(0) { | 1017 ProfileCodeInlinedFunctionsCache() : cache_cursor_(0), last_hit_(0) { |
1064 for (intptr_t i = 0; i < kCacheSize; i++) { | 1018 for (intptr_t i = 0; i < kCacheSize; i++) { |
1065 cache_[i].Reset(); | 1019 cache_[i].Reset(); |
1066 } | 1020 } |
1067 cache_hit_ = 0; | 1021 cache_hit_ = 0; |
1068 cache_miss_ = 0; | 1022 cache_miss_ = 0; |
1069 } | 1023 } |
1070 | 1024 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1195 }; | 1149 }; |
1196 | 1150 |
1197 static const intptr_t kCacheSize = 128; | 1151 static const intptr_t kCacheSize = 128; |
1198 intptr_t cache_cursor_; | 1152 intptr_t cache_cursor_; |
1199 intptr_t last_hit_; | 1153 intptr_t last_hit_; |
1200 CacheEntry cache_[kCacheSize]; | 1154 CacheEntry cache_[kCacheSize]; |
1201 intptr_t cache_miss_; | 1155 intptr_t cache_miss_; |
1202 intptr_t cache_hit_; | 1156 intptr_t cache_hit_; |
1203 }; | 1157 }; |
1204 | 1158 |
1205 | |
1206 class ProfileBuilder : public ValueObject { | 1159 class ProfileBuilder : public ValueObject { |
1207 public: | 1160 public: |
1208 enum ProfileInfoKind { | 1161 enum ProfileInfoKind { |
1209 kNone, | 1162 kNone, |
1210 kOptimized, | 1163 kOptimized, |
1211 kUnoptimized, | 1164 kUnoptimized, |
1212 kNative, | 1165 kNative, |
1213 kInlineStart, | 1166 kInlineStart, |
1214 kInlineFinish, | 1167 kInlineFinish, |
1215 kNumProfileInfoKind, | 1168 kNumProfileInfoKind, |
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1771 ProfileCodeTable* tag_table = profile_->tag_code_; | 1724 ProfileCodeTable* tag_table = profile_->tag_code_; |
1772 intptr_t index = tag_table->FindCodeIndexForPC(VMTag::kTruncatedTagId); | 1725 intptr_t index = tag_table->FindCodeIndexForPC(VMTag::kTruncatedTagId); |
1773 ASSERT(index >= 0); | 1726 ASSERT(index >= 0); |
1774 ProfileCode* code = tag_table->At(index); | 1727 ProfileCode* code = tag_table->At(index); |
1775 code->IncInclusiveTicks(); | 1728 code->IncInclusiveTicks(); |
1776 ASSERT(code != NULL); | 1729 ASSERT(code != NULL); |
1777 ProfileFunction* function = code->function(); | 1730 ProfileFunction* function = code->function(); |
1778 function->IncInclusiveTicks(); | 1731 function->IncInclusiveTicks(); |
1779 } | 1732 } |
1780 | 1733 |
1781 | |
1782 // Tag append functions are overloaded for |ProfileCodeTrieNode| and | 1734 // Tag append functions are overloaded for |ProfileCodeTrieNode| and |
1783 // |ProfileFunctionTrieNode| types. | 1735 // |ProfileFunctionTrieNode| types. |
1784 | 1736 |
1785 // ProfileCodeTrieNode | 1737 // ProfileCodeTrieNode |
1786 ProfileCodeTrieNode* AppendUserTag(uword user_tag, | 1738 ProfileCodeTrieNode* AppendUserTag(uword user_tag, |
1787 ProfileCodeTrieNode* current, | 1739 ProfileCodeTrieNode* current, |
1788 ProcessedSample* sample) { | 1740 ProcessedSample* sample) { |
1789 intptr_t user_tag_index = GetProfileCodeTagIndex(user_tag); | 1741 intptr_t user_tag_index = GetProfileCodeTagIndex(user_tag); |
1790 if (user_tag_index >= 0) { | 1742 if (user_tag_index >= 0) { |
1791 current = current->GetChild(user_tag_index); | 1743 current = current->GetChild(user_tag_index); |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2218 ProfileCode* code = | 2170 ProfileCode* code = |
2219 new ProfileCode(ProfileCode::kReusedCode, pc, pc + 1, 0, null_code_); | 2171 new ProfileCode(ProfileCode::kReusedCode, pc, pc + 1, 0, null_code_); |
2220 return code; | 2172 return code; |
2221 } | 2173 } |
2222 | 2174 |
2223 bool IsPCInDartHeap(uword pc) { | 2175 bool IsPCInDartHeap(uword pc) { |
2224 return vm_isolate_->heap()->CodeContains(pc) || | 2176 return vm_isolate_->heap()->CodeContains(pc) || |
2225 thread_->isolate()->heap()->CodeContains(pc); | 2177 thread_->isolate()->heap()->CodeContains(pc); |
2226 } | 2178 } |
2227 | 2179 |
2228 | |
2229 ProfileCode* FindOrRegisterNativeProfileCode(uword pc) { | 2180 ProfileCode* FindOrRegisterNativeProfileCode(uword pc) { |
2230 // Check if |pc| is already known in the live code table. | 2181 // Check if |pc| is already known in the live code table. |
2231 ProfileCodeTable* live_table = profile_->live_code_; | 2182 ProfileCodeTable* live_table = profile_->live_code_; |
2232 ProfileCode* profile_code = live_table->FindCodeForPC(pc); | 2183 ProfileCode* profile_code = live_table->FindCodeForPC(pc); |
2233 if (profile_code != NULL) { | 2184 if (profile_code != NULL) { |
2234 return profile_code; | 2185 return profile_code; |
2235 } | 2186 } |
2236 | 2187 |
2237 // We haven't seen this pc yet. | 2188 // We haven't seen this pc yet. |
2238 Code& code = Code::Handle(thread_->zone()); | 2189 Code& code = Code::Handle(thread_->zone()); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2338 DeoptimizedCodeSet* deoptimized_code_; | 2289 DeoptimizedCodeSet* deoptimized_code_; |
2339 const Code& null_code_; | 2290 const Code& null_code_; |
2340 const Function& null_function_; | 2291 const Function& null_function_; |
2341 bool tick_functions_; | 2292 bool tick_functions_; |
2342 bool inclusive_tree_; | 2293 bool inclusive_tree_; |
2343 ProfileCodeInlinedFunctionsCache inlined_functions_cache_; | 2294 ProfileCodeInlinedFunctionsCache inlined_functions_cache_; |
2344 ProcessedSampleBuffer* samples_; | 2295 ProcessedSampleBuffer* samples_; |
2345 ProfileInfoKind info_kind_; | 2296 ProfileInfoKind info_kind_; |
2346 }; // ProfileBuilder. | 2297 }; // ProfileBuilder. |
2347 | 2298 |
2348 | |
2349 Profile::Profile(Isolate* isolate) | 2299 Profile::Profile(Isolate* isolate) |
2350 : isolate_(isolate), | 2300 : isolate_(isolate), |
2351 zone_(Thread::Current()->zone()), | 2301 zone_(Thread::Current()->zone()), |
2352 samples_(NULL), | 2302 samples_(NULL), |
2353 live_code_(NULL), | 2303 live_code_(NULL), |
2354 dead_code_(NULL), | 2304 dead_code_(NULL), |
2355 tag_code_(NULL), | 2305 tag_code_(NULL), |
2356 functions_(NULL), | 2306 functions_(NULL), |
2357 dead_code_index_offset_(-1), | 2307 dead_code_index_offset_(-1), |
2358 tag_code_index_offset_(-1), | 2308 tag_code_index_offset_(-1), |
2359 min_time_(kMaxInt64), | 2309 min_time_(kMaxInt64), |
2360 max_time_(0) { | 2310 max_time_(0) { |
2361 ASSERT(isolate_ != NULL); | 2311 ASSERT(isolate_ != NULL); |
2362 for (intptr_t i = 0; i < kNumTrieKinds; i++) { | 2312 for (intptr_t i = 0; i < kNumTrieKinds; i++) { |
2363 roots_[i] = NULL; | 2313 roots_[i] = NULL; |
2364 } | 2314 } |
2365 } | 2315 } |
2366 | 2316 |
2367 | |
2368 void Profile::Build(Thread* thread, | 2317 void Profile::Build(Thread* thread, |
2369 SampleFilter* filter, | 2318 SampleFilter* filter, |
2370 SampleBuffer* sample_buffer, | 2319 SampleBuffer* sample_buffer, |
2371 TagOrder tag_order, | 2320 TagOrder tag_order, |
2372 intptr_t extra_tags) { | 2321 intptr_t extra_tags) { |
2373 ProfileBuilder builder(thread, filter, sample_buffer, tag_order, extra_tags, | 2322 ProfileBuilder builder(thread, filter, sample_buffer, tag_order, extra_tags, |
2374 this); | 2323 this); |
2375 builder.Build(); | 2324 builder.Build(); |
2376 } | 2325 } |
2377 | 2326 |
2378 | |
2379 intptr_t Profile::NumFunctions() const { | 2327 intptr_t Profile::NumFunctions() const { |
2380 return functions_->length(); | 2328 return functions_->length(); |
2381 } | 2329 } |
2382 | 2330 |
2383 ProfileFunction* Profile::GetFunction(intptr_t index) { | 2331 ProfileFunction* Profile::GetFunction(intptr_t index) { |
2384 ASSERT(functions_ != NULL); | 2332 ASSERT(functions_ != NULL); |
2385 return functions_->At(index); | 2333 return functions_->At(index); |
2386 } | 2334 } |
2387 | 2335 |
2388 | |
2389 ProfileCode* Profile::GetCode(intptr_t index) { | 2336 ProfileCode* Profile::GetCode(intptr_t index) { |
2390 ASSERT(live_code_ != NULL); | 2337 ASSERT(live_code_ != NULL); |
2391 ASSERT(dead_code_ != NULL); | 2338 ASSERT(dead_code_ != NULL); |
2392 ASSERT(tag_code_ != NULL); | 2339 ASSERT(tag_code_ != NULL); |
2393 ASSERT(dead_code_index_offset_ >= 0); | 2340 ASSERT(dead_code_index_offset_ >= 0); |
2394 ASSERT(tag_code_index_offset_ >= 0); | 2341 ASSERT(tag_code_index_offset_ >= 0); |
2395 | 2342 |
2396 // Code indexes span three arrays. | 2343 // Code indexes span three arrays. |
2397 // 0 ... |live_code| | 2344 // 0 ... |live_code| |
2398 // |live_code| ... |dead_code| | 2345 // |live_code| ... |dead_code| |
2399 // |dead_code| ... |tag_code| | 2346 // |dead_code| ... |tag_code| |
2400 | 2347 |
2401 if (index < dead_code_index_offset_) { | 2348 if (index < dead_code_index_offset_) { |
2402 return live_code_->At(index); | 2349 return live_code_->At(index); |
2403 } | 2350 } |
2404 | 2351 |
2405 if (index < tag_code_index_offset_) { | 2352 if (index < tag_code_index_offset_) { |
2406 index -= dead_code_index_offset_; | 2353 index -= dead_code_index_offset_; |
2407 return dead_code_->At(index); | 2354 return dead_code_->At(index); |
2408 } | 2355 } |
2409 | 2356 |
2410 index -= tag_code_index_offset_; | 2357 index -= tag_code_index_offset_; |
2411 return tag_code_->At(index); | 2358 return tag_code_->At(index); |
2412 } | 2359 } |
2413 | 2360 |
2414 | |
2415 ProfileTrieNode* Profile::GetTrieRoot(TrieKind trie_kind) { | 2361 ProfileTrieNode* Profile::GetTrieRoot(TrieKind trie_kind) { |
2416 return roots_[static_cast<intptr_t>(trie_kind)]; | 2362 return roots_[static_cast<intptr_t>(trie_kind)]; |
2417 } | 2363 } |
2418 | 2364 |
2419 | |
2420 void Profile::PrintHeaderJSON(JSONObject* obj) { | 2365 void Profile::PrintHeaderJSON(JSONObject* obj) { |
2421 obj->AddProperty("samplePeriod", static_cast<intptr_t>(FLAG_profile_period)); | 2366 obj->AddProperty("samplePeriod", static_cast<intptr_t>(FLAG_profile_period)); |
2422 obj->AddProperty("stackDepth", static_cast<intptr_t>(FLAG_max_profile_depth)); | 2367 obj->AddProperty("stackDepth", static_cast<intptr_t>(FLAG_max_profile_depth)); |
2423 obj->AddProperty("sampleCount", sample_count()); | 2368 obj->AddProperty("sampleCount", sample_count()); |
2424 obj->AddProperty("timeSpan", MicrosecondsToSeconds(GetTimeSpan())); | 2369 obj->AddProperty("timeSpan", MicrosecondsToSeconds(GetTimeSpan())); |
2425 obj->AddPropertyTimeMicros("timeOriginMicros", min_time()); | 2370 obj->AddPropertyTimeMicros("timeOriginMicros", min_time()); |
2426 obj->AddPropertyTimeMicros("timeExtentMicros", GetTimeSpan()); | 2371 obj->AddPropertyTimeMicros("timeExtentMicros", GetTimeSpan()); |
2427 | 2372 |
2428 ProfilerCounters counters = Profiler::counters(); | 2373 ProfilerCounters counters = Profiler::counters(); |
2429 { | 2374 { |
(...skipping 12 matching lines...) Expand all Loading... |
2442 "single_frame_sample_get_and_validate_stack_bounds", | 2387 "single_frame_sample_get_and_validate_stack_bounds", |
2443 counters.single_frame_sample_get_and_validate_stack_bounds); | 2388 counters.single_frame_sample_get_and_validate_stack_bounds); |
2444 counts.AddProperty64("stack_walker_native", counters.stack_walker_native); | 2389 counts.AddProperty64("stack_walker_native", counters.stack_walker_native); |
2445 counts.AddProperty64("stack_walker_dart_exit", | 2390 counts.AddProperty64("stack_walker_dart_exit", |
2446 counters.stack_walker_dart_exit); | 2391 counters.stack_walker_dart_exit); |
2447 counts.AddProperty64("stack_walker_dart", counters.stack_walker_dart); | 2392 counts.AddProperty64("stack_walker_dart", counters.stack_walker_dart); |
2448 counts.AddProperty64("stack_walker_none", counters.stack_walker_none); | 2393 counts.AddProperty64("stack_walker_none", counters.stack_walker_none); |
2449 } | 2394 } |
2450 } | 2395 } |
2451 | 2396 |
2452 | |
2453 void Profile::PrintTimelineFrameJSON(JSONObject* frames, | 2397 void Profile::PrintTimelineFrameJSON(JSONObject* frames, |
2454 ProfileTrieNode* current, | 2398 ProfileTrieNode* current, |
2455 ProfileTrieNode* parent, | 2399 ProfileTrieNode* parent, |
2456 intptr_t* next_id) { | 2400 intptr_t* next_id) { |
2457 ASSERT(current->frame_id() == -1); | 2401 ASSERT(current->frame_id() == -1); |
2458 const intptr_t id = *next_id; | 2402 const intptr_t id = *next_id; |
2459 *next_id = id + 1; | 2403 *next_id = id + 1; |
2460 current->set_frame_id(id); | 2404 current->set_frame_id(id); |
2461 ASSERT(current->frame_id() != -1); | 2405 ASSERT(current->frame_id() != -1); |
2462 | 2406 |
(...skipping 13 matching lines...) Expand all Loading... |
2476 parent->frame_id()); | 2420 parent->frame_id()); |
2477 } | 2421 } |
2478 } | 2422 } |
2479 | 2423 |
2480 for (intptr_t i = 0; i < current->NumChildren(); i++) { | 2424 for (intptr_t i = 0; i < current->NumChildren(); i++) { |
2481 ProfileTrieNode* child = current->At(i); | 2425 ProfileTrieNode* child = current->At(i); |
2482 PrintTimelineFrameJSON(frames, child, current, next_id); | 2426 PrintTimelineFrameJSON(frames, child, current, next_id); |
2483 } | 2427 } |
2484 } | 2428 } |
2485 | 2429 |
2486 | |
2487 void Profile::PrintTimelineJSON(JSONStream* stream) { | 2430 void Profile::PrintTimelineJSON(JSONStream* stream) { |
2488 ScopeTimer sw("Profile::PrintTimelineJSON", FLAG_trace_profiler); | 2431 ScopeTimer sw("Profile::PrintTimelineJSON", FLAG_trace_profiler); |
2489 JSONObject obj(stream); | 2432 JSONObject obj(stream); |
2490 obj.AddProperty("type", "_CpuProfileTimeline"); | 2433 obj.AddProperty("type", "_CpuProfileTimeline"); |
2491 PrintHeaderJSON(&obj); | 2434 PrintHeaderJSON(&obj); |
2492 { | 2435 { |
2493 JSONObject frames(&obj, "stackFrames"); | 2436 JSONObject frames(&obj, "stackFrames"); |
2494 ProfileTrieNode* root = GetTrieRoot(kInclusiveFunction); | 2437 ProfileTrieNode* root = GetTrieRoot(kInclusiveFunction); |
2495 intptr_t next_id = 0; | 2438 intptr_t next_id = 0; |
2496 PrintTimelineFrameJSON(&frames, root, NULL, &next_id); | 2439 PrintTimelineFrameJSON(&frames, root, NULL, &next_id); |
(...skipping 14 matching lines...) Expand all Loading... |
2511 event.AddPropertyTimeMicros("ts", sample->timestamp()); | 2454 event.AddPropertyTimeMicros("ts", sample->timestamp()); |
2512 event.AddProperty("cat", "Dart"); | 2455 event.AddProperty("cat", "Dart"); |
2513 | 2456 |
2514 ProfileTrieNode* trie = sample->timeline_trie(); | 2457 ProfileTrieNode* trie = sample->timeline_trie(); |
2515 ASSERT(trie->frame_id() != -1); | 2458 ASSERT(trie->frame_id() != -1); |
2516 event.AddPropertyF("sf", "%" Pd "-%" Pd, isolate_id, trie->frame_id()); | 2459 event.AddPropertyF("sf", "%" Pd "-%" Pd, isolate_id, trie->frame_id()); |
2517 } | 2460 } |
2518 } | 2461 } |
2519 } | 2462 } |
2520 | 2463 |
2521 | |
2522 ProfileFunction* Profile::FindFunction(const Function& function) { | 2464 ProfileFunction* Profile::FindFunction(const Function& function) { |
2523 return (functions_ != NULL) ? functions_->Lookup(function) : NULL; | 2465 return (functions_ != NULL) ? functions_->Lookup(function) : NULL; |
2524 } | 2466 } |
2525 | 2467 |
2526 | |
2527 void Profile::PrintProfileJSON(JSONStream* stream) { | 2468 void Profile::PrintProfileJSON(JSONStream* stream) { |
2528 ScopeTimer sw("Profile::PrintProfileJSON", FLAG_trace_profiler); | 2469 ScopeTimer sw("Profile::PrintProfileJSON", FLAG_trace_profiler); |
2529 JSONObject obj(stream); | 2470 JSONObject obj(stream); |
2530 obj.AddProperty("type", "_CpuProfile"); | 2471 obj.AddProperty("type", "_CpuProfile"); |
2531 PrintHeaderJSON(&obj); | 2472 PrintHeaderJSON(&obj); |
2532 { | 2473 { |
2533 JSONArray codes(&obj, "codes"); | 2474 JSONArray codes(&obj, "codes"); |
2534 for (intptr_t i = 0; i < live_code_->length(); i++) { | 2475 for (intptr_t i = 0; i < live_code_->length(); i++) { |
2535 ProfileCode* code = live_code_->At(i); | 2476 ProfileCode* code = live_code_->At(i); |
2536 ASSERT(code != NULL); | 2477 ASSERT(code != NULL); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2575 root->PrintToJSONArray(&function_trie); | 2516 root->PrintToJSONArray(&function_trie); |
2576 } | 2517 } |
2577 { | 2518 { |
2578 JSONArray function_trie(&obj, "inclusiveFunctionTrie"); | 2519 JSONArray function_trie(&obj, "inclusiveFunctionTrie"); |
2579 ProfileTrieNode* root = roots_[static_cast<intptr_t>(kInclusiveFunction)]; | 2520 ProfileTrieNode* root = roots_[static_cast<intptr_t>(kInclusiveFunction)]; |
2580 ASSERT(root != NULL); | 2521 ASSERT(root != NULL); |
2581 root->PrintToJSONArray(&function_trie); | 2522 root->PrintToJSONArray(&function_trie); |
2582 } | 2523 } |
2583 } | 2524 } |
2584 | 2525 |
2585 | |
2586 void ProfileTrieWalker::Reset(Profile::TrieKind trie_kind) { | 2526 void ProfileTrieWalker::Reset(Profile::TrieKind trie_kind) { |
2587 code_trie_ = Profile::IsCodeTrie(trie_kind); | 2527 code_trie_ = Profile::IsCodeTrie(trie_kind); |
2588 parent_ = NULL; | 2528 parent_ = NULL; |
2589 current_ = profile_->GetTrieRoot(trie_kind); | 2529 current_ = profile_->GetTrieRoot(trie_kind); |
2590 ASSERT(current_ != NULL); | 2530 ASSERT(current_ != NULL); |
2591 } | 2531 } |
2592 | 2532 |
2593 | |
2594 const char* ProfileTrieWalker::CurrentName() { | 2533 const char* ProfileTrieWalker::CurrentName() { |
2595 if (current_ == NULL) { | 2534 if (current_ == NULL) { |
2596 return NULL; | 2535 return NULL; |
2597 } | 2536 } |
2598 if (code_trie_) { | 2537 if (code_trie_) { |
2599 ProfileCode* code = profile_->GetCode(current_->table_index()); | 2538 ProfileCode* code = profile_->GetCode(current_->table_index()); |
2600 return code->name(); | 2539 return code->name(); |
2601 } else { | 2540 } else { |
2602 ProfileFunction* func = profile_->GetFunction(current_->table_index()); | 2541 ProfileFunction* func = profile_->GetFunction(current_->table_index()); |
2603 return func->Name(); | 2542 return func->Name(); |
2604 } | 2543 } |
2605 UNREACHABLE(); | 2544 UNREACHABLE(); |
2606 return NULL; | 2545 return NULL; |
2607 } | 2546 } |
2608 | 2547 |
2609 | |
2610 intptr_t ProfileTrieWalker::CurrentNodeTickCount() { | 2548 intptr_t ProfileTrieWalker::CurrentNodeTickCount() { |
2611 if (current_ == NULL) { | 2549 if (current_ == NULL) { |
2612 return -1; | 2550 return -1; |
2613 } | 2551 } |
2614 return current_->count(); | 2552 return current_->count(); |
2615 } | 2553 } |
2616 | 2554 |
2617 | |
2618 intptr_t ProfileTrieWalker::CurrentInclusiveTicks() { | 2555 intptr_t ProfileTrieWalker::CurrentInclusiveTicks() { |
2619 if (current_ == NULL) { | 2556 if (current_ == NULL) { |
2620 return -1; | 2557 return -1; |
2621 } | 2558 } |
2622 if (code_trie_) { | 2559 if (code_trie_) { |
2623 ProfileCode* code = profile_->GetCode(current_->table_index()); | 2560 ProfileCode* code = profile_->GetCode(current_->table_index()); |
2624 return code->inclusive_ticks(); | 2561 return code->inclusive_ticks(); |
2625 } else { | 2562 } else { |
2626 ProfileFunction* func = profile_->GetFunction(current_->table_index()); | 2563 ProfileFunction* func = profile_->GetFunction(current_->table_index()); |
2627 return func->inclusive_ticks(); | 2564 return func->inclusive_ticks(); |
2628 } | 2565 } |
2629 UNREACHABLE(); | 2566 UNREACHABLE(); |
2630 return -1; | 2567 return -1; |
2631 } | 2568 } |
2632 | 2569 |
2633 | |
2634 intptr_t ProfileTrieWalker::CurrentExclusiveTicks() { | 2570 intptr_t ProfileTrieWalker::CurrentExclusiveTicks() { |
2635 if (current_ == NULL) { | 2571 if (current_ == NULL) { |
2636 return -1; | 2572 return -1; |
2637 } | 2573 } |
2638 if (code_trie_) { | 2574 if (code_trie_) { |
2639 ProfileCode* code = profile_->GetCode(current_->table_index()); | 2575 ProfileCode* code = profile_->GetCode(current_->table_index()); |
2640 return code->exclusive_ticks(); | 2576 return code->exclusive_ticks(); |
2641 } else { | 2577 } else { |
2642 ProfileFunction* func = profile_->GetFunction(current_->table_index()); | 2578 ProfileFunction* func = profile_->GetFunction(current_->table_index()); |
2643 return func->exclusive_ticks(); | 2579 return func->exclusive_ticks(); |
2644 } | 2580 } |
2645 UNREACHABLE(); | 2581 UNREACHABLE(); |
2646 return -1; | 2582 return -1; |
2647 } | 2583 } |
2648 | 2584 |
2649 | |
2650 intptr_t ProfileTrieWalker::CurrentInclusiveAllocations() { | 2585 intptr_t ProfileTrieWalker::CurrentInclusiveAllocations() { |
2651 if (current_ == NULL) { | 2586 if (current_ == NULL) { |
2652 return -1; | 2587 return -1; |
2653 } | 2588 } |
2654 return current_->inclusive_allocations(); | 2589 return current_->inclusive_allocations(); |
2655 } | 2590 } |
2656 | 2591 |
2657 | |
2658 intptr_t ProfileTrieWalker::CurrentExclusiveAllocations() { | 2592 intptr_t ProfileTrieWalker::CurrentExclusiveAllocations() { |
2659 if (current_ == NULL) { | 2593 if (current_ == NULL) { |
2660 return -1; | 2594 return -1; |
2661 } | 2595 } |
2662 return current_->exclusive_allocations(); | 2596 return current_->exclusive_allocations(); |
2663 } | 2597 } |
2664 | 2598 |
2665 | |
2666 const char* ProfileTrieWalker::CurrentToken() { | 2599 const char* ProfileTrieWalker::CurrentToken() { |
2667 if (current_ == NULL) { | 2600 if (current_ == NULL) { |
2668 return NULL; | 2601 return NULL; |
2669 } | 2602 } |
2670 if (code_trie_) { | 2603 if (code_trie_) { |
2671 return NULL; | 2604 return NULL; |
2672 } | 2605 } |
2673 ProfileFunction* func = profile_->GetFunction(current_->table_index()); | 2606 ProfileFunction* func = profile_->GetFunction(current_->table_index()); |
2674 const Function& function = *(func->function()); | 2607 const Function& function = *(func->function()); |
2675 if (function.IsNull()) { | 2608 if (function.IsNull()) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2716 | 2649 |
2717 bool ProfileTrieWalker::Down() { | 2650 bool ProfileTrieWalker::Down() { |
2718 if ((current_ == NULL) || (current_->NumChildren() == 0)) { | 2651 if ((current_ == NULL) || (current_->NumChildren() == 0)) { |
2719 return false; | 2652 return false; |
2720 } | 2653 } |
2721 parent_ = current_; | 2654 parent_ = current_; |
2722 current_ = current_->At(0); | 2655 current_ = current_->At(0); |
2723 return true; | 2656 return true; |
2724 } | 2657 } |
2725 | 2658 |
2726 | |
2727 bool ProfileTrieWalker::NextSibling() { | 2659 bool ProfileTrieWalker::NextSibling() { |
2728 if (parent_ == NULL) { | 2660 if (parent_ == NULL) { |
2729 return false; | 2661 return false; |
2730 } | 2662 } |
2731 intptr_t current_index = parent_->IndexOf(current_); | 2663 intptr_t current_index = parent_->IndexOf(current_); |
2732 if (current_index < 0) { | 2664 if (current_index < 0) { |
2733 return false; | 2665 return false; |
2734 } | 2666 } |
2735 current_index++; | 2667 current_index++; |
2736 if (current_index >= parent_->NumChildren()) { | 2668 if (current_index >= parent_->NumChildren()) { |
2737 return false; | 2669 return false; |
2738 } | 2670 } |
2739 current_ = parent_->At(current_index); | 2671 current_ = parent_->At(current_index); |
2740 return true; | 2672 return true; |
2741 } | 2673 } |
2742 | 2674 |
2743 | |
2744 intptr_t ProfileTrieWalker::SiblingCount() { | 2675 intptr_t ProfileTrieWalker::SiblingCount() { |
2745 ASSERT(parent_ != NULL); | 2676 ASSERT(parent_ != NULL); |
2746 return parent_->NumChildren(); | 2677 return parent_->NumChildren(); |
2747 } | 2678 } |
2748 | 2679 |
2749 | |
2750 void ProfilerService::PrintJSONImpl(Thread* thread, | 2680 void ProfilerService::PrintJSONImpl(Thread* thread, |
2751 JSONStream* stream, | 2681 JSONStream* stream, |
2752 Profile::TagOrder tag_order, | 2682 Profile::TagOrder tag_order, |
2753 intptr_t extra_tags, | 2683 intptr_t extra_tags, |
2754 SampleFilter* filter, | 2684 SampleFilter* filter, |
2755 SampleBuffer* sample_buffer, | 2685 SampleBuffer* sample_buffer, |
2756 bool as_timeline) { | 2686 bool as_timeline) { |
2757 Isolate* isolate = thread->isolate(); | 2687 Isolate* isolate = thread->isolate(); |
2758 // Disable thread interrupts while processing the buffer. | 2688 // Disable thread interrupts while processing the buffer. |
2759 DisableThreadInterruptsScope dtis(thread); | 2689 DisableThreadInterruptsScope dtis(thread); |
2760 | 2690 |
2761 if (sample_buffer == NULL) { | 2691 if (sample_buffer == NULL) { |
2762 stream->PrintError(kFeatureDisabled, NULL); | 2692 stream->PrintError(kFeatureDisabled, NULL); |
2763 return; | 2693 return; |
2764 } | 2694 } |
2765 | 2695 |
2766 { | 2696 { |
2767 StackZone zone(thread); | 2697 StackZone zone(thread); |
2768 HANDLESCOPE(thread); | 2698 HANDLESCOPE(thread); |
2769 Profile profile(isolate); | 2699 Profile profile(isolate); |
2770 profile.Build(thread, filter, sample_buffer, tag_order, extra_tags); | 2700 profile.Build(thread, filter, sample_buffer, tag_order, extra_tags); |
2771 if (as_timeline) { | 2701 if (as_timeline) { |
2772 profile.PrintTimelineJSON(stream); | 2702 profile.PrintTimelineJSON(stream); |
2773 } else { | 2703 } else { |
2774 profile.PrintProfileJSON(stream); | 2704 profile.PrintProfileJSON(stream); |
2775 } | 2705 } |
2776 } | 2706 } |
2777 } | 2707 } |
2778 | 2708 |
2779 | |
2780 class NoAllocationSampleFilter : public SampleFilter { | 2709 class NoAllocationSampleFilter : public SampleFilter { |
2781 public: | 2710 public: |
2782 NoAllocationSampleFilter(Dart_Port port, | 2711 NoAllocationSampleFilter(Dart_Port port, |
2783 intptr_t thread_task_mask, | 2712 intptr_t thread_task_mask, |
2784 int64_t time_origin_micros, | 2713 int64_t time_origin_micros, |
2785 int64_t time_extent_micros) | 2714 int64_t time_extent_micros) |
2786 : SampleFilter(port, | 2715 : SampleFilter(port, |
2787 thread_task_mask, | 2716 thread_task_mask, |
2788 time_origin_micros, | 2717 time_origin_micros, |
2789 time_extent_micros) {} | 2718 time_extent_micros) {} |
2790 | 2719 |
2791 bool FilterSample(Sample* sample) { return !sample->is_allocation_sample(); } | 2720 bool FilterSample(Sample* sample) { return !sample->is_allocation_sample(); } |
2792 }; | 2721 }; |
2793 | 2722 |
2794 | |
2795 void ProfilerService::PrintJSON(JSONStream* stream, | 2723 void ProfilerService::PrintJSON(JSONStream* stream, |
2796 Profile::TagOrder tag_order, | 2724 Profile::TagOrder tag_order, |
2797 intptr_t extra_tags, | 2725 intptr_t extra_tags, |
2798 int64_t time_origin_micros, | 2726 int64_t time_origin_micros, |
2799 int64_t time_extent_micros) { | 2727 int64_t time_extent_micros) { |
2800 Thread* thread = Thread::Current(); | 2728 Thread* thread = Thread::Current(); |
2801 Isolate* isolate = thread->isolate(); | 2729 Isolate* isolate = thread->isolate(); |
2802 NoAllocationSampleFilter filter(isolate->main_port(), Thread::kMutatorTask, | 2730 NoAllocationSampleFilter filter(isolate->main_port(), Thread::kMutatorTask, |
2803 time_origin_micros, time_extent_micros); | 2731 time_origin_micros, time_extent_micros); |
2804 const bool as_timeline = false; | 2732 const bool as_timeline = false; |
2805 PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter, | 2733 PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter, |
2806 Profiler::sample_buffer(), as_timeline); | 2734 Profiler::sample_buffer(), as_timeline); |
2807 } | 2735 } |
2808 | 2736 |
2809 | |
2810 class ClassAllocationSampleFilter : public SampleFilter { | 2737 class ClassAllocationSampleFilter : public SampleFilter { |
2811 public: | 2738 public: |
2812 ClassAllocationSampleFilter(Dart_Port port, | 2739 ClassAllocationSampleFilter(Dart_Port port, |
2813 const Class& cls, | 2740 const Class& cls, |
2814 intptr_t thread_task_mask, | 2741 intptr_t thread_task_mask, |
2815 int64_t time_origin_micros, | 2742 int64_t time_origin_micros, |
2816 int64_t time_extent_micros) | 2743 int64_t time_extent_micros) |
2817 : SampleFilter(port, | 2744 : SampleFilter(port, |
2818 thread_task_mask, | 2745 thread_task_mask, |
2819 time_origin_micros, | 2746 time_origin_micros, |
2820 time_extent_micros), | 2747 time_extent_micros), |
2821 cls_(Class::Handle(cls.raw())) { | 2748 cls_(Class::Handle(cls.raw())) { |
2822 ASSERT(!cls_.IsNull()); | 2749 ASSERT(!cls_.IsNull()); |
2823 } | 2750 } |
2824 | 2751 |
2825 bool FilterSample(Sample* sample) { | 2752 bool FilterSample(Sample* sample) { |
2826 return sample->is_allocation_sample() && | 2753 return sample->is_allocation_sample() && |
2827 (sample->allocation_cid() == cls_.id()); | 2754 (sample->allocation_cid() == cls_.id()); |
2828 } | 2755 } |
2829 | 2756 |
2830 private: | 2757 private: |
2831 const Class& cls_; | 2758 const Class& cls_; |
2832 }; | 2759 }; |
2833 | 2760 |
2834 | |
2835 void ProfilerService::PrintAllocationJSON(JSONStream* stream, | 2761 void ProfilerService::PrintAllocationJSON(JSONStream* stream, |
2836 Profile::TagOrder tag_order, | 2762 Profile::TagOrder tag_order, |
2837 const Class& cls, | 2763 const Class& cls, |
2838 int64_t time_origin_micros, | 2764 int64_t time_origin_micros, |
2839 int64_t time_extent_micros) { | 2765 int64_t time_extent_micros) { |
2840 Thread* thread = Thread::Current(); | 2766 Thread* thread = Thread::Current(); |
2841 Isolate* isolate = thread->isolate(); | 2767 Isolate* isolate = thread->isolate(); |
2842 ClassAllocationSampleFilter filter(isolate->main_port(), cls, | 2768 ClassAllocationSampleFilter filter(isolate->main_port(), cls, |
2843 Thread::kMutatorTask, time_origin_micros, | 2769 Thread::kMutatorTask, time_origin_micros, |
2844 time_extent_micros); | 2770 time_extent_micros); |
2845 const bool as_timeline = false; | 2771 const bool as_timeline = false; |
2846 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, | 2772 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, |
2847 Profiler::sample_buffer(), as_timeline); | 2773 Profiler::sample_buffer(), as_timeline); |
2848 } | 2774 } |
2849 | 2775 |
2850 | |
2851 void ProfilerService::PrintNativeAllocationJSON(JSONStream* stream, | 2776 void ProfilerService::PrintNativeAllocationJSON(JSONStream* stream, |
2852 Profile::TagOrder tag_order, | 2777 Profile::TagOrder tag_order, |
2853 int64_t time_origin_micros, | 2778 int64_t time_origin_micros, |
2854 int64_t time_extent_micros) { | 2779 int64_t time_extent_micros) { |
2855 Thread* thread = Thread::Current(); | 2780 Thread* thread = Thread::Current(); |
2856 NativeAllocationSampleFilter filter(time_origin_micros, time_extent_micros); | 2781 NativeAllocationSampleFilter filter(time_origin_micros, time_extent_micros); |
2857 const bool as_timeline = false; | 2782 const bool as_timeline = false; |
2858 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, | 2783 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, |
2859 Profiler::allocation_sample_buffer(), as_timeline); | 2784 Profiler::allocation_sample_buffer(), as_timeline); |
2860 } | 2785 } |
2861 | 2786 |
2862 | |
2863 void ProfilerService::PrintTimelineJSON(JSONStream* stream, | 2787 void ProfilerService::PrintTimelineJSON(JSONStream* stream, |
2864 Profile::TagOrder tag_order, | 2788 Profile::TagOrder tag_order, |
2865 int64_t time_origin_micros, | 2789 int64_t time_origin_micros, |
2866 int64_t time_extent_micros) { | 2790 int64_t time_extent_micros) { |
2867 Thread* thread = Thread::Current(); | 2791 Thread* thread = Thread::Current(); |
2868 Isolate* isolate = thread->isolate(); | 2792 Isolate* isolate = thread->isolate(); |
2869 const intptr_t thread_task_mask = Thread::kMutatorTask | | 2793 const intptr_t thread_task_mask = Thread::kMutatorTask | |
2870 Thread::kCompilerTask | | 2794 Thread::kCompilerTask | |
2871 Thread::kSweeperTask | Thread::kMarkerTask; | 2795 Thread::kSweeperTask | Thread::kMarkerTask; |
2872 NoAllocationSampleFilter filter(isolate->main_port(), thread_task_mask, | 2796 NoAllocationSampleFilter filter(isolate->main_port(), thread_task_mask, |
2873 time_origin_micros, time_extent_micros); | 2797 time_origin_micros, time_extent_micros); |
2874 const bool as_timeline = true; | 2798 const bool as_timeline = true; |
2875 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, | 2799 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, |
2876 Profiler::sample_buffer(), as_timeline); | 2800 Profiler::sample_buffer(), as_timeline); |
2877 } | 2801 } |
2878 | 2802 |
2879 | |
2880 void ProfilerService::ClearSamples() { | 2803 void ProfilerService::ClearSamples() { |
2881 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | 2804 SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
2882 if (sample_buffer == NULL) { | 2805 if (sample_buffer == NULL) { |
2883 return; | 2806 return; |
2884 } | 2807 } |
2885 | 2808 |
2886 Thread* thread = Thread::Current(); | 2809 Thread* thread = Thread::Current(); |
2887 Isolate* isolate = thread->isolate(); | 2810 Isolate* isolate = thread->isolate(); |
2888 | 2811 |
2889 // Disable thread interrupts while processing the buffer. | 2812 // Disable thread interrupts while processing the buffer. |
2890 DisableThreadInterruptsScope dtis(thread); | 2813 DisableThreadInterruptsScope dtis(thread); |
2891 | 2814 |
2892 ClearProfileVisitor clear_profile(isolate); | 2815 ClearProfileVisitor clear_profile(isolate); |
2893 sample_buffer->VisitSamples(&clear_profile); | 2816 sample_buffer->VisitSamples(&clear_profile); |
2894 } | 2817 } |
2895 | 2818 |
2896 #endif // !PRODUCT | 2819 #endif // !PRODUCT |
2897 | 2820 |
2898 } // namespace dart | 2821 } // namespace dart |
OLD | NEW |