| Index: runtime/vm/timeline.h
|
| diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d248c40950298f75d529c6dd8b50e2e5ccb3cfb2
|
| --- /dev/null
|
| +++ b/runtime/vm/timeline.h
|
| @@ -0,0 +1,276 @@
|
| +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +#ifndef VM_TIMELINE_H_
|
| +#define VM_TIMELINE_H_
|
| +
|
| +#include "vm/bitfield.h"
|
| +
|
| +namespace dart {
|
| +
|
| +class JSONStream;
|
| +class Object;
|
| +class RawArray;
|
| +class Thread;
|
| +class TimelineEvent;
|
| +class TimelineEventBuffer;
|
| +class TimelineStream;
|
| +
|
| +class TimelineEvent {
|
| + public:
|
| + // Keep in sync with StateBits below.
|
| + enum EventType {
|
| + kNone,
|
| + kDuration,
|
| + kInstant,
|
| + kAsyncBegin,
|
| + kAsyncInstant,
|
| + kAsyncEnd,
|
| + kNumEventTypes,
|
| + };
|
| +
|
| + TimelineEvent();
|
| + ~TimelineEvent();
|
| +
|
| + void Reset();
|
| +
|
| + bool IsValid() const {
|
| + return (event_type() > kNone) && (event_type() < kNumEventTypes);
|
| + }
|
| +
|
| + // Marks the beginning of an asynchronous operation.
|
| + // Returns |async_id| which must be passed to |AsyncInstant| and |AsyncEnd|.
|
| + int64_t AsyncBegin(TimelineStream* stream, const char* label);
|
| + // Marks an instantaneous event associated with |async_id|.
|
| + void AsyncInstant(TimelineStream* stream,
|
| + const char* label,
|
| + int64_t async_id);
|
| + // Marks the end of an asynchronous operation associated with |async_id|.
|
| + void AsyncEnd(TimelineStream* stream,
|
| + const char* label,
|
| + int64_t async_id);
|
| +
|
| + void DurationBegin(TimelineStream* stream, const char* label);
|
| + void DurationEnd();
|
| + void Instant(TimelineStream* stream, const char* label);
|
| +
|
| + void Duration(TimelineStream* stream,
|
| + const char* label,
|
| + int64_t start_micros,
|
| + int64_t end_micros);
|
| +
|
| + // Set the number of arguments in the event.
|
| + void SetNumArguments(intptr_t length);
|
| + // |name| must be a compile time constant. Takes ownership of |argumentp|.
|
| + void SetArgument(intptr_t i, const char* name, char* argument);
|
| + // |name| must be a compile time constant. Copies |argument|.
|
| + void CopyArgument(intptr_t i, const char* name, const char* argument);
|
| + // |name| must be a compile time constant.
|
| + void FormatArgument(intptr_t i,
|
| + const char* name,
|
| + const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5);
|
| + EventType event_type() const {
|
| + return EventTypeField::decode(state_);
|
| + }
|
| +
|
| + int64_t TimeOrigin() const;
|
| + int64_t AsyncId() const;
|
| + int64_t TimeDuration() const;
|
| +
|
| + void PrintJSON(JSONStream* stream) const;
|
| +
|
| + private:
|
| + struct TimelineEventArgument {
|
| + const char* name;
|
| + char* value;
|
| + };
|
| +
|
| + int64_t timestamp0_;
|
| + int64_t timestamp1_;
|
| + TimelineEventArgument* arguments_;
|
| + intptr_t arguments_length_;
|
| + uword state_;
|
| + const char* label_;
|
| + TimelineStream* stream_;
|
| + Thread* thread_;
|
| +
|
| + void FreeArguments();
|
| +
|
| + void Init(EventType event_type, TimelineStream* stream, const char* label);
|
| +
|
| + void set_event_type(EventType event_type) {
|
| + state_ = EventTypeField::update(event_type, state_);
|
| + }
|
| +
|
| + enum StateBits {
|
| + kEventTypeBit = 0,
|
| + // reserve 4 bits for type.
|
| + kNextBit = 4,
|
| + };
|
| +
|
| + class EventTypeField : public BitField<EventType, kEventTypeBit, 4> {};
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TimelineEvent);
|
| +};
|
| +
|
| +
|
| +// A stream of timeline events. A stream has a name and can be enabled or
|
| +// disabled.
|
| +class TimelineStream {
|
| + public:
|
| + TimelineStream();
|
| +
|
| + void Init(const char* name, bool enabled);
|
| +
|
| + const char* name() const {
|
| + return name_;
|
| + }
|
| +
|
| + bool enabled() const {
|
| + return enabled_;
|
| + }
|
| +
|
| + void set_enabled(bool enabled) {
|
| + enabled_ = enabled;
|
| + }
|
| +
|
| + TimelineEventBuffer* buffer() const {
|
| + return buffer_;
|
| + }
|
| +
|
| + void set_buffer(TimelineEventBuffer* buffer) {
|
| + buffer_ = buffer;
|
| + }
|
| +
|
| + // Records an event. Will return |NULL| if not enabled. The returned
|
| + // |TimelineEvent| is in an undefined state and must be initialized.
|
| + // |obj| is associated with the returned |TimelineEvent|.
|
| + TimelineEvent* RecordEvent(const Object& obj);
|
| +
|
| + // Records an event. Will return |NULL| if not enabled. The returned
|
| + // |TimelineEvent| is in an undefined state and must be initialized.
|
| + TimelineEvent* RecordEvent();
|
| +
|
| + int64_t GetNextSeq();
|
| +
|
| + private:
|
| + // Buffer of TimelineEvents.
|
| + TimelineEventBuffer* buffer_;
|
| + const char* name_;
|
| + bool enabled_;
|
| + int64_t seq_;
|
| +};
|
| +
|
| +
|
| +// (name, enabled by default).
|
| +#define ISOLATE_TIMELINE_STREAM_LIST(V) \
|
| + V(API, false) \
|
| + V(Compiler, false) \
|
| + V(Embedder, false) \
|
| + V(GC, false) \
|
| + V(Isolate, false) \
|
| +
|
| +
|
| +#define TIMELINE_FUNCTION_COMPILATION_DURATION(isolate, suffix, function) \
|
| + TimelineDurationScope tds(isolate, \
|
| + isolate->GetCompilerStream(), \
|
| + "Compile"#suffix); \
|
| + if (tds.enabled()) { \
|
| + tds.SetNumArguments(1); \
|
| + tds.CopyArgument( \
|
| + 0, \
|
| + "function", \
|
| + const_cast<char*>(function.QualifiedUserVisibleNameCString())); \
|
| + }
|
| +
|
| +class TimelineDurationScope : public StackResource {
|
| + public:
|
| + TimelineDurationScope(Isolate* isolate,
|
| + TimelineStream* stream,
|
| + const char* label)
|
| + : StackResource(isolate) {
|
| + event_ = stream->RecordEvent();
|
| + if (event_ == NULL) {
|
| + return;
|
| + }
|
| + event_->DurationBegin(stream, label);
|
| + }
|
| +
|
| + bool enabled() const {
|
| + return event_ != NULL;
|
| + }
|
| +
|
| + void SetNumArguments(intptr_t length) {
|
| + if (event_ == NULL) {
|
| + return;
|
| + }
|
| + event_->SetNumArguments(length);
|
| + }
|
| +
|
| + void SetArgument(intptr_t i, const char* name, char* argument) {
|
| + if (event_ == NULL) {
|
| + return;
|
| + }
|
| + event_->SetArgument(i, name, argument);
|
| + }
|
| +
|
| + void CopyArgument(intptr_t i, const char* name, const char* argument) {
|
| + if (event_ == NULL) {
|
| + return;
|
| + }
|
| + event_->CopyArgument(i, name, argument);
|
| + }
|
| +
|
| + void FormatArgument(intptr_t i,
|
| + const char* name,
|
| + const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5);
|
| +
|
| + ~TimelineDurationScope() {
|
| + if (event_ == NULL) {
|
| + return;
|
| + }
|
| + event_->DurationEnd();
|
| + }
|
| +
|
| + private:
|
| + TimelineEvent* event_;
|
| +};
|
| +
|
| +
|
| +class TimelineEventBuffer {
|
| + public:
|
| + static const intptr_t kDefaultCapacity = 8192;
|
| +
|
| + static intptr_t SizeForCapacity(intptr_t capacity);
|
| +
|
| + explicit TimelineEventBuffer(intptr_t capacity = kDefaultCapacity);
|
| + ~TimelineEventBuffer();
|
| +
|
| + void PrintJSON(JSONStream* js) const;
|
| +
|
| + void WriteTo(const char* directory);
|
| +
|
| + private:
|
| + // events_[i] and event_objects_[i] are indexed together.
|
| + TimelineEvent* events_;
|
| + RawArray* event_objects_;
|
| + uintptr_t cursor_;
|
| + intptr_t capacity_;
|
| +
|
| + void PrintJSONMeta(JSONArray* array) const;
|
| + void PrintJSONEvents(JSONArray* array) const;
|
| +
|
| + intptr_t GetNextIndex();
|
| + void VisitObjectPointers(ObjectPointerVisitor* visitor);
|
| + TimelineEvent* RecordEvent(const Object& obj);
|
| + TimelineEvent* RecordEvent();
|
| +
|
| + friend class TimelineStream;
|
| + friend class Isolate;
|
| + DISALLOW_COPY_AND_ASSIGN(TimelineEventBuffer);
|
| +};
|
| +
|
| +} // namespace dart
|
| +
|
| +#endif // VM_TIMELINE_H_
|
|
|