| 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 #ifndef VM_TIMELINE_H_ | 5 #ifndef VM_TIMELINE_H_ |
| 6 #define VM_TIMELINE_H_ | 6 #define VM_TIMELINE_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/bitfield.h" | 9 #include "vm/bitfield.h" |
| 10 #include "vm/os.h" |
| 10 | 11 |
| 11 namespace dart { | 12 namespace dart { |
| 12 | 13 |
| 13 class JSONArray; | 14 class JSONArray; |
| 14 class JSONObject; | 15 class JSONObject; |
| 15 class JSONStream; | 16 class JSONStream; |
| 16 class Object; | 17 class Object; |
| 17 class ObjectPointerVisitor; | 18 class ObjectPointerVisitor; |
| 18 class Isolate; | 19 class Isolate; |
| 19 class RawArray; | 20 class RawArray; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 #define ISOLATE_TIMELINE_STREAM_DECLARE_FLAG(name, not_used) \ | 75 #define ISOLATE_TIMELINE_STREAM_DECLARE_FLAG(name, not_used) \ |
| 75 static bool stream_##name##_enabled_; | 76 static bool stream_##name##_enabled_; |
| 76 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DECLARE_FLAG) | 77 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DECLARE_FLAG) |
| 77 #undef ISOLATE_TIMELINE_STREAM_DECLARE_FLAG | 78 #undef ISOLATE_TIMELINE_STREAM_DECLARE_FLAG |
| 78 | 79 |
| 79 friend class TimelineRecorderOverride; | 80 friend class TimelineRecorderOverride; |
| 80 friend class ReclaimBlocksIsolateVisitor; | 81 friend class ReclaimBlocksIsolateVisitor; |
| 81 }; | 82 }; |
| 82 | 83 |
| 83 | 84 |
| 85 struct TimelineEventArgument { |
| 86 const char* name; |
| 87 char* value; |
| 88 }; |
| 89 |
| 90 |
| 84 // You should get a |TimelineEvent| from a |TimelineStream|. | 91 // You should get a |TimelineEvent| from a |TimelineStream|. |
| 85 class TimelineEvent { | 92 class TimelineEvent { |
| 86 public: | 93 public: |
| 87 // Keep in sync with StateBits below. | 94 // Keep in sync with StateBits below. |
| 88 enum EventType { | 95 enum EventType { |
| 89 kNone, | 96 kNone, |
| 90 kBegin, | 97 kBegin, |
| 91 kEnd, | 98 kEnd, |
| 92 kDuration, | 99 kDuration, |
| 93 kInstant, | 100 kInstant, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 117 | 124 |
| 118 void DurationBegin(const char* label); | 125 void DurationBegin(const char* label); |
| 119 void DurationEnd(); | 126 void DurationEnd(); |
| 120 void Instant(const char* label); | 127 void Instant(const char* label); |
| 121 | 128 |
| 122 void Duration(const char* label, | 129 void Duration(const char* label, |
| 123 int64_t start_micros, | 130 int64_t start_micros, |
| 124 int64_t end_micros); | 131 int64_t end_micros); |
| 125 | 132 |
| 126 void Begin(const char* label, | 133 void Begin(const char* label, |
| 127 int64_t micros); | 134 int64_t micros = OS::GetCurrentTraceMicros()); |
| 128 | 135 |
| 129 void End(const char* label, | 136 void End(const char* label, |
| 130 int64_t micros); | 137 int64_t micros = OS::GetCurrentTraceMicros()); |
| 131 | 138 |
| 132 // Set the number of arguments in the event. | 139 // Set the number of arguments in the event. |
| 133 void SetNumArguments(intptr_t length); | 140 void SetNumArguments(intptr_t length); |
| 134 // |name| must be a compile time constant. Takes ownership of |argumentp|. | 141 // |name| must be a compile time constant. Takes ownership of |argumentp|. |
| 135 void SetArgument(intptr_t i, const char* name, char* argument); | 142 void SetArgument(intptr_t i, const char* name, char* argument); |
| 136 // |name| must be a compile time constant. Copies |argument|. | 143 // |name| must be a compile time constant. Copies |argument|. |
| 137 void CopyArgument(intptr_t i, const char* name, const char* argument); | 144 void CopyArgument(intptr_t i, const char* name, const char* argument); |
| 138 // |name| must be a compile time constant. | 145 // |name| must be a compile time constant. |
| 139 void FormatArgument(intptr_t i, | 146 void FormatArgument(intptr_t i, |
| 140 const char* name, | 147 const char* name, |
| 141 const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5); | 148 const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5); |
| 142 | 149 |
| 150 void StealArguments(intptr_t arguments_length, |
| 151 TimelineEventArgument* arguments); |
| 143 // Mandatory to call when this event is completely filled out. | 152 // Mandatory to call when this event is completely filled out. |
| 144 void Complete(); | 153 void Complete(); |
| 145 | 154 |
| 146 EventType event_type() const { | 155 EventType event_type() const { |
| 147 return EventTypeField::decode(state_); | 156 return EventTypeField::decode(state_); |
| 148 } | 157 } |
| 149 | 158 |
| 150 bool IsFinishedDuration() const { | 159 bool IsFinishedDuration() const { |
| 151 return (event_type() == kDuration) && (timestamp1_ > timestamp0_); | 160 return (event_type() == kDuration) && (timestamp1_ > timestamp0_); |
| 152 } | 161 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 return false; | 223 return false; |
| 215 } | 224 } |
| 216 if (other->TimeEnd() > TimeEnd()) { | 225 if (other->TimeEnd() > TimeEnd()) { |
| 217 return false; | 226 return false; |
| 218 } | 227 } |
| 219 return true; | 228 return true; |
| 220 } | 229 } |
| 221 } | 230 } |
| 222 | 231 |
| 223 private: | 232 private: |
| 224 struct TimelineEventArgument { | |
| 225 const char* name; | |
| 226 char* value; | |
| 227 }; | |
| 228 | |
| 229 int64_t timestamp0_; | 233 int64_t timestamp0_; |
| 230 int64_t timestamp1_; | 234 int64_t timestamp1_; |
| 231 TimelineEventArgument* arguments_; | 235 TimelineEventArgument* arguments_; |
| 232 intptr_t arguments_length_; | 236 intptr_t arguments_length_; |
| 233 uword state_; | 237 uword state_; |
| 234 const char* label_; | 238 const char* label_; |
| 235 const char* category_; | 239 const char* category_; |
| 236 ThreadId thread_; | 240 ThreadId thread_; |
| 237 Isolate* isolate_; | 241 Isolate* isolate_; |
| 238 | 242 |
| 239 void FreeArguments(); | 243 void FreeArguments(); |
| 240 | 244 |
| 241 void StreamInit(TimelineStream* stream); | 245 void StreamInit(TimelineStream* stream); |
| 242 void Init(EventType event_type, const char* label); | 246 void Init(EventType event_type, const char* label); |
| 243 | 247 |
| 244 void set_event_type(EventType event_type) { | 248 void set_event_type(EventType event_type) { |
| 245 // We only reserve 4 bits to hold the event type. | 249 // We only reserve 4 bits to hold the event type. |
| 246 COMPILE_ASSERT(kNumEventTypes < 16); | 250 COMPILE_ASSERT(kNumEventTypes < 16); |
| 247 state_ = EventTypeField::update(event_type, state_); | 251 state_ = EventTypeField::update(event_type, state_); |
| 248 } | 252 } |
| 249 | 253 |
| 254 void set_global_block(bool global_block) { |
| 255 state_ = GlobalBlockField::update(global_block, state_); |
| 256 } |
| 257 |
| 258 bool global_block() const { |
| 259 return GlobalBlockField::decode(state_); |
| 260 } |
| 261 |
| 250 enum StateBits { | 262 enum StateBits { |
| 251 kEventTypeBit = 0, | 263 kEventTypeBit = 0, // reserve 4 bits for type. |
| 252 // reserve 4 bits for type. | 264 // Was this event allocated from the global block? |
| 253 kNextBit = 4, | 265 kGlobalBlockBit = 4, |
| 266 kNextBit = 5, |
| 254 }; | 267 }; |
| 255 | 268 |
| 256 class EventTypeField : public BitField<EventType, kEventTypeBit, 4> {}; | 269 class EventTypeField : public BitField<EventType, kEventTypeBit, 4> {}; |
| 270 class GlobalBlockField : public BitField<bool, kGlobalBlockBit, 1> {}; |
| 257 | 271 |
| 272 friend class TimelineEventRecorder; |
| 273 friend class TimelineEventEndlessRecorder; |
| 274 friend class TimelineEventRingRecorder; |
| 275 friend class TimelineStream; |
| 258 friend class TimelineTestHelper; | 276 friend class TimelineTestHelper; |
| 259 friend class TimelineStream; | |
| 260 DISALLOW_COPY_AND_ASSIGN(TimelineEvent); | 277 DISALLOW_COPY_AND_ASSIGN(TimelineEvent); |
| 261 }; | 278 }; |
| 262 | 279 |
| 263 | 280 |
| 264 // A stream of timeline events. A stream has a name and can be enabled or | 281 // A stream of timeline events. A stream has a name and can be enabled or |
| 265 // disabled (globally and per isolate). | 282 // disabled (globally and per isolate). |
| 266 class TimelineStream { | 283 class TimelineStream { |
| 267 public: | 284 public: |
| 268 TimelineStream(); | 285 TimelineStream(); |
| 269 | 286 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 283 bool enabled() const { | 300 bool enabled() const { |
| 284 return enabled_; | 301 return enabled_; |
| 285 } | 302 } |
| 286 | 303 |
| 287 void set_enabled(bool enabled) { | 304 void set_enabled(bool enabled) { |
| 288 enabled_ = enabled; | 305 enabled_ = enabled; |
| 289 } | 306 } |
| 290 | 307 |
| 291 // Records an event. Will return |NULL| if not enabled. The returned | 308 // Records an event. Will return |NULL| if not enabled. The returned |
| 292 // |TimelineEvent| is in an undefined state and must be initialized. | 309 // |TimelineEvent| is in an undefined state and must be initialized. |
| 310 // NOTE: It is not allowed to call StartEvent again without completing |
| 311 // the first event. |
| 293 TimelineEvent* StartEvent(); | 312 TimelineEvent* StartEvent(); |
| 294 | 313 |
| 295 private: | 314 private: |
| 296 const char* name_; | 315 const char* name_; |
| 297 bool enabled_; | 316 bool enabled_; |
| 298 const bool* globally_enabled_; | 317 const bool* globally_enabled_; |
| 299 }; | 318 }; |
| 300 | 319 |
| 301 #define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, suffix, function) \ | 320 #define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, suffix, function) \ |
| 302 TimelineDurationScope tds(thread, \ | 321 TimelineDurationScope tds(thread, \ |
| 303 thread->isolate()->GetCompilerStream(), \ | 322 thread->isolate()->GetCompilerStream(), \ |
| 304 "Compile" suffix); \ | 323 "Compile" suffix); \ |
| 305 if (tds.enabled()) { \ | 324 if (tds.enabled()) { \ |
| 306 tds.SetNumArguments(1); \ | 325 tds.SetNumArguments(1); \ |
| 307 tds.CopyArgument( \ | 326 tds.CopyArgument( \ |
| 308 0, \ | 327 0, \ |
| 309 "function", \ | 328 "function", \ |
| 310 const_cast<char*>(function.ToLibNamePrefixedQualifiedCString())); \ | 329 const_cast<char*>(function.ToLibNamePrefixedQualifiedCString())); \ |
| 311 } | 330 } |
| 312 | 331 |
| 313 | 332 |
| 314 // TODO(johnmccutchan): TimelineDurationScope should only allocate the | |
| 315 // event when complete. | |
| 316 class TimelineDurationScope : public StackResource { | 333 class TimelineDurationScope : public StackResource { |
| 317 public: | 334 public: |
| 318 TimelineDurationScope(Isolate* isolate, | 335 TimelineDurationScope(TimelineStream* stream, |
| 319 TimelineStream* stream, | 336 const char* label); |
| 320 const char* label) | |
| 321 : StackResource(isolate) { | |
| 322 Init(stream, label); | |
| 323 } | |
| 324 | 337 |
| 325 TimelineDurationScope(Thread* thread, | 338 TimelineDurationScope(Thread* thread, |
| 326 TimelineStream* stream, | 339 TimelineStream* stream, |
| 327 const char* label) | 340 const char* label); |
| 328 : StackResource(thread) { | 341 |
| 329 Init(stream, label); | 342 ~TimelineDurationScope(); |
| 343 |
| 344 bool enabled() const { |
| 345 return enabled_; |
| 330 } | 346 } |
| 331 | 347 |
| 332 TimelineDurationScope(TimelineStream* stream, | 348 void SetNumArguments(intptr_t length); |
| 333 const char* label) | |
| 334 : StackResource(reinterpret_cast<Thread*>(NULL)) { | |
| 335 Init(stream, label); | |
| 336 } | |
| 337 | 349 |
| 338 void Init(TimelineStream* stream, const char* label) { | 350 void SetArgument(intptr_t i, const char* name, char* argument); |
| 339 event_ = stream->StartEvent(); | |
| 340 if (event_ == NULL) { | |
| 341 return; | |
| 342 } | |
| 343 event_->DurationBegin(label); | |
| 344 } | |
| 345 | 351 |
| 346 bool enabled() const { | 352 void CopyArgument(intptr_t i, const char* name, const char* argument); |
| 347 return event_ != NULL; | |
| 348 } | |
| 349 | |
| 350 void SetNumArguments(intptr_t length) { | |
| 351 if (event_ == NULL) { | |
| 352 return; | |
| 353 } | |
| 354 event_->SetNumArguments(length); | |
| 355 } | |
| 356 | |
| 357 void SetArgument(intptr_t i, const char* name, char* argument) { | |
| 358 if (event_ == NULL) { | |
| 359 return; | |
| 360 } | |
| 361 event_->SetArgument(i, name, argument); | |
| 362 } | |
| 363 | |
| 364 void CopyArgument(intptr_t i, const char* name, const char* argument) { | |
| 365 if (event_ == NULL) { | |
| 366 return; | |
| 367 } | |
| 368 event_->CopyArgument(i, name, argument); | |
| 369 } | |
| 370 | 353 |
| 371 void FormatArgument(intptr_t i, | 354 void FormatArgument(intptr_t i, |
| 372 const char* name, | 355 const char* name, |
| 373 const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5); | 356 const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5); |
| 374 | 357 |
| 375 ~TimelineDurationScope() { | 358 private: |
| 376 if (event_ == NULL) { | 359 void Init(); |
| 377 return; | 360 void FreeArguments(); |
| 378 } | |
| 379 event_->DurationEnd(); | |
| 380 event_->Complete(); | |
| 381 } | |
| 382 | 361 |
| 383 private: | 362 int64_t timestamp_; |
| 384 TimelineEvent* event_; | 363 TimelineStream* stream_; |
| 364 const char* label_; |
| 365 TimelineEventArgument* arguments_; |
| 366 intptr_t arguments_length_; |
| 367 bool enabled_; |
| 368 |
| 369 DISALLOW_COPY_AND_ASSIGN(TimelineDurationScope); |
| 385 }; | 370 }; |
| 386 | 371 |
| 387 | 372 |
| 388 // A block of |TimelineEvent|s. Not thread safe. | 373 // A block of |TimelineEvent|s. Not thread safe. |
| 389 class TimelineEventBlock { | 374 class TimelineEventBlock { |
| 390 public: | 375 public: |
| 391 static const intptr_t kBlockSize = 64; | 376 static const intptr_t kBlockSize = 64; |
| 392 | 377 |
| 393 explicit TimelineEventBlock(intptr_t index); | 378 explicit TimelineEventBlock(intptr_t index); |
| 394 ~TimelineEventBlock(); | 379 ~TimelineEventBlock(); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 virtual void CompleteEvent(TimelineEvent* event) = 0; | 565 virtual void CompleteEvent(TimelineEvent* event) = 0; |
| 581 virtual TimelineEventBlock* GetHeadBlockLocked() = 0; | 566 virtual TimelineEventBlock* GetHeadBlockLocked() = 0; |
| 582 virtual TimelineEventBlock* GetNewBlockLocked(Isolate* isolate) = 0; | 567 virtual TimelineEventBlock* GetNewBlockLocked(Isolate* isolate) = 0; |
| 583 virtual intptr_t NumDartEventsLocked() = 0; | 568 virtual intptr_t NumDartEventsLocked() = 0; |
| 584 virtual DartTimelineEvent* DartEventAtLocked(intptr_t i) = 0; | 569 virtual DartTimelineEvent* DartEventAtLocked(intptr_t i) = 0; |
| 585 | 570 |
| 586 // Utility method(s). | 571 // Utility method(s). |
| 587 void PrintJSONMeta(JSONArray* array) const; | 572 void PrintJSONMeta(JSONArray* array) const; |
| 588 TimelineEvent* ThreadBlockStartEvent(); | 573 TimelineEvent* ThreadBlockStartEvent(); |
| 589 TimelineEvent* GlobalBlockStartEvent(); | 574 TimelineEvent* GlobalBlockStartEvent(); |
| 575 void ThreadBlockCompleteEvent(TimelineEvent* event); |
| 576 void GlobalBlockCompleteEvent(TimelineEvent* event); |
| 590 | 577 |
| 591 Mutex lock_; | 578 Mutex lock_; |
| 592 // Only accessed under |lock_|. | 579 // Only accessed under |lock_|. |
| 593 TimelineEventBlock* global_block_; | 580 TimelineEventBlock* global_block_; |
| 594 void ReclaimGlobalBlock(); | 581 void ReclaimGlobalBlock(); |
| 595 | 582 |
| 596 uintptr_t async_id_; | 583 uintptr_t async_id_; |
| 597 | 584 |
| 598 friend class DartTimelineEventIterator; | 585 friend class DartTimelineEventIterator; |
| 599 friend class TimelineEvent; | 586 friend class TimelineEvent; |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 | 737 |
| 751 private: | 738 private: |
| 752 intptr_t cursor_; | 739 intptr_t cursor_; |
| 753 intptr_t num_events_; | 740 intptr_t num_events_; |
| 754 TimelineEventRecorder* recorder_; | 741 TimelineEventRecorder* recorder_; |
| 755 }; | 742 }; |
| 756 | 743 |
| 757 } // namespace dart | 744 } // namespace dart |
| 758 | 745 |
| 759 #endif // VM_TIMELINE_H_ | 746 #endif // VM_TIMELINE_H_ |
| OLD | NEW |