Chromium Code Reviews| Index: src/gc-tracer.h |
| diff --git a/src/gc-tracer.h b/src/gc-tracer.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..cf2a03a6ead51625510dadf88d7f9fcc3cdb1823 |
| --- /dev/null |
| +++ b/src/gc-tracer.h |
| @@ -0,0 +1,268 @@ |
| +// Copyright 2014 the V8 project authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef V8_GC_TRACER_H_ |
| +#define V8_GC_TRACER_H_ |
| + |
| +namespace v8 { |
| +namespace internal { |
| + |
| +// TODO(ernstm): Move into GCTracer. |
|
Hannes Payer (out of office)
2014/07/24 09:03:33
remove todo
ernstm
2014/07/24 11:49:49
Done.
|
| +// A simple ring buffer class with maximum size known at compile time. |
| +// The class only implements the functionality required in GCTracer. |
| +template<typename T, size_t MAX_SIZE> |
| +class RingBuffer { |
| + public: |
| + class const_iterator { |
| + public: |
| + const_iterator() : index_(0), elements_(NULL) {} |
| + |
| + const_iterator(size_t index, const T* elements) : |
| + index_(index), elements_(elements) {} |
| + |
| + bool operator==(const const_iterator& rhs) const { |
| + return elements_ == rhs.elements_ && |
| + index_ == rhs.index_; |
| + } |
| + |
| + bool operator!=(const const_iterator& rhs) const { |
| + return elements_ != rhs.elements_ || |
| + index_ != rhs.index_; |
| + } |
| + |
| + operator const T*() const { |
| + return elements_ + index_; |
| + } |
| + |
| + const T* operator->() const { |
| + return elements_ + index_; |
| + } |
| + |
| + const T& operator*() const { |
| + return elements_[index_]; |
| + } |
| + |
| + const_iterator& operator++() { |
| + index_ = (index_ + 1) % (MAX_SIZE + 1); |
| + return *this; |
| + } |
| + |
| + const_iterator& operator--() { |
| + index_ = (index_ + MAX_SIZE) % (MAX_SIZE + 1); |
| + return *this; |
| + } |
| + |
| + private: |
| + size_t index_; |
| + const T* elements_; |
| + }; |
| + |
| + RingBuffer() : begin_(0), end_(0) {} |
| + |
| + bool empty() const { return begin_ == end_; } |
| + size_t size() const { |
| + return (end_ - begin_ + MAX_SIZE + 1) % (MAX_SIZE + 1); |
| + } |
| + const_iterator begin() const { return const_iterator(begin_, elements_); } |
| + const_iterator end() const { return const_iterator(end_, elements_); } |
| + const_iterator back() const { return --end(); } |
| + void push_back(const T& element) { |
| + elements_[end_] = element; |
| + end_ = (end_ + 1) % (MAX_SIZE + 1); |
| + if (end_ == begin_) |
| + begin_ = (begin_ + 1) % (MAX_SIZE + 1); |
| + } |
| + void push_front(const T& element) { |
| + begin_ = (begin_ + MAX_SIZE) % (MAX_SIZE + 1); |
| + if (begin_ == end_) |
| + end_ = (end_ + MAX_SIZE) % (MAX_SIZE + 1); |
| + elements_[begin_] = element; |
| + } |
| + |
| + private: |
| + T elements_[MAX_SIZE + 1]; |
| + size_t begin_; |
| + size_t end_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(RingBuffer); |
| +}; |
| + |
| + |
| +// GCTracer collects and prints ONE line after each garbage collector |
| +// invocation IFF --trace_gc is used. |
| + |
|
Hannes Payer (out of office)
2014/07/24 09:03:33
remove newline
ernstm
2014/07/24 11:49:49
Done.
|
| +// TODO(ernstm): Unit tests. |
| +class GCTracer BASE_EMBEDDED { |
| + public: |
| + class Scope BASE_EMBEDDED { |
| + public: |
| + enum ScopeId { |
| + EXTERNAL, |
| + MC_MARK, |
| + MC_SWEEP, |
| + MC_SWEEP_NEWSPACE, |
| + MC_SWEEP_OLDSPACE, |
| + MC_SWEEP_CODE, |
| + MC_SWEEP_CELL, |
| + MC_SWEEP_MAP, |
| + MC_EVACUATE_PAGES, |
| + MC_UPDATE_NEW_TO_NEW_POINTERS, |
| + MC_UPDATE_ROOT_TO_NEW_POINTERS, |
| + MC_UPDATE_OLD_TO_NEW_POINTERS, |
| + MC_UPDATE_POINTERS_TO_EVACUATED, |
| + MC_UPDATE_POINTERS_BETWEEN_EVACUATED, |
| + MC_UPDATE_MISC_POINTERS, |
| + MC_WEAKCOLLECTION_PROCESS, |
| + MC_WEAKCOLLECTION_CLEAR, |
| + MC_FLUSH_CODE, |
| + NUMBER_OF_SCOPES |
| + }; |
| + |
| + Scope(GCTracer* tracer, ScopeId scope) |
| + : tracer_(tracer), |
| + scope_(scope) { |
| + start_time_ = base::OS::TimeCurrentMillis(); |
| + } |
| + |
| + ~Scope() { |
| + ASSERT(scope_ < NUMBER_OF_SCOPES); // scope_ is unsigned. |
| + tracer_->current_.scopes[scope_] += |
| + base::OS::TimeCurrentMillis() - start_time_; |
| + } |
| + |
| + private: |
| + GCTracer* tracer_; |
| + ScopeId scope_; |
| + double start_time_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Scope); |
| + }; |
| + |
| + |
| + class Event { |
| + public: |
| + enum Type { |
| + SCAVENGER = 0, |
| + MARK_COMPACTOR = 1, |
| + START = 2 |
| + }; |
| + |
| + // Default constructor leaves the event uninitialized. |
| + Event() {} |
| + |
| + Event(Type type, |
| + const char* gc_reason, |
| + const char* collector_reason); |
| + |
| + // Returns a string describing the event type. |
| + const char* TypeName(bool short_name) const; |
| + |
| + // Type of event |
| + Type type; |
| + |
| + const char* gc_reason; |
| + const char* collector_reason; |
| + |
| + // Timestamp set in the constructor. |
| + double start_time; |
| + |
| + // Timestamp set in the destructor. |
| + double end_time; |
| + |
| + // Size of objects in heap set in constructor. |
| + intptr_t start_object_size; |
| + |
| + // Size of objects in heap set in destructor. |
| + intptr_t end_object_size; |
| + |
| + // Size of memory allocated from OS set in constructor. |
| + intptr_t start_memory_size; |
| + |
| + // Size of memory allocated from OS set in destructor. |
| + intptr_t end_memory_size; |
| + |
| + // Total amount of space either wasted or contained in one of free lists |
| + // before the current GC. |
| + intptr_t start_holes_size; |
| + |
| + // Total amount of space either wasted or contained in one of free lists |
| + // after the current GC. |
| + intptr_t end_holes_size; |
| + |
| + // Number of incremental marking steps since creation of tracer. |
| + // (value at start of event) |
| + int incremental_marking_steps; |
| + |
| + // Cumulative duration of incremental marking steps since creation of |
| + // tracer. (value at start of event) |
| + double incremental_marking_duration; |
| + |
| + // Longest incremental marking step since start of marking. |
| + // (value at start of event) |
| + double longest_incremental_marking_step; |
| + |
| + // Amounts of time spent in different scopes during GC. |
| + double scopes[Scope::NUMBER_OF_SCOPES]; |
| + }; |
| + |
| + static const int kRingBufferMaxSize = 10; |
| + |
| + typedef RingBuffer<Event, kRingBufferMaxSize> EventBuffer; |
| + |
| + explicit GCTracer(Heap* heap); |
| + |
| + // Start collecting data. |
| + void Start(GarbageCollector collector, |
| + const char* gc_reason, |
| + const char* collector_reason); |
| + |
| + // Stop collecting data and print results. |
| + void Stop(); |
| + |
| + // Log an incremental marking step. |
| + void AddIncrementalMarkingStep(double duration); |
| + |
| + private: |
| + // Print one detailed trace line in name=value format. |
| + // TODO(ernstm): Move to Heap. |
| + void PrintNVP() const; |
| + |
| + // Print one trace line. |
| + // TODO(ernstm): Move to Heap. |
| + void Print() const; |
| + |
| + // Pointer to the heap that owns this tracer. |
| + Heap* heap_; |
| + |
| + // Current tracer event. Populated during Start/Stop cycle. Valid after Stop() |
| + // has returned. |
| + Event current_; |
| + |
| + // Previous tracer event. |
| + Event previous_; |
| + |
| + // Previous MARK_COMPACTOR event. |
| + Event previous_mark_compactor_event_; |
| + |
| + // RingBuffers for SCAVENGER events. |
| + EventBuffer scavenger_events_; |
| + |
| + // RingBuffers for MARK_COMPACTOR events. |
| + EventBuffer mark_compactor_events_; |
| + |
| + // Cumulative number of incremental marking steps since creation of tracer. |
| + int incremental_marking_steps_; |
| + |
| + // Cumulative duration of incremental marking steps since creation of tracer. |
| + double incremental_marking_duration_; |
| + |
| + // Longest incremental marking step since start of marking. |
| + double longest_incremental_marking_step_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(GCTracer); |
| +}; |
| + |
| +} } // namespace v8::internal |
| + |
| +#endif // V8_GC_TRACER_H_ |