| 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 <cstdlib> | 5 #include <cstdlib> |
| 6 | 6 |
| 7 #include "vm/isolate.h" | 7 #include "vm/isolate.h" |
| 8 #include "vm/json_stream.h" | 8 #include "vm/json_stream.h" |
| 9 #include "vm/lockers.h" | 9 #include "vm/lockers.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 | 325 |
| 326 | 326 |
| 327 TimelineEventRecorder::TimelineEventRecorder() { | 327 TimelineEventRecorder::TimelineEventRecorder() { |
| 328 } | 328 } |
| 329 | 329 |
| 330 | 330 |
| 331 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const { | 331 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const { |
| 332 } | 332 } |
| 333 | 333 |
| 334 | 334 |
| 335 TimelineEvent* TimelineEventRecorder::ThreadBlockStartEvent() { |
| 336 // Grab the thread's timeline event block. |
| 337 Thread* thread = Thread::Current(); |
| 338 TimelineEventBlock* thread_block = thread->timeline_block(); |
| 339 if ((thread_block == NULL) || thread_block->IsFull()) { |
| 340 // If it is full, request a new block. |
| 341 thread_block = GetNewBlock(); |
| 342 thread->set_timeline_block(thread_block); |
| 343 } |
| 344 if (thread_block == NULL) { |
| 345 // Could not allocate block. |
| 346 return NULL; |
| 347 } |
| 348 ASSERT(thread_block != NULL); |
| 349 ASSERT(!thread_block->IsFull()); |
| 350 return thread_block->StartEvent(); |
| 351 } |
| 352 |
| 353 |
| 335 void TimelineEventRecorder::WriteTo(const char* directory) { | 354 void TimelineEventRecorder::WriteTo(const char* directory) { |
| 336 Isolate* isolate = Isolate::Current(); | 355 Isolate* isolate = Isolate::Current(); |
| 337 | 356 |
| 338 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); | 357 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); |
| 339 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); | 358 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); |
| 340 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); | 359 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); |
| 341 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { | 360 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { |
| 342 return; | 361 return; |
| 343 } | 362 } |
| 344 | 363 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 355 void* file = (*file_open)(filename, true); | 374 void* file = (*file_open)(filename, true); |
| 356 if (file == NULL) { | 375 if (file == NULL) { |
| 357 OS::Print("Failed to write timeline file: %s\n", filename); | 376 OS::Print("Failed to write timeline file: %s\n", filename); |
| 358 return; | 377 return; |
| 359 } | 378 } |
| 360 (*file_write)(js.buffer()->buf(), js.buffer()->length(), file); | 379 (*file_write)(js.buffer()->buf(), js.buffer()->length(), file); |
| 361 (*file_close)(file); | 380 (*file_close)(file); |
| 362 } | 381 } |
| 363 | 382 |
| 364 | 383 |
| 365 intptr_t TimelineEventRingRecorder::SizeForCapacity(intptr_t capacity) { | |
| 366 return sizeof(TimelineEvent) * capacity; | |
| 367 } | |
| 368 | |
| 369 | 384 |
| 370 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity) | 385 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity) |
| 371 : events_(NULL), | 386 : blocks_(NULL), |
| 372 event_objects_(Array::null()), | 387 event_objects_(Array::null()), |
| 373 cursor_(0), | 388 capacity_(capacity), |
| 374 capacity_(capacity) { | 389 num_blocks_(0), |
| 375 if (FLAG_trace_timeline) { | 390 block_cursor_(0) { |
| 376 // 32-bit: 262,144 bytes per isolate. | 391 // Capacity must be a multiple of TimelineEventBlock::kBlockSize |
| 377 // 64-bit: 393,216 bytes per isolate. | 392 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0); |
| 378 // NOTE: Internal isolates (vm and service) do not have a timeline | 393 // Allocate blocks array. |
| 379 // event buffer. | 394 num_blocks_ = capacity / TimelineEventBlock::kBlockSize; |
| 380 OS::Print("TimelineEventRingRecorder is %" Pd " bytes (%" Pd " events)\n", | 395 blocks_ = |
| 381 SizeForCapacity(capacity), | 396 reinterpret_cast<TimelineEventBlock**>( |
| 382 capacity); | 397 calloc(num_blocks_, sizeof(TimelineEventBlock*))); |
| 398 // Allocate each block. |
| 399 for (intptr_t i = 0; i < num_blocks_; i++) { |
| 400 blocks_[i] = new TimelineEventBlock(i); |
| 383 } | 401 } |
| 384 events_ = | 402 // Chain blocks together. |
| 385 reinterpret_cast<TimelineEvent*>(calloc(capacity, sizeof(TimelineEvent))); | 403 for (intptr_t i = 0; i < num_blocks_ - 1; i++) { |
| 404 blocks_[i]->set_next(blocks_[i + 1]); |
| 405 } |
| 386 const Array& array = Array::Handle(Array::New(capacity, Heap::kOld)); | 406 const Array& array = Array::Handle(Array::New(capacity, Heap::kOld)); |
| 387 event_objects_ = array.raw(); | 407 event_objects_ = array.raw(); |
| 388 } | 408 } |
| 389 | 409 |
| 390 | 410 |
| 391 TimelineEventRingRecorder::~TimelineEventRingRecorder() { | 411 TimelineEventRingRecorder::~TimelineEventRingRecorder() { |
| 392 for (intptr_t i = 0; i < capacity_; i++) { | 412 // Delete all blocks. |
| 393 // Clear any extra data. | 413 for (intptr_t i = 0; i < num_blocks_; i++) { |
| 394 events_[i].Reset(); | 414 TimelineEventBlock* block = blocks_[i]; |
| 415 delete block; |
| 395 } | 416 } |
| 396 free(events_); | 417 free(blocks_); |
| 397 event_objects_ = Array::null(); | 418 event_objects_ = Array::null(); |
| 398 } | 419 } |
| 399 | 420 |
| 400 | 421 |
| 401 void TimelineEventRingRecorder::PrintJSONEvents(JSONArray* events) const { | 422 void TimelineEventRingRecorder::PrintJSONEvents(JSONArray* events) const { |
| 402 for (intptr_t i = 0; i < capacity_; i++) { | 423 // TODO(johnmccutchan): This output needs to start with the oldest block |
| 403 if (events_[i].IsValid()) { | 424 // first. |
| 404 events->AddValue(&events_[i]); | 425 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) { |
| 426 TimelineEventBlock* block = blocks_[block_idx]; |
| 427 if (block->IsEmpty()) { |
| 428 // Skip empty blocks. |
| 429 continue; |
| 430 } |
| 431 for (intptr_t event_idx = 0; event_idx < block->length(); event_idx++) { |
| 432 TimelineEvent* event = block->At(event_idx); |
| 433 if (event->IsValid()) { |
| 434 events->AddValue(event); |
| 435 } |
| 405 } | 436 } |
| 406 } | 437 } |
| 407 } | 438 } |
| 408 | 439 |
| 409 | 440 |
| 410 void TimelineEventRingRecorder::PrintJSON(JSONStream* js) { | 441 void TimelineEventRingRecorder::PrintJSON(JSONStream* js) { |
| 442 MutexLocker ml(&lock_); |
| 411 JSONObject topLevel(js); | 443 JSONObject topLevel(js); |
| 412 topLevel.AddProperty("type", "_Timeline"); | 444 topLevel.AddProperty("type", "_Timeline"); |
| 413 { | 445 { |
| 414 JSONArray events(&topLevel, "traceEvents"); | 446 JSONArray events(&topLevel, "traceEvents"); |
| 415 PrintJSONMeta(&events); | 447 PrintJSONMeta(&events); |
| 416 PrintJSONEvents(&events); | 448 PrintJSONEvents(&events); |
| 417 } | 449 } |
| 418 } | 450 } |
| 419 | 451 |
| 420 | 452 |
| 421 intptr_t TimelineEventRingRecorder::GetNextIndex() { | 453 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlock() { |
| 422 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_); | 454 MutexLocker ml(&lock_); |
| 423 return cursor % capacity_; | 455 return GetNewBlockLocked(); |
| 424 } | 456 } |
| 425 | 457 |
| 426 | 458 |
| 459 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() { |
| 460 if (block_cursor_ == num_blocks_) { |
| 461 block_cursor_ = 0; |
| 462 } |
| 463 TimelineEventBlock* block = blocks_[block_cursor_++]; |
| 464 block->Reset(); |
| 465 return block; |
| 466 } |
| 467 |
| 468 |
| 427 void TimelineEventRingRecorder::VisitObjectPointers( | 469 void TimelineEventRingRecorder::VisitObjectPointers( |
| 428 ObjectPointerVisitor* visitor) { | 470 ObjectPointerVisitor* visitor) { |
| 429 visitor->VisitPointer(reinterpret_cast<RawObject**>(&event_objects_)); | 471 visitor->VisitPointer(reinterpret_cast<RawObject**>(&event_objects_)); |
| 430 } | 472 } |
| 431 | 473 |
| 432 | 474 |
| 433 TimelineEvent* TimelineEventRingRecorder::StartEvent(const Object& obj) { | 475 TimelineEvent* TimelineEventRingRecorder::StartEvent(const Object& obj) { |
| 434 ASSERT(events_ != NULL); | 476 TimelineEvent* event = StartEvent(); |
| 435 uintptr_t index = GetNextIndex(); | 477 if (event == NULL) { |
| 478 return NULL; |
| 479 } |
| 480 // Grab the thread's timeline event block which contains |event|. |
| 481 Thread* thread = Thread::Current(); |
| 482 TimelineEventBlock* thread_block = thread->timeline_block(); |
| 483 ASSERT(thread_block != NULL); |
| 484 ASSERT(thread_block->length() > 0); |
| 485 const intptr_t block_index = thread_block->block_index(); |
| 486 const intptr_t event_objects_index = |
| 487 block_index * TimelineEventBlock::kBlockSize + thread_block->length() - 1; |
| 436 const Array& event_objects = Array::Handle(event_objects_); | 488 const Array& event_objects = Array::Handle(event_objects_); |
| 437 event_objects.SetAt(index, obj); | 489 event_objects.SetAt(event_objects_index, obj); |
| 438 return &events_[index]; | 490 return event; |
| 439 } | 491 } |
| 440 | 492 |
| 441 | 493 |
| 442 TimelineEvent* TimelineEventRingRecorder::StartEvent() { | 494 TimelineEvent* TimelineEventRingRecorder::StartEvent() { |
| 443 ASSERT(events_ != NULL); | 495 return ThreadBlockStartEvent(); |
| 444 uintptr_t index = GetNextIndex(); | |
| 445 return &events_[index]; | |
| 446 } | 496 } |
| 447 | 497 |
| 498 |
| 448 void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) { | 499 void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) { |
| 449 ASSERT(events_ != NULL); | |
| 450 // no-op. | 500 // no-op. |
| 451 } | 501 } |
| 452 | 502 |
| 453 | 503 |
| 454 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() { | 504 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() { |
| 455 } | 505 } |
| 456 | 506 |
| 457 | 507 |
| 458 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() { | 508 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() { |
| 459 } | 509 } |
| 460 | 510 |
| 461 | 511 |
| 462 void TimelineEventStreamingRecorder::PrintJSON(JSONStream* js) { | 512 void TimelineEventStreamingRecorder::PrintJSON(JSONStream* js) { |
| 463 JSONObject topLevel(js); | 513 JSONObject topLevel(js); |
| 464 topLevel.AddProperty("type", "_Timeline"); | 514 topLevel.AddProperty("type", "_Timeline"); |
| 465 { | 515 { |
| 466 JSONArray events(&topLevel, "traceEvents"); | 516 JSONArray events(&topLevel, "traceEvents"); |
| 467 PrintJSONMeta(&events); | 517 PrintJSONMeta(&events); |
| 468 } | 518 } |
| 469 } | 519 } |
| 470 | 520 |
| 521 |
| 471 void TimelineEventStreamingRecorder::VisitObjectPointers( | 522 void TimelineEventStreamingRecorder::VisitObjectPointers( |
| 472 ObjectPointerVisitor* visitor) { | 523 ObjectPointerVisitor* visitor) { |
| 473 // no-op. | 524 // no-op. |
| 474 } | 525 } |
| 475 | 526 |
| 476 | 527 |
| 477 TimelineEvent* TimelineEventStreamingRecorder::StartEvent( | 528 TimelineEvent* TimelineEventStreamingRecorder::StartEvent( |
| 478 const Object& object) { | 529 const Object& object) { |
| 479 // The streaming recorder does not track Dart objects. | 530 // The streaming recorder does not track Dart objects. |
| 480 return StartEvent(); | 531 return StartEvent(); |
| 481 } | 532 } |
| 482 | 533 |
| 483 | 534 |
| 484 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() { | 535 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() { |
| 485 TimelineEvent* event = new TimelineEvent(); | 536 TimelineEvent* event = new TimelineEvent(); |
| 486 return event; | 537 return event; |
| 487 } | 538 } |
| 488 | 539 |
| 489 | 540 |
| 490 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) { | 541 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) { |
| 491 StreamEvent(event); | 542 StreamEvent(event); |
| 492 delete event; | 543 delete event; |
| 493 } | 544 } |
| 494 | 545 |
| 495 | 546 |
| 496 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder() | 547 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder() |
| 497 : head_(NULL) { | 548 : head_(NULL), |
| 549 block_index_(0) { |
| 498 GetNewBlock(); | 550 GetNewBlock(); |
| 499 } | 551 } |
| 500 | 552 |
| 501 | 553 |
| 502 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js) { | 554 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js) { |
| 503 MutexLocker ml(&lock_); | 555 MutexLocker ml(&lock_); |
| 504 JSONObject topLevel(js); | 556 JSONObject topLevel(js); |
| 505 topLevel.AddProperty("type", "_Timeline"); | 557 topLevel.AddProperty("type", "_Timeline"); |
| 506 { | 558 { |
| 507 JSONArray events(&topLevel, "traceEvents"); | 559 JSONArray events(&topLevel, "traceEvents"); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 522 // no-op. | 574 // no-op. |
| 523 } | 575 } |
| 524 | 576 |
| 525 | 577 |
| 526 TimelineEvent* TimelineEventEndlessRecorder::StartEvent(const Object& object) { | 578 TimelineEvent* TimelineEventEndlessRecorder::StartEvent(const Object& object) { |
| 527 return StartEvent(); | 579 return StartEvent(); |
| 528 } | 580 } |
| 529 | 581 |
| 530 | 582 |
| 531 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { | 583 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { |
| 532 // Grab the thread's timeline event block. | 584 return ThreadBlockStartEvent(); |
| 533 Thread* thread = Thread::Current(); | |
| 534 TimelineEventBlock* thread_block = thread->timeline_block(); | |
| 535 if (thread_block == NULL) { | |
| 536 return NULL; | |
| 537 } | |
| 538 ASSERT(thread_block != NULL); | |
| 539 if (thread_block->IsFull()) { | |
| 540 // If it is full, request a new block. | |
| 541 thread_block = GetNewBlock(); | |
| 542 thread->set_timeline_block(thread_block); | |
| 543 } | |
| 544 ASSERT(!thread_block->IsFull()); | |
| 545 return thread_block->StartEvent(); | |
| 546 } | 585 } |
| 547 | 586 |
| 548 | 587 |
| 549 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) { | 588 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) { |
| 550 // no-op. | 589 // no-op. |
| 551 } | 590 } |
| 552 | 591 |
| 553 | 592 |
| 554 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked() { | 593 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked() { |
| 555 TimelineEventBlock* block = new TimelineEventBlock(); | 594 TimelineEventBlock* block = new TimelineEventBlock(block_index_++); |
| 556 block->set_next(head_); | 595 block->set_next(head_); |
| 557 head_ = block; | 596 head_ = block; |
| 558 return head_; | 597 return head_; |
| 559 } | 598 } |
| 560 | 599 |
| 561 | 600 |
| 562 void TimelineEventEndlessRecorder::PrintJSONEvents(JSONArray* events) const { | 601 void TimelineEventEndlessRecorder::PrintJSONEvents(JSONArray* events) const { |
| 563 TimelineEventBlock* current = head_; | 602 TimelineEventBlock* current = head_; |
| 564 while (current != NULL) { | 603 while (current != NULL) { |
| 565 intptr_t length = current->length(); | 604 intptr_t length = current->length(); |
| 566 for (intptr_t i = 0; i < length; i++) { | 605 for (intptr_t i = 0; i < length; i++) { |
| 567 TimelineEvent* event = current->At(i); | 606 TimelineEvent* event = current->At(i); |
| 568 if (!event->IsValid()) { | 607 if (!event->IsValid()) { |
| 569 continue; | 608 continue; |
| 570 } | 609 } |
| 571 events->AddValue(event); | 610 events->AddValue(event); |
| 572 } | 611 } |
| 573 current = current->next(); | 612 current = current->next(); |
| 574 } | 613 } |
| 575 } | 614 } |
| 576 | 615 |
| 577 | 616 |
| 578 TimelineEventBlock::TimelineEventBlock() | 617 TimelineEventBlock::TimelineEventBlock(intptr_t block_index) |
| 579 : next_(NULL), | 618 : next_(NULL), |
| 580 length_(0) { | 619 length_(0), |
| 620 block_index_(block_index) { |
| 581 } | 621 } |
| 582 | 622 |
| 583 | 623 |
| 624 TimelineEventBlock::~TimelineEventBlock() { |
| 625 Reset(); |
| 626 } |
| 627 |
| 628 |
| 584 TimelineEvent* TimelineEventBlock::StartEvent() { | 629 TimelineEvent* TimelineEventBlock::StartEvent() { |
| 585 ASSERT(!IsFull()); | 630 ASSERT(!IsFull()); |
| 586 return &events_[length_++]; | 631 return &events_[length_++]; |
| 587 } | 632 } |
| 588 | 633 |
| 589 | 634 |
| 590 ThreadId TimelineEventBlock::thread() const { | 635 ThreadId TimelineEventBlock::thread() const { |
| 591 ASSERT(length_ > 0); | 636 ASSERT(length_ > 0); |
| 592 return events_[0].thread(); | 637 return events_[0].thread(); |
| 593 } | 638 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 618 if (last_time > At(i)->TimeOrigin()) { | 663 if (last_time > At(i)->TimeOrigin()) { |
| 619 return false; | 664 return false; |
| 620 } | 665 } |
| 621 last_time = At(i)->TimeOrigin(); | 666 last_time = At(i)->TimeOrigin(); |
| 622 } | 667 } |
| 623 | 668 |
| 624 return true; | 669 return true; |
| 625 } | 670 } |
| 626 | 671 |
| 627 | 672 |
| 673 void TimelineEventBlock::Reset() { |
| 674 for (intptr_t i = 0; i < kBlockSize; i++) { |
| 675 // Clear any extra data. |
| 676 events_[i].Reset(); |
| 677 } |
| 678 length_ = 0; |
| 679 } |
| 680 |
| 681 |
| 628 TimelineEventBlockIterator::TimelineEventBlockIterator( | 682 TimelineEventBlockIterator::TimelineEventBlockIterator( |
| 629 TimelineEventEndlessRecorder* recorder) | 683 TimelineEventEndlessRecorder* recorder) |
| 630 : current_(NULL), | 684 : current_(NULL), |
| 631 recorder_(recorder) { | 685 recorder_(recorder) { |
| 632 if (recorder_ == NULL) { | 686 if (recorder_ == NULL) { |
| 633 return; | 687 return; |
| 634 } | 688 } |
| 635 recorder->lock_.Lock(); | 689 recorder->lock_.Lock(); |
| 636 } | 690 } |
| 637 | 691 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 655 } | 709 } |
| 656 if (current_ == NULL) { | 710 if (current_ == NULL) { |
| 657 current_ = recorder_->head_; | 711 current_ = recorder_->head_; |
| 658 } else { | 712 } else { |
| 659 current_ = current_->next(); | 713 current_ = current_->next(); |
| 660 } | 714 } |
| 661 return current_ != NULL; | 715 return current_ != NULL; |
| 662 } | 716 } |
| 663 | 717 |
| 664 } // namespace dart | 718 } // namespace dart |
| OLD | NEW |