| 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 RUNTIME_VM_TIMELINE_H_ | 5 #ifndef RUNTIME_VM_TIMELINE_H_ |
| 6 #define RUNTIME_VM_TIMELINE_H_ | 6 #define RUNTIME_VM_TIMELINE_H_ |
| 7 | 7 |
| 8 #include "include/dart_tools_api.h" | 8 #include "include/dart_tools_api.h" |
| 9 | 9 |
| 10 #include "vm/allocation.h" | 10 #include "vm/allocation.h" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 V(GC, false) \ | 37 V(GC, false) \ |
| 38 V(Isolate, false) \ | 38 V(Isolate, false) \ |
| 39 V(VM, false) | 39 V(VM, false) |
| 40 | 40 |
| 41 // A stream of timeline events. A stream has a name and can be enabled or | 41 // A stream of timeline events. A stream has a name and can be enabled or |
| 42 // disabled (globally and per isolate). | 42 // disabled (globally and per isolate). |
| 43 class TimelineStream { | 43 class TimelineStream { |
| 44 public: | 44 public: |
| 45 TimelineStream(); | 45 TimelineStream(); |
| 46 | 46 |
| 47 void Init(const char* name, | 47 void Init(const char* name, bool enabled); |
| 48 bool enabled); | |
| 49 | 48 |
| 50 const char* name() const { | 49 const char* name() const { return name_; } |
| 51 return name_; | |
| 52 } | |
| 53 | 50 |
| 54 bool enabled() const { | 51 bool enabled() const { return enabled_ != 0; } |
| 55 return enabled_ != 0; | |
| 56 } | |
| 57 | 52 |
| 58 void set_enabled(bool enabled) { | 53 void set_enabled(bool enabled) { enabled_ = enabled ? 1 : 0; } |
| 59 enabled_ = enabled ? 1 : 0; | |
| 60 } | |
| 61 | 54 |
| 62 // Records an event. Will return |NULL| if not enabled. The returned | 55 // Records an event. Will return |NULL| if not enabled. The returned |
| 63 // |TimelineEvent| is in an undefined state and must be initialized. | 56 // |TimelineEvent| is in an undefined state and must be initialized. |
| 64 // NOTE: It is not allowed to call StartEvent again without completing | 57 // NOTE: It is not allowed to call StartEvent again without completing |
| 65 // the first event. | 58 // the first event. |
| 66 TimelineEvent* StartEvent(); | 59 TimelineEvent* StartEvent(); |
| 67 | 60 |
| 68 static intptr_t enabled_offset() { | 61 static intptr_t enabled_offset() { |
| 69 return OFFSET_OF(TimelineStream, enabled_); | 62 return OFFSET_OF(TimelineStream, enabled_); |
| 70 } | 63 } |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 // Completes this event with pre-serialized JSON. Copies |json|. | 216 // Completes this event with pre-serialized JSON. Copies |json|. |
| 224 void CompleteWithPreSerializedJSON(const char* json); | 217 void CompleteWithPreSerializedJSON(const char* json); |
| 225 | 218 |
| 226 // Set the number of arguments in the event. | 219 // Set the number of arguments in the event. |
| 227 void SetNumArguments(intptr_t length); | 220 void SetNumArguments(intptr_t length); |
| 228 // |name| must be a compile time constant. Takes ownership of |argument|. | 221 // |name| must be a compile time constant. Takes ownership of |argument|. |
| 229 void SetArgument(intptr_t i, const char* name, char* argument); | 222 void SetArgument(intptr_t i, const char* name, char* argument); |
| 230 // |name| must be a compile time constant. Copies |argument|. | 223 // |name| must be a compile time constant. Copies |argument|. |
| 231 void CopyArgument(intptr_t i, const char* name, const char* argument); | 224 void CopyArgument(intptr_t i, const char* name, const char* argument); |
| 232 // |name| must be a compile time constant. | 225 // |name| must be a compile time constant. |
| 233 void FormatArgument(intptr_t i, | 226 void FormatArgument(intptr_t i, const char* name, const char* fmt, ...) |
| 234 const char* name, | 227 PRINTF_ATTRIBUTE(4, 5); |
| 235 const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5); | |
| 236 | 228 |
| 237 void StealArguments(intptr_t arguments_length, | 229 void StealArguments(intptr_t arguments_length, |
| 238 TimelineEventArgument* arguments); | 230 TimelineEventArgument* arguments); |
| 239 // Mandatory to call when this event is completely filled out. | 231 // Mandatory to call when this event is completely filled out. |
| 240 void Complete(); | 232 void Complete(); |
| 241 | 233 |
| 242 EventType event_type() const { | 234 EventType event_type() const { return EventTypeField::decode(state_); } |
| 243 return EventTypeField::decode(state_); | |
| 244 } | |
| 245 | 235 |
| 246 bool IsFinishedDuration() const { | 236 bool IsFinishedDuration() const { |
| 247 return (event_type() == kDuration) && (timestamp1_ > timestamp0_); | 237 return (event_type() == kDuration) && (timestamp1_ > timestamp0_); |
| 248 } | 238 } |
| 249 | 239 |
| 250 bool HasThreadCPUTime() const; | 240 bool HasThreadCPUTime() const; |
| 251 int64_t ThreadCPUTimeDuration() const; | 241 int64_t ThreadCPUTimeDuration() const; |
| 252 int64_t ThreadCPUTimeOrigin() const; | 242 int64_t ThreadCPUTimeOrigin() const; |
| 253 | 243 |
| 254 int64_t TimeOrigin() const; | 244 int64_t TimeOrigin() const; |
| 255 int64_t AsyncId() const; | 245 int64_t AsyncId() const; |
| 256 int64_t TimeDuration() const; | 246 int64_t TimeDuration() const; |
| 257 int64_t TimeEnd() const { | 247 int64_t TimeEnd() const { |
| 258 ASSERT(IsFinishedDuration()); | 248 ASSERT(IsFinishedDuration()); |
| 259 return timestamp1_; | 249 return timestamp1_; |
| 260 } | 250 } |
| 261 | 251 |
| 262 // The lowest time value stored in this event. | 252 // The lowest time value stored in this event. |
| 263 int64_t LowTime() const; | 253 int64_t LowTime() const; |
| 264 // The highest time value stored in this event. | 254 // The highest time value stored in this event. |
| 265 int64_t HighTime() const; | 255 int64_t HighTime() const; |
| 266 | 256 |
| 267 void PrintJSON(JSONStream* stream) const; | 257 void PrintJSON(JSONStream* stream) const; |
| 268 | 258 |
| 269 ThreadId thread() const { | 259 ThreadId thread() const { return thread_; } |
| 270 return thread_; | |
| 271 } | |
| 272 | 260 |
| 273 void set_thread(ThreadId tid) { | 261 void set_thread(ThreadId tid) { thread_ = tid; } |
| 274 thread_ = tid; | |
| 275 } | |
| 276 | 262 |
| 277 Dart_Port isolate_id() const { | 263 Dart_Port isolate_id() const { return isolate_id_; } |
| 278 return isolate_id_; | |
| 279 } | |
| 280 | 264 |
| 281 const char* label() const { | 265 const char* label() const { return label_; } |
| 282 return label_; | |
| 283 } | |
| 284 | 266 |
| 285 // Does this duration end before |micros| ? | 267 // Does this duration end before |micros| ? |
| 286 bool DurationFinishedBefore(int64_t micros) const { | 268 bool DurationFinishedBefore(int64_t micros) const { |
| 287 return TimeEnd() <= micros; | 269 return TimeEnd() <= micros; |
| 288 } | 270 } |
| 289 | 271 |
| 290 bool IsDuration() const { | 272 bool IsDuration() const { return (event_type() == kDuration); } |
| 291 return (event_type() == kDuration); | |
| 292 } | |
| 293 | 273 |
| 294 bool IsBegin() const { | 274 bool IsBegin() const { return (event_type() == kBegin); } |
| 295 return (event_type() == kBegin); | |
| 296 } | |
| 297 | 275 |
| 298 bool IsEnd() const { | 276 bool IsEnd() const { return (event_type() == kEnd); } |
| 299 return (event_type() == kEnd); | |
| 300 } | |
| 301 | 277 |
| 302 // Is this event a synchronous begin or end event? | 278 // Is this event a synchronous begin or end event? |
| 303 bool IsBeginOrEnd() const { | 279 bool IsBeginOrEnd() const { return IsBegin() || IsEnd(); } |
| 304 return IsBegin() || IsEnd(); | |
| 305 } | |
| 306 | 280 |
| 307 // Does this duration fully contain |other| ? | 281 // Does this duration fully contain |other| ? |
| 308 bool DurationContains(TimelineEvent* other) const { | 282 bool DurationContains(TimelineEvent* other) const { |
| 309 ASSERT(IsFinishedDuration()); | 283 ASSERT(IsFinishedDuration()); |
| 310 if (other->IsBegin()) { | 284 if (other->IsBegin()) { |
| 311 if (other->TimeOrigin() < TimeOrigin()) { | 285 if (other->TimeOrigin() < TimeOrigin()) { |
| 312 return false; | 286 return false; |
| 313 } | 287 } |
| 314 if (other->TimeOrigin() > TimeEnd()) { | 288 if (other->TimeOrigin() > TimeEnd()) { |
| 315 return false; | 289 return false; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 326 if (other->TimeOrigin() > TimeEnd()) { | 300 if (other->TimeOrigin() > TimeEnd()) { |
| 327 return false; | 301 return false; |
| 328 } | 302 } |
| 329 if (other->TimeEnd() > TimeEnd()) { | 303 if (other->TimeEnd() > TimeEnd()) { |
| 330 return false; | 304 return false; |
| 331 } | 305 } |
| 332 return true; | 306 return true; |
| 333 } | 307 } |
| 334 } | 308 } |
| 335 | 309 |
| 336 bool Within(int64_t time_origin_micros, | 310 bool Within(int64_t time_origin_micros, int64_t time_extent_micros); |
| 337 int64_t time_extent_micros); | |
| 338 | 311 |
| 339 const char* GetSerializedJSON() const; | 312 const char* GetSerializedJSON() const; |
| 340 | 313 |
| 341 void set_owns_label(bool owns_label) { | 314 void set_owns_label(bool owns_label) { |
| 342 state_ = OwnsLabelBit::update(owns_label, state_); | 315 state_ = OwnsLabelBit::update(owns_label, state_); |
| 343 } | 316 } |
| 344 | 317 |
| 345 // Returns the number of bytes written into |buffer|. | 318 // Returns the number of bytes written into |buffer|. |
| 346 intptr_t PrintSystrace(char* buffer, intptr_t buffer_size); | 319 intptr_t PrintSystrace(char* buffer, intptr_t buffer_size); |
| 347 | 320 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 369 void set_thread_timestamp0(int64_t value) { | 342 void set_thread_timestamp0(int64_t value) { |
| 370 ASSERT(thread_timestamp0_ == -1); | 343 ASSERT(thread_timestamp0_ == -1); |
| 371 thread_timestamp0_ = value; | 344 thread_timestamp0_ = value; |
| 372 } | 345 } |
| 373 | 346 |
| 374 void set_thread_timestamp1(int64_t value) { | 347 void set_thread_timestamp1(int64_t value) { |
| 375 ASSERT(thread_timestamp1_ == -1); | 348 ASSERT(thread_timestamp1_ == -1); |
| 376 thread_timestamp1_ = value; | 349 thread_timestamp1_ = value; |
| 377 } | 350 } |
| 378 | 351 |
| 379 bool pre_serialized_json() const { | 352 bool pre_serialized_json() const { return PreSerializedJSON::decode(state_); } |
| 380 return PreSerializedJSON::decode(state_); | |
| 381 } | |
| 382 | 353 |
| 383 void set_pre_serialized_json(bool pre_serialized_json) { | 354 void set_pre_serialized_json(bool pre_serialized_json) { |
| 384 state_ = PreSerializedJSON::update(pre_serialized_json, state_); | 355 state_ = PreSerializedJSON::update(pre_serialized_json, state_); |
| 385 } | 356 } |
| 386 | 357 |
| 387 bool owns_label() const { | 358 bool owns_label() const { return OwnsLabelBit::decode(state_); } |
| 388 return OwnsLabelBit::decode(state_); | |
| 389 } | |
| 390 | 359 |
| 391 enum StateBits { | 360 enum StateBits { |
| 392 kEventTypeBit = 0, // reserve 4 bits for type. | 361 kEventTypeBit = 0, // reserve 4 bits for type. |
| 393 kPreSerializedJSON = 4, | 362 kPreSerializedJSON = 4, |
| 394 kOwnsLabelBit = 5, | 363 kOwnsLabelBit = 5, |
| 395 kNextBit = 6, | 364 kNextBit = 6, |
| 396 }; | 365 }; |
| 397 | 366 |
| 398 class EventTypeField : public BitField<uword, EventType, kEventTypeBit, 4> {}; | 367 class EventTypeField : public BitField<uword, EventType, kEventTypeBit, 4> {}; |
| 399 class PreSerializedJSON : | 368 class PreSerializedJSON |
| 400 public BitField<uword, bool, kPreSerializedJSON, 1> {}; | 369 : public BitField<uword, bool, kPreSerializedJSON, 1> {}; |
| 401 class OwnsLabelBit : public BitField<uword, bool, kOwnsLabelBit, 1> {}; | 370 class OwnsLabelBit : public BitField<uword, bool, kOwnsLabelBit, 1> {}; |
| 402 | 371 |
| 403 int64_t timestamp0_; | 372 int64_t timestamp0_; |
| 404 int64_t timestamp1_; | 373 int64_t timestamp1_; |
| 405 int64_t thread_timestamp0_; | 374 int64_t thread_timestamp0_; |
| 406 int64_t thread_timestamp1_; | 375 int64_t thread_timestamp1_; |
| 407 TimelineEventArgument* arguments_; | 376 TimelineEventArgument* arguments_; |
| 408 intptr_t arguments_length_; | 377 intptr_t arguments_length_; |
| 409 uword state_; | 378 uword state_; |
| 410 const char* label_; | 379 const char* label_; |
| 411 const char* category_; | 380 const char* category_; |
| 412 ThreadId thread_; | 381 ThreadId thread_; |
| 413 Dart_Port isolate_id_; | 382 Dart_Port isolate_id_; |
| 414 | 383 |
| 415 friend class TimelineEventRecorder; | 384 friend class TimelineEventRecorder; |
| 416 friend class TimelineEventEndlessRecorder; | 385 friend class TimelineEventEndlessRecorder; |
| 417 friend class TimelineEventRingRecorder; | 386 friend class TimelineEventRingRecorder; |
| 418 friend class TimelineEventStartupRecorder; | 387 friend class TimelineEventStartupRecorder; |
| 419 friend class TimelineEventSystraceRecorder; | 388 friend class TimelineEventSystraceRecorder; |
| 420 friend class TimelineStream; | 389 friend class TimelineStream; |
| 421 friend class TimelineTestHelper; | 390 friend class TimelineTestHelper; |
| 422 DISALLOW_COPY_AND_ASSIGN(TimelineEvent); | 391 DISALLOW_COPY_AND_ASSIGN(TimelineEvent); |
| 423 }; | 392 }; |
| 424 | 393 |
| 425 | 394 |
| 426 #ifndef PRODUCT | 395 #ifndef PRODUCT |
| 427 #define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function) \ | 396 #define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function) \ |
| 428 TimelineDurationScope tds(thread, \ | 397 TimelineDurationScope tds(thread, Timeline::GetCompilerStream(), name); \ |
| 429 Timeline::GetCompilerStream(), \ | |
| 430 name); \ | |
| 431 if (tds.enabled()) { \ | 398 if (tds.enabled()) { \ |
| 432 tds.SetNumArguments(1); \ | 399 tds.SetNumArguments(1); \ |
| 433 tds.CopyArgument( \ | 400 tds.CopyArgument(0, "function", \ |
| 434 0, \ | 401 function.ToLibNamePrefixedQualifiedCString()); \ |
| 435 "function", \ | |
| 436 function.ToLibNamePrefixedQualifiedCString()); \ | |
| 437 } | 402 } |
| 438 | 403 |
| 439 #define TIMELINE_FUNCTION_GC_DURATION(thread, name) \ | 404 #define TIMELINE_FUNCTION_GC_DURATION(thread, name) \ |
| 440 TimelineDurationScope tds(thread, Timeline::GetGCStream(), name); | 405 TimelineDurationScope tds(thread, Timeline::GetGCStream(), name); |
| 441 #else | 406 #else |
| 442 #define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function) | 407 #define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function) |
| 443 #define TIMELINE_FUNCTION_GC_DURATION(thread, name) | 408 #define TIMELINE_FUNCTION_GC_DURATION(thread, name) |
| 444 #endif // !PRODUCT | 409 #endif // !PRODUCT |
| 445 | 410 |
| 446 // See |TimelineDurationScope| and |TimelineBeginEndScope|. | 411 // See |TimelineDurationScope| and |TimelineBeginEndScope|. |
| 447 class TimelineEventScope : public StackResource { | 412 class TimelineEventScope : public StackResource { |
| 448 public: | 413 public: |
| 449 bool enabled() const { | 414 bool enabled() const { return enabled_; } |
| 450 return enabled_; | |
| 451 } | |
| 452 | 415 |
| 453 void SetNumArguments(intptr_t length); | 416 void SetNumArguments(intptr_t length); |
| 454 | 417 |
| 455 void SetArgument(intptr_t i, const char* name, char* argument); | 418 void SetArgument(intptr_t i, const char* name, char* argument); |
| 456 | 419 |
| 457 void CopyArgument(intptr_t i, const char* name, const char* argument); | 420 void CopyArgument(intptr_t i, const char* name, const char* argument); |
| 458 | 421 |
| 459 void FormatArgument(intptr_t i, | 422 void FormatArgument(intptr_t i, const char* name, const char* fmt, ...) |
| 460 const char* name, | 423 PRINTF_ATTRIBUTE(4, 5); |
| 461 const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5); | |
| 462 | 424 |
| 463 protected: | 425 protected: |
| 464 TimelineEventScope(TimelineStream* stream, | 426 TimelineEventScope(TimelineStream* stream, const char* label); |
| 465 const char* label); | |
| 466 | 427 |
| 467 TimelineEventScope(Thread* thread, | 428 TimelineEventScope(Thread* thread, TimelineStream* stream, const char* label); |
| 468 TimelineStream* stream, | |
| 469 const char* label); | |
| 470 | 429 |
| 471 bool ShouldEmitEvent() const { | 430 bool ShouldEmitEvent() const { return enabled_; } |
| 472 return enabled_; | |
| 473 } | |
| 474 | 431 |
| 475 void set_enabled(bool enabled) { | 432 void set_enabled(bool enabled) { enabled_ = enabled; } |
| 476 enabled_ = enabled; | |
| 477 } | |
| 478 | 433 |
| 479 const char* label() const { | 434 const char* label() const { return label_; } |
| 480 return label_; | |
| 481 } | |
| 482 | 435 |
| 483 TimelineStream* stream() const { | 436 TimelineStream* stream() const { return stream_; } |
| 484 return stream_; | |
| 485 } | |
| 486 | 437 |
| 487 virtual ~TimelineEventScope(); | 438 virtual ~TimelineEventScope(); |
| 488 | 439 |
| 489 void StealArguments(TimelineEvent* event); | 440 void StealArguments(TimelineEvent* event); |
| 490 | 441 |
| 491 private: | 442 private: |
| 492 void Init(); | 443 void Init(); |
| 493 void FreeArguments(); | 444 void FreeArguments(); |
| 494 | 445 |
| 495 TimelineStream* stream_; | 446 TimelineStream* stream_; |
| 496 const char* label_; | 447 const char* label_; |
| 497 TimelineEventArgument* arguments_; | 448 TimelineEventArgument* arguments_; |
| 498 intptr_t arguments_length_; | 449 intptr_t arguments_length_; |
| 499 bool enabled_; | 450 bool enabled_; |
| 500 | 451 |
| 501 DISALLOW_COPY_AND_ASSIGN(TimelineEventScope); | 452 DISALLOW_COPY_AND_ASSIGN(TimelineEventScope); |
| 502 }; | 453 }; |
| 503 | 454 |
| 504 | 455 |
| 505 class TimelineDurationScope : public TimelineEventScope { | 456 class TimelineDurationScope : public TimelineEventScope { |
| 506 public: | 457 public: |
| 507 TimelineDurationScope(TimelineStream* stream, | 458 TimelineDurationScope(TimelineStream* stream, const char* label); |
| 508 const char* label); | |
| 509 | 459 |
| 510 TimelineDurationScope(Thread* thread, | 460 TimelineDurationScope(Thread* thread, |
| 511 TimelineStream* stream, | 461 TimelineStream* stream, |
| 512 const char* label); | 462 const char* label); |
| 513 | 463 |
| 514 ~TimelineDurationScope(); | 464 ~TimelineDurationScope(); |
| 515 | 465 |
| 516 private: | 466 private: |
| 517 int64_t timestamp_; | 467 int64_t timestamp_; |
| 518 int64_t thread_timestamp_; | 468 int64_t thread_timestamp_; |
| 519 | 469 |
| 520 DISALLOW_COPY_AND_ASSIGN(TimelineDurationScope); | 470 DISALLOW_COPY_AND_ASSIGN(TimelineDurationScope); |
| 521 }; | 471 }; |
| 522 | 472 |
| 523 | 473 |
| 524 class TimelineBeginEndScope : public TimelineEventScope { | 474 class TimelineBeginEndScope : public TimelineEventScope { |
| 525 public: | 475 public: |
| 526 TimelineBeginEndScope(TimelineStream* stream, | 476 TimelineBeginEndScope(TimelineStream* stream, const char* label); |
| 527 const char* label); | |
| 528 | 477 |
| 529 TimelineBeginEndScope(Thread* thread, | 478 TimelineBeginEndScope(Thread* thread, |
| 530 TimelineStream* stream, | 479 TimelineStream* stream, |
| 531 const char* label); | 480 const char* label); |
| 532 | 481 |
| 533 ~TimelineBeginEndScope(); | 482 ~TimelineBeginEndScope(); |
| 534 | 483 |
| 535 private: | 484 private: |
| 536 void EmitBegin(); | 485 void EmitBegin(); |
| 537 void EmitEnd(); | 486 void EmitEnd(); |
| 538 | 487 |
| 539 DISALLOW_COPY_AND_ASSIGN(TimelineBeginEndScope); | 488 DISALLOW_COPY_AND_ASSIGN(TimelineBeginEndScope); |
| 540 }; | 489 }; |
| 541 | 490 |
| 542 | 491 |
| 543 // A block of |TimelineEvent|s. Not thread safe. | 492 // A block of |TimelineEvent|s. Not thread safe. |
| 544 class TimelineEventBlock { | 493 class TimelineEventBlock { |
| 545 public: | 494 public: |
| 546 static const intptr_t kBlockSize = 64; | 495 static const intptr_t kBlockSize = 64; |
| 547 | 496 |
| 548 explicit TimelineEventBlock(intptr_t index); | 497 explicit TimelineEventBlock(intptr_t index); |
| 549 ~TimelineEventBlock(); | 498 ~TimelineEventBlock(); |
| 550 | 499 |
| 551 TimelineEventBlock* next() const { | 500 TimelineEventBlock* next() const { return next_; } |
| 552 return next_; | 501 void set_next(TimelineEventBlock* next) { next_ = next; } |
| 553 } | |
| 554 void set_next(TimelineEventBlock* next) { | |
| 555 next_ = next; | |
| 556 } | |
| 557 | 502 |
| 558 intptr_t length() const { | 503 intptr_t length() const { return length_; } |
| 559 return length_; | |
| 560 } | |
| 561 | 504 |
| 562 intptr_t block_index() const { | 505 intptr_t block_index() const { return block_index_; } |
| 563 return block_index_; | |
| 564 } | |
| 565 | 506 |
| 566 bool IsEmpty() const { | 507 bool IsEmpty() const { return length_ == 0; } |
| 567 return length_ == 0; | |
| 568 } | |
| 569 | 508 |
| 570 bool IsFull() const { | 509 bool IsFull() const { return length_ == kBlockSize; } |
| 571 return length_ == kBlockSize; | |
| 572 } | |
| 573 | 510 |
| 574 TimelineEvent* At(intptr_t index) { | 511 TimelineEvent* At(intptr_t index) { |
| 575 ASSERT(index >= 0); | 512 ASSERT(index >= 0); |
| 576 ASSERT(index < kBlockSize); | 513 ASSERT(index < kBlockSize); |
| 577 return &events_[index]; | 514 return &events_[index]; |
| 578 } | 515 } |
| 579 | 516 |
| 580 const TimelineEvent* At(intptr_t index) const { | 517 const TimelineEvent* At(intptr_t index) const { |
| 581 ASSERT(index >= 0); | 518 ASSERT(index >= 0); |
| 582 ASSERT(index < kBlockSize); | 519 ASSERT(index < kBlockSize); |
| 583 return &events_[index]; | 520 return &events_[index]; |
| 584 } | 521 } |
| 585 | 522 |
| 586 // Attempt to sniff the timestamp from the first event. | 523 // Attempt to sniff the timestamp from the first event. |
| 587 int64_t LowerTimeBound() const; | 524 int64_t LowerTimeBound() const; |
| 588 | 525 |
| 589 // Returns false if |this| violates any of the following invariants: | 526 // Returns false if |this| violates any of the following invariants: |
| 590 // - events in the block come from one thread. | 527 // - events in the block come from one thread. |
| 591 // - events have monotonically increasing timestamps. | 528 // - events have monotonically increasing timestamps. |
| 592 bool CheckBlock(); | 529 bool CheckBlock(); |
| 593 | 530 |
| 594 // Call Reset on all events and set length to 0. | 531 // Call Reset on all events and set length to 0. |
| 595 void Reset(); | 532 void Reset(); |
| 596 | 533 |
| 597 // Only safe to access under the recorder's lock. | 534 // Only safe to access under the recorder's lock. |
| 598 bool in_use() const { | 535 bool in_use() const { return in_use_; } |
| 599 return in_use_; | |
| 600 } | |
| 601 | 536 |
| 602 // Only safe to access under the recorder's lock. | 537 // Only safe to access under the recorder's lock. |
| 603 ThreadId thread_id() const { | 538 ThreadId thread_id() const { return thread_id_; } |
| 604 return thread_id_; | |
| 605 } | |
| 606 | 539 |
| 607 protected: | 540 protected: |
| 608 void PrintJSON(JSONStream* stream) const; | 541 void PrintJSON(JSONStream* stream) const; |
| 609 | 542 |
| 610 TimelineEvent* StartEvent(); | 543 TimelineEvent* StartEvent(); |
| 611 | 544 |
| 612 TimelineEvent events_[kBlockSize]; | 545 TimelineEvent events_[kBlockSize]; |
| 613 TimelineEventBlock* next_; | 546 TimelineEventBlock* next_; |
| 614 intptr_t length_; | 547 intptr_t length_; |
| 615 intptr_t block_index_; | 548 intptr_t block_index_; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 return !block->IsEmpty() && !block->in_use(); | 583 return !block->IsEmpty() && !block->in_use(); |
| 651 } | 584 } |
| 652 | 585 |
| 653 virtual bool IncludeEvent(TimelineEvent* event) { | 586 virtual bool IncludeEvent(TimelineEvent* event) { |
| 654 if (event == NULL) { | 587 if (event == NULL) { |
| 655 return false; | 588 return false; |
| 656 } | 589 } |
| 657 return event->IsValid(); | 590 return event->IsValid(); |
| 658 } | 591 } |
| 659 | 592 |
| 660 int64_t time_origin_micros() const { | 593 int64_t time_origin_micros() const { return time_origin_micros_; } |
| 661 return time_origin_micros_; | |
| 662 } | |
| 663 | 594 |
| 664 int64_t time_extent_micros() const { | 595 int64_t time_extent_micros() const { return time_extent_micros_; } |
| 665 return time_extent_micros_; | |
| 666 } | |
| 667 | 596 |
| 668 private: | 597 private: |
| 669 int64_t time_origin_micros_; | 598 int64_t time_origin_micros_; |
| 670 int64_t time_extent_micros_; | 599 int64_t time_extent_micros_; |
| 671 }; | 600 }; |
| 672 | 601 |
| 673 | 602 |
| 674 class IsolateTimelineEventFilter : public TimelineEventFilter { | 603 class IsolateTimelineEventFilter : public TimelineEventFilter { |
| 675 public: | 604 public: |
| 676 explicit IsolateTimelineEventFilter(Dart_Port isolate_id, | 605 explicit IsolateTimelineEventFilter(Dart_Port isolate_id, |
| 677 int64_t time_origin_micros = -1, | 606 int64_t time_origin_micros = -1, |
| 678 int64_t time_extent_micros = -1); | 607 int64_t time_extent_micros = -1); |
| 679 | 608 |
| 680 bool IncludeBlock(TimelineEventBlock* block) { | 609 bool IncludeBlock(TimelineEventBlock* block) { |
| 681 if (block == NULL) { | 610 if (block == NULL) { |
| 682 return false; | 611 return false; |
| 683 } | 612 } |
| 684 // Not empty, not in use, and isolate match. | 613 // Not empty, not in use, and isolate match. |
| 685 return !block->IsEmpty() && !block->in_use(); | 614 return !block->IsEmpty() && !block->in_use(); |
| 686 } | 615 } |
| 687 | 616 |
| 688 bool IncludeEvent(TimelineEvent* event) { | 617 bool IncludeEvent(TimelineEvent* event) { |
| 689 return event->IsValid() && | 618 return event->IsValid() && (event->isolate_id() == isolate_id_); |
| 690 (event->isolate_id() == isolate_id_); | |
| 691 } | 619 } |
| 692 | 620 |
| 693 private: | 621 private: |
| 694 Dart_Port isolate_id_; | 622 Dart_Port isolate_id_; |
| 695 }; | 623 }; |
| 696 | 624 |
| 697 | 625 |
| 698 // Recorder of |TimelineEvent|s. | 626 // Recorder of |TimelineEvent|s. |
| 699 class TimelineEventRecorder { | 627 class TimelineEventRecorder { |
| 700 public: | 628 public: |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 775 | 703 |
| 776 | 704 |
| 777 // A recorder that stores events in a buffer of fixed capacity. When the buffer | 705 // A recorder that stores events in a buffer of fixed capacity. When the buffer |
| 778 // is full, new events overwrite old events. | 706 // is full, new events overwrite old events. |
| 779 class TimelineEventRingRecorder : public TimelineEventFixedBufferRecorder { | 707 class TimelineEventRingRecorder : public TimelineEventFixedBufferRecorder { |
| 780 public: | 708 public: |
| 781 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity) | 709 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity) |
| 782 : TimelineEventFixedBufferRecorder(capacity) {} | 710 : TimelineEventFixedBufferRecorder(capacity) {} |
| 783 ~TimelineEventRingRecorder() {} | 711 ~TimelineEventRingRecorder() {} |
| 784 | 712 |
| 785 const char* name() const { | 713 const char* name() const { return "Ring"; } |
| 786 return "Ring"; | |
| 787 } | |
| 788 | 714 |
| 789 protected: | 715 protected: |
| 790 TimelineEventBlock* GetNewBlockLocked(); | 716 TimelineEventBlock* GetNewBlockLocked(); |
| 791 }; | 717 }; |
| 792 | 718 |
| 793 | 719 |
| 794 // A recorder that writes events to Android Systrace. Events are also stored in | 720 // A recorder that writes events to Android Systrace. Events are also stored in |
| 795 // a buffer of fixed capacity. When the buffer is full, new events overwrite | 721 // a buffer of fixed capacity. When the buffer is full, new events overwrite |
| 796 // old events. | 722 // old events. |
| 797 class TimelineEventSystraceRecorder | 723 class TimelineEventSystraceRecorder : public TimelineEventFixedBufferRecorder { |
| 798 : public TimelineEventFixedBufferRecorder { | |
| 799 public: | 724 public: |
| 800 explicit TimelineEventSystraceRecorder(intptr_t capacity = kDefaultCapacity); | 725 explicit TimelineEventSystraceRecorder(intptr_t capacity = kDefaultCapacity); |
| 801 | 726 |
| 802 ~TimelineEventSystraceRecorder(); | 727 ~TimelineEventSystraceRecorder(); |
| 803 | 728 |
| 804 const char* name() const { | 729 const char* name() const { return "Systrace"; } |
| 805 return "Systrace"; | |
| 806 } | |
| 807 | 730 |
| 808 protected: | 731 protected: |
| 809 TimelineEventBlock* GetNewBlockLocked(); | 732 TimelineEventBlock* GetNewBlockLocked(); |
| 810 void CompleteEvent(TimelineEvent* event); | 733 void CompleteEvent(TimelineEvent* event); |
| 811 | 734 |
| 812 int systrace_fd_; | 735 int systrace_fd_; |
| 813 }; | 736 }; |
| 814 | 737 |
| 815 | 738 |
| 816 // A recorder that stores events in a buffer of fixed capacity. When the buffer | 739 // A recorder that stores events in a buffer of fixed capacity. When the buffer |
| 817 // is full, new events are dropped. | 740 // is full, new events are dropped. |
| 818 class TimelineEventStartupRecorder : public TimelineEventFixedBufferRecorder { | 741 class TimelineEventStartupRecorder : public TimelineEventFixedBufferRecorder { |
| 819 public: | 742 public: |
| 820 explicit TimelineEventStartupRecorder(intptr_t capacity = kDefaultCapacity) | 743 explicit TimelineEventStartupRecorder(intptr_t capacity = kDefaultCapacity) |
| 821 : TimelineEventFixedBufferRecorder(capacity) {} | 744 : TimelineEventFixedBufferRecorder(capacity) {} |
| 822 ~TimelineEventStartupRecorder() {} | 745 ~TimelineEventStartupRecorder() {} |
| 823 | 746 |
| 824 const char* name() const { | 747 const char* name() const { return "Startup"; } |
| 825 return "Startup"; | |
| 826 } | |
| 827 | 748 |
| 828 protected: | 749 protected: |
| 829 TimelineEventBlock* GetNewBlockLocked(); | 750 TimelineEventBlock* GetNewBlockLocked(); |
| 830 }; | 751 }; |
| 831 | 752 |
| 832 | 753 |
| 833 // An abstract recorder that calls |OnEvent| whenever an event is complete. | 754 // An abstract recorder that calls |OnEvent| whenever an event is complete. |
| 834 // This should only be used for testing. | 755 // This should only be used for testing. |
| 835 class TimelineEventCallbackRecorder : public TimelineEventRecorder { | 756 class TimelineEventCallbackRecorder : public TimelineEventRecorder { |
| 836 public: | 757 public: |
| 837 TimelineEventCallbackRecorder(); | 758 TimelineEventCallbackRecorder(); |
| 838 ~TimelineEventCallbackRecorder(); | 759 ~TimelineEventCallbackRecorder(); |
| 839 | 760 |
| 840 void PrintJSON(JSONStream* js, TimelineEventFilter* filter); | 761 void PrintJSON(JSONStream* js, TimelineEventFilter* filter); |
| 841 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter); | 762 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter); |
| 842 | 763 |
| 843 // Called when |event| is completed. It is unsafe to keep a reference to | 764 // Called when |event| is completed. It is unsafe to keep a reference to |
| 844 // |event| as it may be freed as soon as this function returns. | 765 // |event| as it may be freed as soon as this function returns. |
| 845 virtual void OnEvent(TimelineEvent* event) = 0; | 766 virtual void OnEvent(TimelineEvent* event) = 0; |
| 846 | 767 |
| 847 const char* name() const { | 768 const char* name() const { return "Callback"; } |
| 848 return "Callback"; | |
| 849 } | |
| 850 | 769 |
| 851 protected: | 770 protected: |
| 852 TimelineEventBlock* GetNewBlockLocked() { | 771 TimelineEventBlock* GetNewBlockLocked() { return NULL; } |
| 853 return NULL; | 772 TimelineEventBlock* GetHeadBlockLocked() { return NULL; } |
| 854 } | 773 void Clear() {} |
| 855 TimelineEventBlock* GetHeadBlockLocked() { | |
| 856 return NULL; | |
| 857 } | |
| 858 void Clear() { | |
| 859 } | |
| 860 TimelineEvent* StartEvent(); | 774 TimelineEvent* StartEvent(); |
| 861 void CompleteEvent(TimelineEvent* event); | 775 void CompleteEvent(TimelineEvent* event); |
| 862 }; | 776 }; |
| 863 | 777 |
| 864 | 778 |
| 865 // A recorder that stores events in chains of blocks of events. | 779 // A recorder that stores events in chains of blocks of events. |
| 866 // NOTE: This recorder will continue to allocate blocks until it exhausts | 780 // NOTE: This recorder will continue to allocate blocks until it exhausts |
| 867 // memory. | 781 // memory. |
| 868 class TimelineEventEndlessRecorder : public TimelineEventRecorder { | 782 class TimelineEventEndlessRecorder : public TimelineEventRecorder { |
| 869 public: | 783 public: |
| 870 TimelineEventEndlessRecorder(); | 784 TimelineEventEndlessRecorder(); |
| 871 | 785 |
| 872 void PrintJSON(JSONStream* js, TimelineEventFilter* filter); | 786 void PrintJSON(JSONStream* js, TimelineEventFilter* filter); |
| 873 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter); | 787 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter); |
| 874 | 788 |
| 875 const char* name() const { | 789 const char* name() const { return "Endless"; } |
| 876 return "Endless"; | |
| 877 } | |
| 878 | 790 |
| 879 protected: | 791 protected: |
| 880 TimelineEvent* StartEvent(); | 792 TimelineEvent* StartEvent(); |
| 881 void CompleteEvent(TimelineEvent* event); | 793 void CompleteEvent(TimelineEvent* event); |
| 882 TimelineEventBlock* GetNewBlockLocked(); | 794 TimelineEventBlock* GetNewBlockLocked(); |
| 883 TimelineEventBlock* GetHeadBlockLocked(); | 795 TimelineEventBlock* GetHeadBlockLocked(); |
| 884 void Clear(); | 796 void Clear(); |
| 885 | 797 |
| 886 void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter); | 798 void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter); |
| 887 | 799 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 908 | 820 |
| 909 private: | 821 private: |
| 910 TimelineEventBlock* current_; | 822 TimelineEventBlock* current_; |
| 911 TimelineEventRecorder* recorder_; | 823 TimelineEventRecorder* recorder_; |
| 912 }; | 824 }; |
| 913 | 825 |
| 914 | 826 |
| 915 } // namespace dart | 827 } // namespace dart |
| 916 | 828 |
| 917 #endif // RUNTIME_VM_TIMELINE_H_ | 829 #endif // RUNTIME_VM_TIMELINE_H_ |
| OLD | NEW |