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

Side by Side Diff: dart/runtime/vm/profiler.cc

Issue 119673004: Version 1.1.0-dev.5.2 (Closed) Base URL: http://dart.googlecode.com/svn/trunk/
Patch Set: Created 6 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « dart/runtime/vm/profiler.h ('k') | dart/runtime/vm/profiler_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 <cstdio>
6
7 #include "platform/utils.h" 5 #include "platform/utils.h"
8 6
7 #include "vm/allocation.h"
9 #include "vm/atomic.h" 8 #include "vm/atomic.h"
9 #include "vm/code_patcher.h"
10 #include "vm/isolate.h" 10 #include "vm/isolate.h"
11 #include "vm/json_stream.h" 11 #include "vm/json_stream.h"
12 #include "vm/native_symbol.h" 12 #include "vm/native_symbol.h"
13 #include "vm/object.h" 13 #include "vm/object.h"
14 #include "vm/os.h" 14 #include "vm/os.h"
15 #include "vm/profiler.h" 15 #include "vm/profiler.h"
16 #include "vm/signal_handler.h" 16 #include "vm/signal_handler.h"
17 #include "vm/simulator.h" 17 #include "vm/simulator.h"
18 18
19 namespace dart { 19 namespace dart {
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 if ((stack_lower == 0) || (stack_upper == 0)) { 211 if ((stack_lower == 0) || (stack_upper == 0)) {
212 stack_lower = 0; 212 stack_lower = 0;
213 stack_upper = 0; 213 stack_upper = 0;
214 } 214 }
215 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, 215 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
216 state.pc, state.fp, state.sp); 216 state.pc, state.fp, state.sp);
217 stackWalker.walk(); 217 stackWalker.walk();
218 } 218 }
219 219
220 220
221 void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream) { 221 struct AddressEntry {
222 uintptr_t pc;
223 uintptr_t ticks;
224 };
225
226
227 // A region of code. Each region is a kind of code (Dart, Collected, or Native).
228 class CodeRegion : public ZoneAllocated {
229 public:
230 enum Kind {
231 kDartCode,
232 kCollectedCode,
233 kNativeCode
234 };
235
236 CodeRegion(Kind kind, uintptr_t start, uintptr_t end) :
237 kind_(kind),
238 start_(start),
239 end_(end),
240 inclusive_ticks_(0),
241 exclusive_ticks_(0),
242 name_(NULL),
243 address_table_(new ZoneGrowableArray<AddressEntry>()) {
244 }
245
246 ~CodeRegion() {
247 }
248
249 uintptr_t start() const { return start_; }
250 void set_start(uintptr_t start) {
251 start_ = start;
252 }
253
254 uintptr_t end() const { return end_; }
255 void set_end(uintptr_t end) {
256 end_ = end;
257 }
258
259 void AdjustExtent(uintptr_t start, uintptr_t end) {
260 if (start < start_) {
261 start_ = start;
262 }
263 if (end > end_) {
264 end_ = end;
265 }
266 }
267
268 bool contains(uintptr_t pc) const {
269 return (pc >= start_) && (pc < end_);
270 }
271
272 intptr_t inclusive_ticks() const { return inclusive_ticks_; }
273 void set_inclusive_ticks(intptr_t inclusive_ticks) {
274 inclusive_ticks_ = inclusive_ticks;
275 }
276
277 intptr_t exclusive_ticks() const { return exclusive_ticks_; }
278 void set_exclusive_ticks(intptr_t exclusive_ticks) {
279 exclusive_ticks_ = exclusive_ticks;
280 }
281
282 const char* name() const { return name_; }
283 void SetName(const char* name) {
284 if (name == NULL) {
285 name_ = NULL;
286 }
287 intptr_t len = strlen(name);
288 name_ = Isolate::Current()->current_zone()->Alloc<const char>(len + 1);
289 strncpy(const_cast<char*>(name_), name, len);
290 const_cast<char*>(name_)[len] = '\0';
291 }
292
293 Kind kind() const { return kind_; }
294
295 static const char* KindToCString(Kind kind) {
296 switch (kind) {
297 case kDartCode:
298 return "Dart";
299 case kCollectedCode:
300 return "Collected";
301 case kNativeCode:
302 return "Native";
303 }
304 UNREACHABLE();
305 return NULL;
306 }
307
308 void AddTick(bool exclusive) {
309 if (exclusive) {
310 exclusive_ticks_++;
311 } else {
312 inclusive_ticks_++;
313 }
314 }
315
316 void AddTickAtAddress(uintptr_t pc) {
317 const intptr_t length = address_table_->length();
318 intptr_t i = 0;
319 for (; i < length; i++) {
320 AddressEntry& entry = (*address_table_)[i];
321 if (entry.pc == pc) {
322 entry.ticks++;
323 return;
324 }
325 if (entry.pc > pc) {
326 break;
327 }
328 }
329 AddressEntry entry;
330 entry.pc = pc;
331 entry.ticks = 1;
332 if (i < length) {
333 // Insert at i.
334 address_table_->InsertAt(i, entry);
335 } else {
336 // Add to end.
337 address_table_->Add(entry);
338 }
339 }
340
341
342 void PrintToJSONArray(JSONArray* events, bool full) {
343 JSONObject obj(events);
344 obj.AddProperty("type", "ProfileCode");
345 obj.AddProperty("kind", KindToCString(kind()));
346 obj.AddPropertyF("inclusive_ticks", "%" Pd "", inclusive_ticks());
347 obj.AddPropertyF("exclusive_ticks", "%" Pd "", exclusive_ticks());
348 if (kind() == kDartCode) {
349 // Look up code in Dart heap.
350 Code& code = Code::Handle(Code::LookupCode(start()));
351 Function& func = Function::Handle();
352 ASSERT(!code.IsNull());
353 func ^= code.function();
354 if (func.IsNull()) {
355 if (name() == NULL) {
356 GenerateAndSetSymbolName("Stub");
357 }
358 obj.AddPropertyF("start", "%" Px "", start());
359 obj.AddPropertyF("end", "%" Px "", end());
360 obj.AddProperty("name", name());
361 } else {
362 obj.AddProperty("code", code, !full);
363 }
364 } else if (kind() == kCollectedCode) {
365 if (name() == NULL) {
366 GenerateAndSetSymbolName("Collected");
367 }
368 obj.AddPropertyF("start", "%" Px "", start());
369 obj.AddPropertyF("end", "%" Px "", end());
370 obj.AddProperty("name", name());
371 } else {
372 ASSERT(kind() == kNativeCode);
373 if (name() == NULL) {
374 GenerateAndSetSymbolName("Native");
375 }
376 obj.AddPropertyF("start", "%" Px "", start());
377 obj.AddPropertyF("end", "%" Px "", end());
378 obj.AddProperty("name", name());
379 }
380 {
381 JSONArray ticks(&obj, "ticks");
382 for (intptr_t i = 0; i < address_table_->length(); i++) {
383 const AddressEntry& entry = (*address_table_)[i];
384 ticks.AddValueF("%" Px "", entry.pc);
385 ticks.AddValueF("%" Pd "", entry.ticks);
386 }
387 }
388 }
389
390 private:
391 void GenerateAndSetSymbolName(const char* prefix) {
392 const intptr_t kBuffSize = 512;
393 char buff[kBuffSize];
394 OS::SNPrint(&buff[0], kBuffSize-1, "%s [%" Px ", %" Px ")",
395 prefix, start(), end());
396 SetName(buff);
397 }
398
399 Kind kind_;
400 uintptr_t start_;
401 uintptr_t end_;
402 intptr_t inclusive_ticks_;
403 intptr_t exclusive_ticks_;
404 const char* name_;
405 ZoneGrowableArray<AddressEntry>* address_table_;
406
407 DISALLOW_COPY_AND_ASSIGN(CodeRegion);
408 };
409
410
411 // All code regions. Code region tables are built on demand when a profile
412 // is requested (through the service or on isolate shutdown).
413 class ProfilerCodeRegionTable : public ValueObject {
414 public:
415 explicit ProfilerCodeRegionTable(Isolate* isolate) :
416 heap_(isolate->heap()),
417 code_region_table_(new ZoneGrowableArray<CodeRegion*>(64)) {
418 }
419
420 ~ProfilerCodeRegionTable() {
421 }
422
423 void AddTick(uintptr_t pc, bool exclusive, bool tick_address) {
424 intptr_t index = FindIndex(pc);
425 if (index < 0) {
426 CodeRegion* code_region = CreateCodeRegion(pc);
427 ASSERT(code_region != NULL);
428 index = InsertCodeRegion(code_region);
429 }
430 ASSERT(index >= 0);
431 ASSERT(index < code_region_table_->length());
432 (*code_region_table_)[index]->AddTick(exclusive);
433 if (tick_address) {
434 (*code_region_table_)[index]->AddTickAtAddress(pc);
435 }
436 }
437
438 intptr_t Length() const { return code_region_table_->length(); }
439
440 CodeRegion* At(intptr_t idx) {
441 return (*code_region_table_)[idx];
442 }
443
444 private:
445 intptr_t FindIndex(uintptr_t pc) {
446 const intptr_t length = code_region_table_->length();
447 for (intptr_t i = 0; i < length; i++) {
448 const CodeRegion* code_region = (*code_region_table_)[i];
449 if (code_region->contains(pc)) {
450 return i;
451 }
452 }
453 return -1;
454 }
455
456 CodeRegion* CreateCodeRegion(uintptr_t pc) {
457 Code& code = Code::Handle(Code::LookupCode(pc));
458 if (!code.IsNull()) {
459 return new CodeRegion(CodeRegion::kDartCode, code.EntryPoint(),
460 code.EntryPoint() + code.Size());
461 }
462 if (heap_->CodeContains(pc)) {
463 const intptr_t kDartCodeAlignment = 0x10;
464 const intptr_t kDartCodeAlignmentMask = ~(kDartCodeAlignment - 1);
465 return new CodeRegion(CodeRegion::kCollectedCode,
466 (pc & kDartCodeAlignmentMask),
467 (pc & kDartCodeAlignmentMask) + kDartCodeAlignment);
468 }
469 uintptr_t native_start = 0;
470 char* native_name = NativeSymbolResolver::LookupSymbolName(pc,
471 &native_start);
472 if (native_name == NULL) {
473 return new CodeRegion(CodeRegion::kNativeCode, pc, pc + 1);
474 }
475 ASSERT(pc >= native_start);
476 CodeRegion* code_region =
477 new CodeRegion(CodeRegion::kNativeCode, native_start, pc + 1);
478 code_region->SetName(native_name);
479 free(native_name);
480 return code_region;
481 }
482
483 intptr_t InsertCodeRegion(CodeRegion* code_region) {
484 const intptr_t length = code_region_table_->length();
485 const uintptr_t start = code_region->start();
486 const uintptr_t end = code_region->end();
487 intptr_t i = 0;
488 for (; i < length; i++) {
489 CodeRegion* region = (*code_region_table_)[i];
490 if (region->contains(start) || region->contains(end - 1)) {
491 // We should only see overlapping native code regions.
492 ASSERT(region->kind() == CodeRegion::kNativeCode);
493 // When code regions overlap, they should be of the same kind.
494 ASSERT(region->kind() == code_region->kind());
495 // Overlapping code region.
496 region->AdjustExtent(start, end);
497 return i;
498 } else if (start >= region->end()) {
499 // Insert here.
500 break;
501 }
502 }
503 if (i != length) {
504 code_region_table_->InsertAt(i, code_region);
505 return i;
506 }
507 code_region_table_->Add(code_region);
508 return code_region_table_->length() - 1;
509 }
510
511 Heap* heap_;
512 ZoneGrowableArray<CodeRegion*>* code_region_table_;
513 };
514
515
516 void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream,
517 bool full) {
222 ASSERT(isolate == Isolate::Current()); 518 ASSERT(isolate == Isolate::Current());
223 UNIMPLEMENTED(); 519 // Disable profile interrupts while processing the buffer.
520 EndExecution(isolate);
521 MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
522 IsolateProfilerData* profiler_data = isolate->profiler_data();
523 if (profiler_data == NULL) {
524 JSONObject error(stream);
525 error.AddProperty("type", "Error");
526 error.AddProperty("text", "Isolate does not have profiling enabled.");
527 return;
528 }
529 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
530 ASSERT(sample_buffer != NULL);
531 {
532 StackZone zone(isolate);
533 {
534 // Build code region table.
535 ProfilerCodeRegionTable code_region_table(isolate);
536 intptr_t samples =
537 ProcessSamples(isolate, &code_region_table, sample_buffer);
538 {
539 // Serialize to JSON.
540 JSONObject obj(stream);
541 obj.AddProperty("type", "Profile");
542 obj.AddProperty("samples", samples);
543 JSONArray codes(&obj, "codes");
544 for (intptr_t i = 0; i < code_region_table.Length(); i++) {
545 CodeRegion* region = code_region_table.At(i);
546 ASSERT(region != NULL);
547 region->PrintToJSONArray(&codes, full);
548 }
549 }
550 }
551 }
552 // Enable profile interrupts.
553 BeginExecution(isolate);
224 } 554 }
225 555
226 556
227 static const char* FindSymbolName(uintptr_t pc, bool* symbol_name_allocated) { 557 intptr_t Profiler::ProcessSamples(Isolate* isolate,
228 // TODO(johnmccutchan): Differentiate between symbols which can't be found 558 ProfilerCodeRegionTable* code_region_table,
229 // and symbols which were GCed. (Heap::CodeContains). 559 SampleBuffer* sample_buffer) {
230 ASSERT(symbol_name_allocated != NULL); 560 int64_t start = OS::GetCurrentTimeMillis();
231 const char* symbol_name = "Unknown"; 561 intptr_t samples = 0;
232 *symbol_name_allocated = false; 562 for (intptr_t i = 0; i < sample_buffer->capacity(); i++) {
233 if (pc == 0) { 563 Sample sample = sample_buffer->GetSample(i);
234 return const_cast<char*>(Sample::kNoFrame); 564 if (sample.isolate != isolate) {
235 } 565 continue;
236 const Code& code = Code::Handle(Code::LookupCode(pc)); 566 }
237 if (!code.IsNull()) { 567 if (sample.timestamp == 0) {
238 const Function& function = Function::Handle(code.function()); 568 continue;
239 if (!function.IsNull()) { 569 }
240 const String& name = String::Handle(function.QualifiedUserVisibleName()); 570 samples += ProcessSample(isolate, code_region_table, &sample);
241 if (!name.IsNull()) { 571 }
242 symbol_name = name.ToCString(); 572 int64_t end = OS::GetCurrentTimeMillis();
243 return symbol_name; 573 if (FLAG_trace_profiled_isolates) {
244 } 574 int64_t delta = end - start;
245 } 575 OS::Print("Processed %" Pd " samples from %s in %" Pd64 " milliseconds.\n",
246 } else { 576 samples,
247 // Possibly a native symbol. 577 isolate->name(),
248 char* native_name = NativeSymbolResolver::LookupSymbolName(pc); 578 delta);
249 if (native_name != NULL) { 579 }
250 symbol_name = native_name; 580 return samples;
251 *symbol_name_allocated = true;
252 return symbol_name;
253 }
254 }
255 const intptr_t kBucketSize = 256;
256 const intptr_t kBucketMask = ~(kBucketSize - 1);
257 // Not a Dart symbol or a native symbol. Bin into buckets by PC.
258 pc &= kBucketMask;
259 {
260 const intptr_t kBuffSize = 256;
261 char buff[kBuffSize];
262 OS::SNPrint(&buff[0], kBuffSize-1, "Unknown [%" Px ", %" Px ")",
263 pc, pc + kBucketSize);
264 symbol_name = strdup(buff);
265 *symbol_name_allocated = true;
266 }
267 return symbol_name;
268 } 581 }
269 582
270 583
271 void Profiler::WriteTracingSample(Isolate* isolate, intptr_t pid, 584 intptr_t Profiler::ProcessSample(Isolate* isolate,
272 Sample* sample, JSONArray& events) { 585 ProfilerCodeRegionTable* code_region_table,
586 Sample* sample) {
273 Sample::SampleType type = sample->type; 587 Sample::SampleType type = sample->type;
274 intptr_t tid = Thread::ThreadIdToIntPtr(sample->tid); 588 if (type != Sample::kIsolateSample) {
275 double timestamp = static_cast<double>(sample->timestamp); 589 return 0;
276 const char* isolate_name = isolate->name(); 590 }
277 switch (type) { 591 if (sample->pcs[0] == 0) {
278 case Sample::kIsolateStart: { 592 // No frames in this sample.
279 JSONObject begin(&events); 593 return 0;
280 begin.AddProperty("ph", "B"); 594 }
281 begin.AddProperty("tid", tid); 595 intptr_t i = 0;
282 begin.AddProperty("pid", pid); 596 // i points to the leaf (exclusive) PC sample. Do not tick the address.
283 begin.AddProperty("name", isolate_name); 597 code_region_table->AddTick(sample->pcs[i], true, false);
284 begin.AddProperty("ts", timestamp); 598 // Give all frames an inclusive tick and tick the address.
285 } 599 for (; i < Sample::kNumStackFrames; i++) {
286 break; 600 if (sample->pcs[i] == 0) {
287 case Sample::kIsolateStop: { 601 break;
288 JSONObject begin(&events); 602 }
289 begin.AddProperty("ph", "E"); 603 code_region_table->AddTick(sample->pcs[i], false, true);
290 begin.AddProperty("tid", tid); 604 }
291 begin.AddProperty("pid", pid); 605 return 1;
292 begin.AddProperty("name", isolate_name);
293 begin.AddProperty("ts", timestamp);
294 }
295 break;
296 case Sample::kIsolateSample:
297 // Write "B" events.
298 for (int i = Sample::kNumStackFrames - 1; i >= 0; i--) {
299 bool symbol_name_allocated = false;
300 const char* symbol_name = FindSymbolName(sample->pcs[i],
301 &symbol_name_allocated);
302 {
303 JSONObject begin(&events);
304 begin.AddProperty("ph", "B");
305 begin.AddProperty("tid", tid);
306 begin.AddProperty("pid", pid);
307 begin.AddProperty("name", symbol_name);
308 begin.AddProperty("ts", timestamp);
309 }
310 if (symbol_name_allocated) {
311 free(const_cast<char*>(symbol_name));
312 }
313 }
314 // Write "E" events.
315 for (int i = 0; i < Sample::kNumStackFrames; i++) {
316 bool symbol_name_allocated = false;
317 const char* symbol_name = FindSymbolName(sample->pcs[i],
318 &symbol_name_allocated);
319 {
320 JSONObject begin(&events);
321 begin.AddProperty("ph", "E");
322 begin.AddProperty("tid", tid);
323 begin.AddProperty("pid", pid);
324 begin.AddProperty("name", symbol_name);
325 begin.AddProperty("ts", timestamp);
326 }
327 if (symbol_name_allocated) {
328 free(const_cast<char*>(symbol_name));
329 }
330 }
331 break;
332 default:
333 UNIMPLEMENTED();
334 }
335 } 606 }
336 607
337 608
338 void Profiler::WriteTracing(Isolate* isolate) { 609 void Profiler::WriteProfile(Isolate* isolate) {
339 if (isolate == NULL) { 610 if (isolate == NULL) {
340 return; 611 return;
341 } 612 }
342 if (!FLAG_profile) { 613 if (!FLAG_profile) {
343 return; 614 return;
344 } 615 }
345 ASSERT(initialized_); 616 ASSERT(initialized_);
346 if (FLAG_profile_dir == NULL) { 617 if (FLAG_profile_dir == NULL) {
347 return; 618 return;
348 } 619 }
349 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); 620 Dart_FileOpenCallback file_open = Isolate::file_open_callback();
350 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); 621 Dart_FileCloseCallback file_close = Isolate::file_close_callback();
351 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); 622 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
352 if ((file_open == NULL) || (file_close == NULL) || (file_write == NULL)) { 623 if ((file_open == NULL) || (file_close == NULL) || (file_write == NULL)) {
353 // Embedder has not provided necessary callbacks. 624 // Embedder has not provided necessary callbacks.
354 return; 625 return;
355 } 626 }
356 // We will be looking up code objects within the isolate. 627 // We will be looking up code objects within the isolate.
357 ASSERT(Isolate::Current() != NULL); 628 ASSERT(Isolate::Current() == isolate);
358 // We do not want to be interrupted while processing the buffer.
359 EndExecution(isolate);
360 MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
361 IsolateProfilerData* profiler_data = isolate->profiler_data();
362 if (profiler_data == NULL) {
363 return;
364 }
365 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
366 ASSERT(sample_buffer != NULL);
367 JSONStream stream(10 * MB); 629 JSONStream stream(10 * MB);
368 intptr_t pid = OS::ProcessId(); 630 intptr_t pid = OS::ProcessId();
369 { 631 PrintToJSONStream(isolate, &stream, true);
370 JSONArray events(&stream);
371 {
372 JSONObject process_name(&events);
373 process_name.AddProperty("name", "process_name");
374 process_name.AddProperty("ph", "M");
375 process_name.AddProperty("pid", pid);
376 {
377 JSONObject args(&process_name, "args");
378 args.AddProperty("name", "Dart VM");
379 }
380 }
381 for (intptr_t i = 0; i < sample_buffer->capacity(); i++) {
382 Sample* sample = sample_buffer->GetSample(i);
383 if (sample->isolate != isolate) {
384 continue;
385 }
386 if (sample->timestamp == 0) {
387 continue;
388 }
389 WriteTracingSample(isolate, pid, sample, events);
390 }
391 }
392 const char* format = "%s/dart-profile-%" Pd "-%" Pd ".json"; 632 const char* format = "%s/dart-profile-%" Pd "-%" Pd ".json";
393 intptr_t len = OS::SNPrint(NULL, 0, format, 633 intptr_t len = OS::SNPrint(NULL, 0, format,
394 FLAG_profile_dir, pid, isolate->main_port()); 634 FLAG_profile_dir, pid, isolate->main_port());
395 char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 635 char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
396 OS::SNPrint(filename, len + 1, format, 636 OS::SNPrint(filename, len + 1, format,
397 FLAG_profile_dir, pid, isolate->main_port()); 637 FLAG_profile_dir, pid, isolate->main_port());
398 void* f = file_open(filename, true); 638 void* f = file_open(filename, true);
399 if (f == NULL) { 639 if (f == NULL) {
400 // Cannot write. 640 // Cannot write.
401 return; 641 return;
402 } 642 }
403 TextBuffer* buffer = stream.buffer(); 643 TextBuffer* buffer = stream.buffer();
404 ASSERT(buffer != NULL); 644 ASSERT(buffer != NULL);
405 file_write(buffer->buf(), buffer->length(), f); 645 file_write(buffer->buf(), buffer->length(), f);
406 file_close(f); 646 file_close(f);
407 BeginExecution(isolate);
408 } 647 }
409 648
410 649
411 IsolateProfilerData::IsolateProfilerData(SampleBuffer* sample_buffer, 650 IsolateProfilerData::IsolateProfilerData(SampleBuffer* sample_buffer,
412 bool own_sample_buffer) { 651 bool own_sample_buffer) {
413 sample_buffer_ = sample_buffer; 652 sample_buffer_ = sample_buffer;
414 own_sample_buffer_ = own_sample_buffer; 653 own_sample_buffer_ = own_sample_buffer;
415 } 654 }
416 655
417 656
418 IsolateProfilerData::~IsolateProfilerData() { 657 IsolateProfilerData::~IsolateProfilerData() {
419 if (own_sample_buffer_) { 658 if (own_sample_buffer_) {
420 delete sample_buffer_; 659 delete sample_buffer_;
421 sample_buffer_ = NULL; 660 sample_buffer_ = NULL;
422 own_sample_buffer_ = false; 661 own_sample_buffer_ = false;
423 } 662 }
424 } 663 }
425 664
426 665
427 const char* Sample::kLookupSymbol = "Symbol Not Looked Up";
428 const char* Sample::kNoSymbol = "No Symbol Found";
429 const char* Sample::kNoFrame = "<no frame>";
430
431 void Sample::Init(SampleType type, Isolate* isolate, int64_t timestamp, 666 void Sample::Init(SampleType type, Isolate* isolate, int64_t timestamp,
432 ThreadId tid) { 667 ThreadId tid) {
433 this->timestamp = timestamp; 668 this->timestamp = timestamp;
434 this->tid = tid; 669 this->tid = tid;
435 this->isolate = isolate; 670 this->isolate = isolate;
436 for (intptr_t i = 0; i < kNumStackFrames; i++) { 671 for (intptr_t i = 0; i < kNumStackFrames; i++) {
437 pcs[i] = 0; 672 pcs[i] = 0;
438 } 673 }
439 this->type = type; 674 this->type = type;
440 vm_tags = 0; 675 vm_tags = 0;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 uintptr_t fp, 709 uintptr_t fp,
475 uintptr_t sp) : 710 uintptr_t sp) :
476 sample_(sample), 711 sample_(sample),
477 stack_lower_(stack_lower), 712 stack_lower_(stack_lower),
478 stack_upper_(stack_upper), 713 stack_upper_(stack_upper),
479 original_pc_(pc), 714 original_pc_(pc),
480 original_fp_(fp), 715 original_fp_(fp),
481 original_sp_(sp), 716 original_sp_(sp),
482 lower_bound_(stack_lower) { 717 lower_bound_(stack_lower) {
483 ASSERT(sample_ != NULL); 718 ASSERT(sample_ != NULL);
719 // Zero out the PCs before (re)using the sample.
720 for (int i = 0; i < Sample::kNumStackFrames; i++) {
721 sample_->pcs[i] = 0;
722 }
484 } 723 }
485 724
486 725
487 int ProfilerSampleStackWalker::walk() { 726 int ProfilerSampleStackWalker::walk() {
488 const intptr_t kMaxStep = 0x1000; // 4K. 727 const intptr_t kMaxStep = 0x1000; // 4K.
489 uword* pc = reinterpret_cast<uword*>(original_pc_); 728 uword* pc = reinterpret_cast<uword*>(original_pc_);
729 // Always store the exclusive PC.
730 sample_->pcs[0] = original_pc_;
490 #define WALK_STACK 731 #define WALK_STACK
491 #if defined(WALK_STACK) 732 #if defined(WALK_STACK)
492 uword* fp = reinterpret_cast<uword*>(original_fp_); 733 uword* fp = reinterpret_cast<uword*>(original_fp_);
493 uword* previous_fp = fp; 734 uword* previous_fp = fp;
494 if (original_sp_ > original_fp_) { 735 if (original_sp_ > original_fp_) {
495 // Stack pointer should not be above frame pointer. 736 // Stack pointer should not be above frame pointer.
496 return 0; 737 return 1;
497 } 738 }
498 intptr_t gap = original_fp_ - original_sp_; 739 intptr_t gap = original_fp_ - original_sp_;
499 if (gap >= kMaxStep) { 740 if (gap >= kMaxStep) {
500 // Gap between frame pointer and stack pointer is 741 // Gap between frame pointer and stack pointer is
501 // too large. 742 // too large.
502 return 0; 743 return 1;
503 } 744 }
504 if (original_sp_ < lower_bound_) { 745 if (original_sp_ < lower_bound_) {
505 // The stack pointer gives us a better lower bound than 746 // The stack pointer gives us a better lower bound than
506 // the isolates stack limit. 747 // the isolates stack limit.
507 lower_bound_ = original_sp_; 748 lower_bound_ = original_sp_;
508 } 749 }
509 int i = 0; 750 int i = 0;
510 for (; i < Sample::kNumStackFrames; i++) { 751 for (; i < Sample::kNumStackFrames; i++) {
511 sample_->pcs[i] = reinterpret_cast<uintptr_t>(pc); 752 sample_->pcs[i] = reinterpret_cast<uintptr_t>(pc);
512 if (!ValidFramePointer(fp)) { 753 if (!ValidFramePointer(fp)) {
513 break; 754 return i + 1;
514 } 755 }
515 pc = CallerPC(fp); 756 pc = CallerPC(fp);
516 previous_fp = fp; 757 previous_fp = fp;
517 fp = CallerFP(fp); 758 fp = CallerFP(fp);
518 intptr_t step = fp - previous_fp; 759 intptr_t step = fp - previous_fp;
519 if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) { 760 if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) {
520 // Frame pointer step is too large. 761 // Frame pointer step is too large.
521 // Frame pointer did not move to a higher address. 762 // Frame pointer did not move to a higher address.
522 // Frame pointer is outside of isolate stack bounds. 763 // Frame pointer is outside of isolate stack bounds.
523 break; 764 return i + 1;
524 } 765 }
525 // Move the lower bound up. 766 // Move the lower bound up.
526 lower_bound_ = reinterpret_cast<uintptr_t>(fp); 767 lower_bound_ = reinterpret_cast<uintptr_t>(fp);
527 } 768 }
528 return i; 769 return i;
529 #else 770 #else
530 sample_->pcs[0] = reinterpret_cast<uintptr_t>(pc); 771 sample_->pcs[0] = reinterpret_cast<uintptr_t>(pc);
531 return 0; 772 return 0;
532 #endif 773 #endif
533 } 774 }
(...skipping 16 matching lines...) Expand all
550 return false; 791 return false;
551 } 792 }
552 uintptr_t cursor = reinterpret_cast<uintptr_t>(fp); 793 uintptr_t cursor = reinterpret_cast<uintptr_t>(fp);
553 cursor += sizeof(fp); 794 cursor += sizeof(fp);
554 bool r = cursor >= lower_bound_ && cursor < stack_upper_; 795 bool r = cursor >= lower_bound_ && cursor < stack_upper_;
555 return r; 796 return r;
556 } 797 }
557 798
558 799
559 } // namespace dart 800 } // namespace dart
OLDNEW
« no previous file with comments | « dart/runtime/vm/profiler.h ('k') | dart/runtime/vm/profiler_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698