OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_HEAP_H_ | 5 #ifndef V8_HEAP_H_ |
6 #define V8_HEAP_H_ | 6 #define V8_HEAP_H_ |
7 | 7 |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "src/allocation.h" | 10 #include "src/allocation.h" |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 | 540 |
541 DISALLOW_COPY_AND_ASSIGN(ExternalStringTable); | 541 DISALLOW_COPY_AND_ASSIGN(ExternalStringTable); |
542 }; | 542 }; |
543 | 543 |
544 | 544 |
545 enum ArrayStorageAllocationMode { | 545 enum ArrayStorageAllocationMode { |
546 DONT_INITIALIZE_ARRAY_ELEMENTS, | 546 DONT_INITIALIZE_ARRAY_ELEMENTS, |
547 INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE | 547 INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE |
548 }; | 548 }; |
549 | 549 |
550 // TODO(ernstm): Move into GCTracer. | |
551 // A simple ring buffer class with maximum size known at compile time. | |
552 // The class only implements the functionality required in GCTracer. | |
553 template<typename T, size_t MAX_SIZE> | |
554 class RingBuffer { | |
555 public: | |
556 class const_iterator { | |
557 public: | |
558 const_iterator() : index_(0), elements_(NULL) {} | |
559 | |
560 const_iterator(size_t index, const T* elements) : | |
561 index_(index), elements_(elements) {} | |
562 | |
563 bool operator==(const const_iterator& rhs) const { | |
564 return elements_ == rhs.elements_ && | |
565 index_ == rhs.index_; | |
566 } | |
567 | |
568 bool operator!=(const const_iterator& rhs) const { | |
569 return elements_ != rhs.elements_ || | |
570 index_ != rhs.index_; | |
571 } | |
572 | |
573 operator const T*() const { | |
574 return elements_ + index_; | |
575 } | |
576 | |
577 const T* operator->() const { | |
578 return elements_ + index_; | |
579 } | |
580 | |
581 const T& operator*() const { | |
582 return elements_[index_]; | |
583 } | |
584 | |
585 const_iterator& operator++() { | |
586 index_ = (index_ + 1) % (MAX_SIZE + 1); | |
587 return *this; | |
588 } | |
589 | |
590 const_iterator& operator--() { | |
591 index_ = (index_ + MAX_SIZE) % (MAX_SIZE + 1); | |
592 return *this; | |
593 } | |
594 | |
595 private: | |
596 size_t index_; | |
597 const T* elements_; | |
598 }; | |
599 | |
600 RingBuffer() : begin_(0), end_(0) {} | |
601 | |
602 bool empty() const { return begin_ == end_; } | |
603 size_t size() const { | |
604 return (end_ - begin_ + MAX_SIZE + 1) % (MAX_SIZE + 1); | |
605 } | |
606 const_iterator begin() const { return const_iterator(begin_, elements_); } | |
607 const_iterator end() const { return const_iterator(end_, elements_); } | |
608 const_iterator back() const { return --end(); } | |
609 void push_back(const T& element) { | |
610 elements_[end_] = element; | |
611 end_ = (end_ + 1) % (MAX_SIZE + 1); | |
612 if (end_ == begin_) | |
613 begin_ = (begin_ + 1) % (MAX_SIZE + 1); | |
614 } | |
615 void push_front(const T& element) { | |
616 begin_ = (begin_ + MAX_SIZE) % (MAX_SIZE + 1); | |
617 if (begin_ == end_) | |
618 end_ = (end_ + MAX_SIZE) % (MAX_SIZE + 1); | |
619 elements_[begin_] = element; | |
620 } | |
621 | |
622 private: | |
623 T elements_[MAX_SIZE + 1]; | |
624 size_t begin_; | |
625 size_t end_; | |
626 | |
627 DISALLOW_COPY_AND_ASSIGN(RingBuffer); | |
628 }; | |
629 | |
630 | 550 |
631 // GCTracer collects and prints ONE line after each garbage collector | 551 // GCTracer collects and prints ONE line after each garbage collector |
632 // invocation IFF --trace_gc is used. | 552 // invocation IFF --trace_gc is used. |
633 | 553 |
634 // TODO(ernstm): Unit tests. Move to separate file. | |
635 class GCTracer BASE_EMBEDDED { | 554 class GCTracer BASE_EMBEDDED { |
636 public: | 555 public: |
637 class Scope BASE_EMBEDDED { | 556 class Scope BASE_EMBEDDED { |
638 public: | 557 public: |
639 enum ScopeId { | 558 enum ScopeId { |
640 EXTERNAL, | 559 EXTERNAL, |
641 MC_MARK, | 560 MC_MARK, |
642 MC_SWEEP, | 561 MC_SWEEP, |
643 MC_SWEEP_NEWSPACE, | 562 MC_SWEEP_NEWSPACE, |
644 MC_SWEEP_OLDSPACE, | 563 MC_SWEEP_OLDSPACE, |
(...skipping 14 matching lines...) Expand all Loading... |
659 }; | 578 }; |
660 | 579 |
661 Scope(GCTracer* tracer, ScopeId scope) | 580 Scope(GCTracer* tracer, ScopeId scope) |
662 : tracer_(tracer), | 581 : tracer_(tracer), |
663 scope_(scope) { | 582 scope_(scope) { |
664 start_time_ = base::OS::TimeCurrentMillis(); | 583 start_time_ = base::OS::TimeCurrentMillis(); |
665 } | 584 } |
666 | 585 |
667 ~Scope() { | 586 ~Scope() { |
668 ASSERT(scope_ < NUMBER_OF_SCOPES); // scope_ is unsigned. | 587 ASSERT(scope_ < NUMBER_OF_SCOPES); // scope_ is unsigned. |
669 tracer_->current_.scopes[scope_] += | 588 tracer_->scopes_[scope_] += base::OS::TimeCurrentMillis() - start_time_; |
670 base::OS::TimeCurrentMillis() - start_time_; | |
671 } | 589 } |
672 | 590 |
673 private: | 591 private: |
674 GCTracer* tracer_; | 592 GCTracer* tracer_; |
675 ScopeId scope_; | 593 ScopeId scope_; |
676 double start_time_; | 594 double start_time_; |
677 | 595 |
678 DISALLOW_COPY_AND_ASSIGN(Scope); | 596 DISALLOW_COPY_AND_ASSIGN(Scope); |
679 }; | 597 }; |
680 | 598 |
681 | |
682 class Event { | |
683 public: | |
684 enum Type { | |
685 SCAVENGER = 0, | |
686 MARK_COMPACTOR = 1, | |
687 START = 2 | |
688 }; | |
689 | |
690 // Default constructor leaves the event uninitialized. | |
691 Event() {} | |
692 | |
693 Event(Type type, | |
694 const char* gc_reason, | |
695 const char* collector_reason); | |
696 | |
697 // Returns a string describing the event type. | |
698 const char* TypeName(bool short_name) const; | |
699 | |
700 // Type of event | |
701 Type type; | |
702 | |
703 const char* gc_reason; | |
704 const char* collector_reason; | |
705 | |
706 // Timestamp set in the constructor. | |
707 double start_time; | |
708 | |
709 // Timestamp set in the destructor. | |
710 double end_time; | |
711 | |
712 // Size of objects in heap set in constructor. | |
713 intptr_t start_object_size; | |
714 | |
715 // Size of objects in heap set in destructor. | |
716 intptr_t end_object_size; | |
717 | |
718 // Size of memory allocated from OS set in constructor. | |
719 intptr_t start_memory_size; | |
720 | |
721 // Size of memory allocated from OS set in destructor. | |
722 intptr_t end_memory_size; | |
723 | |
724 // Total amount of space either wasted or contained in one of free lists | |
725 // before the current GC. | |
726 intptr_t start_holes_size; | |
727 | |
728 // Total amount of space either wasted or contained in one of free lists | |
729 // after the current GC. | |
730 intptr_t end_holes_size; | |
731 | |
732 // Number of incremental marking steps since creation of tracer. | |
733 // (value at start of event) | |
734 int incremental_marking_steps; | |
735 | |
736 // Cumulative duration of incremental marking steps since creation of | |
737 // tracer. (value at start of event) | |
738 double incremental_marking_duration; | |
739 | |
740 // Longest incremental marking step since start of marking. | |
741 // (value at start of event) | |
742 double longest_incremental_marking_step; | |
743 | |
744 // Amounts of time spent in different scopes during GC. | |
745 double scopes[Scope::NUMBER_OF_SCOPES]; | |
746 }; | |
747 | |
748 static const int kRingBufferMaxSize = 10; | |
749 | |
750 typedef RingBuffer<Event, kRingBufferMaxSize> EventBuffer; | |
751 | |
752 explicit GCTracer(Heap* heap); | 599 explicit GCTracer(Heap* heap); |
753 | 600 |
754 // Start collecting data. | 601 // Start collecting data. |
755 void Start(GarbageCollector collector, | 602 void start(GarbageCollector collector, const char* gc_reason, |
756 const char* gc_reason, | |
757 const char* collector_reason); | 603 const char* collector_reason); |
758 | 604 |
759 // Stop collecting data and print results. | 605 // Stop collecting data and print results. |
760 void Stop(); | 606 void stop(); |
761 | |
762 // Log an incremental marking step. | |
763 void AddIncrementalMarkingStep(double duration); | |
764 | 607 |
765 private: | 608 private: |
| 609 // Returns a string matching the collector. |
| 610 const char* CollectorString() const; |
| 611 |
766 // Print one detailed trace line in name=value format. | 612 // Print one detailed trace line in name=value format. |
767 // TODO(ernstm): Move to Heap. | |
768 void PrintNVP() const; | 613 void PrintNVP() const; |
769 | 614 |
770 // Print one trace line. | 615 // Print one trace line. |
771 // TODO(ernstm): Move to Heap. | |
772 void Print() const; | 616 void Print() const; |
773 | 617 |
774 // Pointer to the heap that owns this tracer. | 618 // Timestamp set in the constructor. |
| 619 double start_time_; |
| 620 |
| 621 // Timestamp set in the destructor. |
| 622 double end_time_; |
| 623 |
| 624 // Size of objects in heap set in constructor. |
| 625 intptr_t start_object_size_; |
| 626 |
| 627 // Size of objects in heap set in destructor. |
| 628 intptr_t end_object_size_; |
| 629 |
| 630 // Size of memory allocated from OS set in constructor. |
| 631 intptr_t start_memory_size_; |
| 632 |
| 633 // Size of memory allocated from OS set in destructor. |
| 634 intptr_t end_memory_size_; |
| 635 |
| 636 // Type of collector. |
| 637 GarbageCollector collector_; |
| 638 |
| 639 // Amounts of time spent in different scopes during GC. |
| 640 double scopes_[Scope::NUMBER_OF_SCOPES]; |
| 641 |
| 642 // Total amount of space either wasted or contained in one of free lists |
| 643 // before the current GC. |
| 644 intptr_t in_free_list_or_wasted_before_gc_; |
| 645 |
| 646 // Difference between space used in the heap at the beginning of the current |
| 647 // collection and the end of the previous collection. |
| 648 intptr_t allocated_since_last_gc_; |
| 649 |
| 650 // Amount of time spent in mutator that is time elapsed between end of the |
| 651 // previous collection and the beginning of the current one. |
| 652 double spent_in_mutator_; |
| 653 |
| 654 // Incremental marking steps counters. |
| 655 int steps_count_; |
| 656 double steps_took_; |
| 657 double longest_step_; |
| 658 int steps_count_since_last_gc_; |
| 659 double steps_took_since_last_gc_; |
| 660 |
775 Heap* heap_; | 661 Heap* heap_; |
776 | 662 |
777 // Current tracer event. Populated during Start/Stop cycle. Valid after Stop() | 663 const char* gc_reason_; |
778 // has returned. | 664 const char* collector_reason_; |
779 Event current_; | |
780 | |
781 // Previous tracer event. | |
782 Event previous_; | |
783 | |
784 // Previous MARK_COMPACTOR event. | |
785 Event previous_mark_compactor_event_; | |
786 | |
787 // RingBuffers for SCAVENGER events. | |
788 EventBuffer scavenger_events_; | |
789 | |
790 // RingBuffers for MARK_COMPACTOR events. | |
791 EventBuffer mark_compactor_events_; | |
792 | |
793 // Cumulative number of incremental marking steps since creation of tracer. | |
794 int incremental_marking_steps_; | |
795 | |
796 // Cumulative duration of incremental marking steps since creation of tracer. | |
797 double incremental_marking_duration_; | |
798 | |
799 // Longest incremental marking step since start of marking. | |
800 double longest_incremental_marking_step_; | |
801 | 665 |
802 DISALLOW_COPY_AND_ASSIGN(GCTracer); | 666 DISALLOW_COPY_AND_ASSIGN(GCTracer); |
803 }; | 667 }; |
804 | 668 |
805 | 669 |
806 class Heap { | 670 class Heap { |
807 public: | 671 public: |
808 // Configure heap size in MB before setup. Return false if the heap has been | 672 // Configure heap size in MB before setup. Return false if the heap has been |
809 // set up already. | 673 // set up already. |
810 bool ConfigureHeap(int max_semi_space_size, | 674 bool ConfigureHeap(int max_semi_space_size, |
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1496 | 1360 |
1497 void IncrementCodeGeneratedBytes(bool is_crankshafted, int size) { | 1361 void IncrementCodeGeneratedBytes(bool is_crankshafted, int size) { |
1498 if (is_crankshafted) { | 1362 if (is_crankshafted) { |
1499 crankshaft_codegen_bytes_generated_ += size; | 1363 crankshaft_codegen_bytes_generated_ += size; |
1500 } else { | 1364 } else { |
1501 full_codegen_bytes_generated_ += size; | 1365 full_codegen_bytes_generated_ += size; |
1502 } | 1366 } |
1503 } | 1367 } |
1504 | 1368 |
1505 // Update GC statistics that are tracked on the Heap. | 1369 // Update GC statistics that are tracked on the Heap. |
1506 void UpdateCumulativeGCStatistics(double duration, | 1370 void UpdateGCStatistics(double start_time, double end_time, |
1507 double spent_in_mutator, | 1371 double spent_in_mutator, double marking_time); |
1508 double marking_time); | |
1509 | 1372 |
1510 // Returns maximum GC pause. | 1373 // Returns maximum GC pause. |
1511 double get_max_gc_pause() { return max_gc_pause_; } | 1374 double get_max_gc_pause() { return max_gc_pause_; } |
1512 | 1375 |
1513 // Returns maximum size of objects alive after GC. | 1376 // Returns maximum size of objects alive after GC. |
1514 intptr_t get_max_alive_after_gc() { return max_alive_after_gc_; } | 1377 intptr_t get_max_alive_after_gc() { return max_alive_after_gc_; } |
1515 | 1378 |
1516 // Returns minimal interval between two subsequent collections. | 1379 // Returns minimal interval between two subsequent collections. |
1517 double get_min_in_mutator() { return min_in_mutator_; } | 1380 double get_min_in_mutator() { return min_in_mutator_; } |
1518 | 1381 |
(...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2368 | 2231 |
2369 // Total time spent in GC. | 2232 // Total time spent in GC. |
2370 double total_gc_time_ms_; | 2233 double total_gc_time_ms_; |
2371 | 2234 |
2372 // Maximum size of objects alive after GC. | 2235 // Maximum size of objects alive after GC. |
2373 intptr_t max_alive_after_gc_; | 2236 intptr_t max_alive_after_gc_; |
2374 | 2237 |
2375 // Minimal interval between two subsequent collections. | 2238 // Minimal interval between two subsequent collections. |
2376 double min_in_mutator_; | 2239 double min_in_mutator_; |
2377 | 2240 |
| 2241 // Size of objects alive after last GC. |
| 2242 intptr_t alive_after_last_gc_; |
| 2243 |
| 2244 double last_gc_end_timestamp_; |
| 2245 |
2378 // Cumulative GC time spent in marking | 2246 // Cumulative GC time spent in marking |
2379 double marking_time_; | 2247 double marking_time_; |
2380 | 2248 |
2381 // Cumulative GC time spent in sweeping | 2249 // Cumulative GC time spent in sweeping |
2382 double sweeping_time_; | 2250 double sweeping_time_; |
2383 | 2251 |
2384 MarkCompactCollector mark_compact_collector_; | 2252 MarkCompactCollector mark_compact_collector_; |
2385 | 2253 |
2386 StoreBuffer store_buffer_; | 2254 StoreBuffer store_buffer_; |
2387 | 2255 |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2912 DisallowHeapAllocation no_allocation; // i.e. no gc allowed. | 2780 DisallowHeapAllocation no_allocation; // i.e. no gc allowed. |
2913 | 2781 |
2914 private: | 2782 private: |
2915 DISALLOW_IMPLICIT_CONSTRUCTORS(PathTracer); | 2783 DISALLOW_IMPLICIT_CONSTRUCTORS(PathTracer); |
2916 }; | 2784 }; |
2917 #endif // DEBUG | 2785 #endif // DEBUG |
2918 | 2786 |
2919 } } // namespace v8::internal | 2787 } } // namespace v8::internal |
2920 | 2788 |
2921 #endif // V8_HEAP_H_ | 2789 #endif // V8_HEAP_H_ |
OLD | NEW |