Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
timeline.h
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_TIMELINE_H_
6#define RUNTIME_VM_TIMELINE_H_
7
8#include <functional>
9#include <memory>
10
12
13#include "platform/assert.h"
14#include "platform/atomic.h"
15#include "platform/hashmap.h"
16#include "vm/allocation.h"
17#include "vm/bitfield.h"
18#include "vm/globals.h"
19#include "vm/growable_array.h"
20#include "vm/os.h"
21#include "vm/os_thread.h"
22
23#if defined(SUPPORT_TIMELINE) && defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
24#include "perfetto/protozero/scattered_heap_buffer.h"
26#endif // defined(SUPPORT_TIMELINE) && defined(SUPPORT_PERFETTO) && \
27 // !defined(PRODUCT)
28
29#if defined(FUCHSIA_SDK) || defined(DART_HOST_OS_FUCHSIA)
30#include <lib/trace-engine/context.h>
31#include <lib/trace-engine/instrumentation.h>
32#elif defined(DART_HOST_OS_MACOS)
33#include <os/signpost.h>
34#endif // defined(FUCHSIA_SDK) || defined(DART_HOST_OS_FUCHSIA)
35
36namespace dart {
37
38#if !defined(SUPPORT_TIMELINE)
39#define TIMELINE_DURATION(thread, stream, name)
40#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function)
41#define TIMELINE_FUNCTION_GC_DURATION(thread, name)
42#endif // !defined(SUPPORT_TIMELINE)
43
44class JSONArray;
45class JSONBase64String;
46class JSONObject;
47class JSONStream;
48class JSONWriter;
49class Object;
50class ObjectPointerVisitor;
51class Isolate;
52class Thread;
53class TimelineEvent;
54class TimelineEventBlock;
55class TimelineEventRecorder;
56class TimelineStream;
57class VirtualMemory;
58class Zone;
59
60#if defined(SUPPORT_TIMELINE)
61#define CALLBACK_RECORDER_NAME "Callback"
62#define ENDLESS_RECORDER_NAME "Endless"
63#define FILE_RECORDER_NAME "File"
64#define FUCHSIA_RECORDER_NAME "Fuchsia"
65#define MACOS_RECORDER_NAME "Macos"
66#define PERFETTO_FILE_RECORDER_NAME "Perfettofile"
67#define RING_RECORDER_NAME "Ring"
68#define STARTUP_RECORDER_NAME "Startup"
69#define SYSTRACE_RECORDER_NAME "Systrace"
70
71// (name, fuchsia_name, has_static_labels).
72#define TIMELINE_STREAM_LIST(V) \
73 V(API, "dart:api", true) \
74 V(Compiler, "dart:compiler", true) \
75 V(CompilerVerbose, "dart:compiler.verbose", true) \
76 V(Dart, "dart:dart", false) \
77 V(Debugger, "dart:debugger", true) \
78 V(Embedder, "dart:embedder", true) \
79 V(GC, "dart:gc", true) \
80 V(Isolate, "dart:isolate", true) \
81 V(VM, "dart:vm", true)
82#endif // defined(SUPPORT_TIMELINE)
83
84// A stream of timeline events. A stream has a name and can be enabled or
85// disabled (globally and per isolate).
87 public:
88 TimelineStream(const char* name,
89 const char* fuchsia_name,
90 bool static_labels,
91 bool enabled);
92
93 const char* name() const { return name_; }
94 const char* fuchsia_name() const { return fuchsia_name_; }
95
96 bool enabled() {
97#if defined(DART_HOST_OS_FUCHSIA)
98#ifdef PRODUCT
99 return trace_is_category_enabled(fuchsia_name_);
100#else
101 return trace_is_category_enabled(fuchsia_name_) || enabled_ != 0;
102#endif // PRODUCT
103#else
104 return enabled_ != 0;
105#endif // defined(DART_HOST_OS_FUCHSIA)
106 }
107
108 void set_enabled(bool enabled) { enabled_ = enabled ? 1 : 0; }
109
110 // Records an event. Will return |nullptr| if not enabled. The returned
111 // |TimelineEvent| is in an undefined state and must be initialized.
112 TimelineEvent* StartEvent();
113
114 static intptr_t enabled_offset() {
115 return OFFSET_OF(TimelineStream, enabled_);
116 }
117
118#if defined(DART_HOST_OS_FUCHSIA)
119 trace_site_t* trace_site() { return &trace_site_; }
120#elif defined(DART_HOST_OS_MACOS)
121 os_log_t macos_log() const { return macos_log_; }
122 bool has_static_labels() const { return has_static_labels_; }
123#endif
124
125 private:
126 const char* const name_;
127 const char* const fuchsia_name_;
128
129 // This field is accessed by generated code (intrinsic) and expects to see
130 // 0 or 1. If this becomes a BitField, the generated code must be updated.
131 uintptr_t enabled_;
132
133#if defined(DART_HOST_OS_FUCHSIA)
134 trace_site_t trace_site_ = {};
135#elif defined(DART_HOST_OS_MACOS)
136 os_log_t macos_log_ = {};
137 bool has_static_labels_ = false;
138#endif
139};
140
141#if defined(SUPPORT_TIMELINE)
142class RecorderSynchronizationLock : public AllStatic {
143 public:
144 static void Init() {
145 recorder_state_.store(kActive, std::memory_order_release);
146 outstanding_event_writes_.store(0);
147 }
148
149 static void EnterLock() {
150 outstanding_event_writes_.fetch_add(1, std::memory_order_acquire);
151 }
152
153 static void ExitLock() {
154 intptr_t count =
155 outstanding_event_writes_.fetch_sub(1, std::memory_order_release);
156 ASSERT(count >= 0);
157 }
158
159 static bool IsUninitialized() {
160 return (recorder_state_.load(std::memory_order_acquire) == kUninitialized);
161 }
162
163 static bool IsActive() {
164 return (recorder_state_.load(std::memory_order_acquire) == kActive);
165 }
166
167 static bool IsShuttingDown() {
168 return (recorder_state_.load(std::memory_order_acquire) == kShuttingDown);
169 }
170
171 static void WaitForShutdown() {
172 recorder_state_.store(kShuttingDown, std::memory_order_release);
173 // Spin waiting for outstanding events to be completed.
174 while (outstanding_event_writes_.load(std::memory_order_relaxed) > 0) {
175 }
176 }
177
178 private:
179 typedef enum { kUninitialized = 0, kActive, kShuttingDown } RecorderState;
180 static std::atomic<RecorderState> recorder_state_;
181 static std::atomic<intptr_t> outstanding_event_writes_;
182
183 DISALLOW_COPY_AND_ASSIGN(RecorderSynchronizationLock);
184};
185
186// Any modifications to the timeline must be guarded by a
187// |RecorderSynchronizationLockScope| to prevent the timeline from being
188// cleaned up in the middle of the modifications.
189class RecorderSynchronizationLockScope {
190 public:
191 RecorderSynchronizationLockScope() {
192 RecorderSynchronizationLock::EnterLock();
193 }
194
195 ~RecorderSynchronizationLockScope() {
196 RecorderSynchronizationLock::ExitLock();
197 }
198
199 bool IsUninitialized() const {
200 return RecorderSynchronizationLock::IsUninitialized();
201 }
202
203 bool IsActive() const { return RecorderSynchronizationLock::IsActive(); }
204
205 bool IsShuttingDown() const {
206 return RecorderSynchronizationLock::IsShuttingDown();
207 }
208
209 private:
210 DISALLOW_COPY_AND_ASSIGN(RecorderSynchronizationLockScope);
211};
212
213class Timeline : public AllStatic {
214 public:
215 // Initialize timeline system. Not thread safe.
216 static void Init();
217
218 // Cleanup timeline system. Not thread safe.
219 static void Cleanup();
220
221 // Access the global recorder. Not thread safe.
222 static TimelineEventRecorder* recorder() { return recorder_; }
223
224 static bool recorder_discards_clock_values() {
225 return recorder_discards_clock_values_;
226 }
227 static void set_recorder_discards_clock_values(bool value) {
228 recorder_discards_clock_values_ = value;
229 }
230
232 static void set_callback(Dart_TimelineRecorderCallback callback) {
234 }
235
236 // Reclaim all |TimelineEventBlocks|s that are cached by threads.
237 static void ReclaimCachedBlocksFromThreads();
238
239 static void Clear();
240
241#ifndef PRODUCT
242 // Print information about streams to JSON.
243 static void PrintFlagsToJSON(JSONStream* json);
244
245 // Output the recorded streams to a JSONS array.
246 static void PrintFlagsToJSONArray(JSONArray* arr);
247#endif
248
249#define TIMELINE_STREAM_ACCESSOR(name, ...) \
250 static TimelineStream* Get##name##Stream() { return &stream_##name##_; }
251 TIMELINE_STREAM_LIST(TIMELINE_STREAM_ACCESSOR)
252#undef TIMELINE_STREAM_ACCESSOR
253
254#define TIMELINE_STREAM_FLAGS(name, ...) \
255 static void SetStream##name##Enabled(bool enabled) { \
256 stream_##name##_.set_enabled(enabled); \
257 }
258 TIMELINE_STREAM_LIST(TIMELINE_STREAM_FLAGS)
259#undef TIMELINE_STREAM_FLAGS
260
261 private:
262 static TimelineEventRecorder* recorder_;
264 static MallocGrowableArray<char*>* enabled_streams_;
265 static bool recorder_discards_clock_values_;
266
267#define TIMELINE_STREAM_DECLARE(name, ...) \
268 static TimelineStream stream_##name##_;
269 TIMELINE_STREAM_LIST(TIMELINE_STREAM_DECLARE)
270#undef TIMELINE_STREAM_DECLARE
271
272 template <class>
273 friend class TimelineRecorderOverride;
274 friend class ReclaimBlocksIsolateVisitor;
275};
276
277struct TimelineEventArgument {
278 const char* name;
279 char* value;
280};
281
282class TimelineEventArguments {
283 public:
284 TimelineEventArguments() : buffer_(nullptr), length_(0) {}
285 ~TimelineEventArguments() { Free(); }
286 // Get/Set the number of arguments in the event.
287 void SetNumArguments(intptr_t length);
288 // |name| must be a compile time constant. Takes ownership of |argument|.
289 void SetArgument(intptr_t i, const char* name, char* argument);
290 // |name| must be a compile time constant. Copies |argument|.
291 void CopyArgument(intptr_t i, const char* name, const char* argument);
292 // |name| must be a compile time constant. Takes ownership of |args|
293 void FormatArgument(intptr_t i,
294 const char* name,
295 const char* fmt,
296 va_list args);
297
298 void StealArguments(TimelineEventArguments* arguments);
299
300 TimelineEventArgument* buffer() const { return buffer_; }
301
302 intptr_t length() const { return length_; }
303
304 void Free();
305
306 TimelineEventArgument& operator[](intptr_t index) const {
307 return buffer_[index];
308 }
309
310 bool IsEmpty() { return length_ == 0; }
311
312 bool IsNotEmpty() { return length_ != 0; }
313
314 private:
315 TimelineEventArgument* buffer_;
316 intptr_t length_;
317 DISALLOW_COPY_AND_ASSIGN(TimelineEventArguments);
318};
319
320// You should get a |TimelineEvent| from a |TimelineStream|.
321class TimelineEvent {
322 public:
323 // Keep in sync with StateBits below.
324 // Keep in sync with constants in sdk/lib/developer/timeline.dart.
325 enum EventType {
326 kNone = 0,
327 kBegin = 1,
328 kEnd = 2,
329 kDuration = 3,
330 kInstant = 4,
331 kAsyncBegin = 5,
332 kAsyncInstant = 6,
333 kAsyncEnd = 7,
334 kCounter = 8,
335 kFlowBegin = 9,
336 kFlowStep = 10,
337 kFlowEnd = 11,
338 kMetadata = 12,
339 kNumEventTypes,
340 };
341
342 // This value must be kept in sync with the value of _noFlowId in
343 // sdk/lib/developer/timeline.dart.
344 static const int64_t kNoFlowId = -1;
345
346 TimelineEvent();
347 ~TimelineEvent();
348
349 void Reset();
350
351 bool IsValid() const {
352 return (event_type() > kNone) && (event_type() < kNumEventTypes);
353 }
354
355 // Marks the beginning of an asynchronous operation with |async_id|.
356 void AsyncBegin(const char* label,
357 int64_t async_id,
359 // Marks an instantaneous event associated with |async_id|.
360 void AsyncInstant(
361 const char* label,
362 int64_t async_id,
364 // Marks the end of an asynchronous operation associated with |async_id|.
365 void AsyncEnd(const char* label,
366 int64_t async_id,
368
369 void DurationBegin(
370 const char* label,
372
373 void Instant(const char* label,
375
376 void Duration(const char* label, int64_t start_micros, int64_t end_micros);
377
378 void Begin(const char* label,
379 int64_t id,
381
382 void End(const char* label,
383 int64_t id,
385
386 void Counter(const char* label,
388
389 void FlowBegin(const char* label,
390 int64_t id,
392 void FlowStep(const char* label,
393 int64_t id,
395 void FlowEnd(const char* label,
396 int64_t id,
398
399 void Metadata(const char* label,
401
402 void CompleteWithPreSerializedArgs(char* args_json);
403
404 // Get/Set the number of arguments in the event.
405 intptr_t GetNumArguments() const { return arguments_.length(); }
406 void SetNumArguments(intptr_t length) { arguments_.SetNumArguments(length); }
407 // |name| must be a compile time constant. Takes ownership of |argument|.
408 void SetArgument(intptr_t i, const char* name, char* argument) {
409 arguments_.SetArgument(i, name, argument);
410 }
411 // |name| must be a compile time constant. Copies |argument|.
412 void CopyArgument(intptr_t i, const char* name, const char* argument) {
413 arguments_.CopyArgument(i, name, argument);
414 }
415 // |name| must be a compile time constant.
416 void FormatArgument(intptr_t i, const char* name, const char* fmt, ...)
417 PRINTF_ATTRIBUTE(4, 5);
418
419 void StealArguments(TimelineEventArguments* arguments) {
420 arguments_.StealArguments(arguments);
421 }
422 // Mandatory to call when this event is completely filled out.
423 void Complete();
424
425 EventType event_type() const { return EventTypeField::decode(state_); }
426
427 TimelineStream* stream() const { return stream_; }
428
429 int64_t TimeOrigin() const { return timestamp0_; }
430 int64_t Id() const {
431 ASSERT(event_type() != kDuration && event_type() != kInstant &&
432 event_type() != kCounter);
433 return timestamp1_or_id_;
434 }
435 int64_t TimeDuration() const;
436 void SetTimeEnd(int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline()) {
437 ASSERT(event_type() == kDuration);
438 ASSERT(timestamp1_or_id_ == 0);
439 set_timestamp1_or_id(micros);
440 }
441 int64_t TimeEnd() const {
442 ASSERT(IsFinishedDuration());
443 return timestamp1_or_id_;
444 }
445
446 int64_t timestamp0() const { return timestamp0_; }
447 int64_t timestamp1_or_id() const { return timestamp1_or_id_; }
448
449 void SetFlowIds(intptr_t flow_id_count,
450 std::unique_ptr<const int64_t[]>& flow_ids) {
451 flow_id_count_ = flow_id_count;
452 flow_ids_.swap(flow_ids);
453 }
454 intptr_t flow_id_count() const { return flow_id_count_; }
455 const int64_t* FlowIds() const { return flow_ids_.get(); }
456
457 bool HasIsolateId() const;
458 bool HasIsolateGroupId() const;
459 std::unique_ptr<const char[]> GetFormattedIsolateId() const;
460 std::unique_ptr<const char[]> GetFormattedIsolateGroupId() const;
461
462 // The lowest time value stored in this event.
463 int64_t LowTime() const;
464 // The highest time value stored in this event.
465 int64_t HighTime() const;
466
467#ifndef PRODUCT
468 void PrintJSON(JSONStream* stream) const;
469#endif
470 void PrintJSON(JSONWriter* writer) const;
471#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
472 bool CanBeRepresentedByPerfettoTracePacket() const;
473 /*
474 * Populates the fields of |packet| with this event's data.
475 */
476 void PopulateTracePacket(perfetto::protos::pbzero::TracePacket* packet) const;
477#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
478
479 ThreadId thread() const { return thread_; }
480
481 void set_thread(ThreadId tid) { thread_ = tid; }
482
483 Dart_Port isolate_id() const { return isolate_id_; }
484
485 uint64_t isolate_group_id() const { return isolate_group_id_; }
486
487 void* isolate_data() const { return isolate_data_; }
488
489 void* isolate_group_data() const { return isolate_group_data_; }
490
491 const char* label() const { return label_; }
492
493 // Does this duration end before |micros| ?
494 bool DurationFinishedBefore(int64_t micros) const {
495 return TimeEnd() <= micros;
496 }
497
498 bool IsDuration() const { return (event_type() == kDuration); }
499
500 bool IsBegin() const { return (event_type() == kBegin); }
501
502 bool IsEnd() const { return (event_type() == kEnd); }
503
504 // Is this event a synchronous begin or end event?
505 bool IsBeginOrEnd() const { return IsBegin() || IsEnd(); }
506
507 // Does this duration fully contain |other| ?
508 bool DurationContains(TimelineEvent* other) const {
509 ASSERT(IsFinishedDuration());
510 if (other->IsBegin()) {
511 if (other->TimeOrigin() < TimeOrigin()) {
512 return false;
513 }
514 if (other->TimeOrigin() > TimeEnd()) {
515 return false;
516 }
517 return true;
518 } else {
519 ASSERT(other->IsFinishedDuration());
520 if (other->TimeOrigin() < TimeOrigin()) {
521 return false;
522 }
523 if (other->TimeEnd() < TimeOrigin()) {
524 return false;
525 }
526 if (other->TimeOrigin() > TimeEnd()) {
527 return false;
528 }
529 if (other->TimeEnd() > TimeEnd()) {
530 return false;
531 }
532 return true;
533 }
534 }
535
536 bool Within(int64_t time_origin_micros, int64_t time_extent_micros);
537
538 void set_owns_label(bool owns_label) {
539 state_ = OwnsLabelBit::update(owns_label, state_);
540 }
541
542 TimelineEventArgument* arguments() const { return arguments_.buffer(); }
543
544 intptr_t arguments_length() const { return arguments_.length(); }
545
546 bool ArgsArePreSerialized() const {
547 return PreSerializedArgsBit::decode(state_);
548 }
549
550 TimelineEvent* next() const { return next_; }
551 void set_next(TimelineEvent* next) { next_ = next; }
552
553 private:
554 void StreamInit(TimelineStream* stream) { stream_ = stream; }
555 void Init(EventType event_type, const char* label);
556
557 void set_event_type(EventType event_type) {
558 // We only reserve 4 bits to hold the event type.
559 COMPILE_ASSERT(kNumEventTypes < 16);
560 state_ = EventTypeField::update(event_type, state_);
561 }
562
563 void set_timestamp0(int64_t value) {
564 ASSERT(timestamp0_ == 0);
565 timestamp0_ = value;
566 }
567 void set_timestamp1_or_id(int64_t value) {
568 ASSERT(timestamp1_or_id_ == 0);
569 timestamp1_or_id_ = value;
570 }
571
572 bool IsFinishedDuration() const {
573 return (event_type() == kDuration) && (timestamp1_or_id_ > timestamp0_);
574 }
575
576 void set_pre_serialized_args(bool pre_serialized_args) {
577 state_ = PreSerializedArgsBit::update(pre_serialized_args, state_);
578 }
579
580 bool owns_label() const { return OwnsLabelBit::decode(state_); }
581
582 enum StateBits {
583 kEventTypeBit = 0, // reserve 4 bits for type.
584 kPreSerializedArgsBit = 4,
585 kOwnsLabelBit = 5,
586 kNextBit = 6,
587 };
588
589 class EventTypeField : public BitField<uword, EventType, kEventTypeBit, 4> {};
590 class PreSerializedArgsBit
591 : public BitField<uword, bool, kPreSerializedArgsBit, 1> {};
592 class OwnsLabelBit : public BitField<uword, bool, kOwnsLabelBit, 1> {};
593
594 int64_t timestamp0_;
595 // For an event of type |kDuration|, this is the end time. For an event of
596 // type |kFlowBegin|, |kFlowStep|, or |kFlowEnd| this is the flow ID. For an
597 // event of type |kBegin| or |kEnd|, this is the event ID (which is only
598 // referenced by the MacOS recorder). For an async event, this is the async
599 // ID.
600 int64_t timestamp1_or_id_;
601 intptr_t flow_id_count_;
602 // This field is needed to support trace serialization in Perfetto's proto
603 // format. Flow IDs must be associated with |TimelineEvent::kBegin|,
604 // |TimelineEvent::kDuration|, |TimelineEvent::kInstant|,
605 // |TimelineEvent::kAsyncBegin|, and |TimelineEvent::kAsyncInstant| events to
606 // serialize traces in Perfetto's format. Flow event information is serialized
607 // in Chrome's JSON trace format through events of type
608 // |TimelineEvent::kFlowBegin|, |TimelineEvent::kFlowStep|, and
609 // |TimelineEvent::kFlowEnd|.
610 std::unique_ptr<const int64_t[]> flow_ids_;
611 TimelineEventArguments arguments_;
612 uword state_;
613 const char* label_;
614 TimelineStream* stream_;
615 ThreadId thread_;
616 Dart_Port isolate_id_;
617 uint64_t isolate_group_id_;
618 void* isolate_data_;
619 void* isolate_group_data_;
620 TimelineEvent* next_;
621
622 friend class TimelineEventRecorder;
623 friend class TimelineEventEndlessRecorder;
624 friend class TimelineEventRingRecorder;
625 friend class TimelineEventStartupRecorder;
626 friend class TimelineEventPlatformRecorder;
627 friend class TimelineEventFuchsiaRecorder;
628 friend class TimelineEventMacosRecorder;
629#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
630 friend class TimelineEventPerfettoFileRecorder;
631#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
632 friend class TimelineStream;
633 friend class TimelineTestHelper;
634 DISALLOW_COPY_AND_ASSIGN(TimelineEvent);
635};
636
637class TimelineTrackMetadata {
638 public:
639 TimelineTrackMetadata(intptr_t pid,
640 intptr_t tid,
641 CStringUniquePtr&& track_name);
642 intptr_t pid() const { return pid_; }
643 intptr_t tid() const { return tid_; }
644 const char* track_name() const { return track_name_.get(); }
645 inline void set_track_name(CStringUniquePtr&& track_name);
646#if !defined(PRODUCT)
647 /*
648 * Prints a Chrome-format event representing the metadata stored by this
649 * object into |jsarr_events|.
650 */
651 void PrintJSON(const JSONArray& jsarr_events) const;
652#if defined(SUPPORT_PERFETTO)
653 /*
654 * Populates the fields of |track_descriptor_packet| with the metadata stored
655 * by this object.
656 */
657 void PopulateTracePacket(
658 perfetto::protos::pbzero::TracePacket* track_descriptor_packet) const;
659#endif // defined(SUPPORT_PERFETTO)
660#endif // !defined(PRODUCT)
661
662 private:
663 // The ID of the process that this track is associated with.
664 intptr_t pid_;
665 // The trace ID of the thread that this track is associated with.
666 intptr_t tid_;
667 // The name of this track.
668 CStringUniquePtr track_name_;
669};
670
671class AsyncTimelineTrackMetadata {
672 public:
673 AsyncTimelineTrackMetadata(intptr_t pid, intptr_t async_id);
674 intptr_t pid() const { return pid_; }
675 intptr_t async_id() const { return async_id_; }
676#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
677 /*
678 * Populates the fields of |track_descriptor_packet| with the metadata stored
679 * by this object.
680 */
681 void PopulateTracePacket(
682 perfetto::protos::pbzero::TracePacket* track_descriptor_packet) const;
683#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
684
685 private:
686 // The ID of the process that this track is associated with.
687 intptr_t pid_;
688 // The async ID that this track is associated with.
689 intptr_t async_id_;
690};
691
692#define TIMELINE_DURATION(thread, stream, name) \
693 TimelineBeginEndScope tbes(thread, Timeline::Get##stream##Stream(), name);
694#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function) \
695 TimelineBeginEndScope tbes(thread, Timeline::GetCompilerStream(), name); \
696 if (tbes.enabled()) { \
697 tbes.SetNumArguments(1); \
698 tbes.CopyArgument(0, "function", function.ToQualifiedCString()); \
699 }
700
701#define TIMELINE_FUNCTION_GC_DURATION(thread, name) \
702 TimelineBeginEndScope tbes(thread, Timeline::GetGCStream(), name);
703
704// See |TimelineBeginEndScope|.
705class TimelineEventScope : public StackResource {
706 public:
707 bool enabled() const { return enabled_; }
708
709 intptr_t GetNumArguments() { return arguments_.length(); }
710 void SetNumArguments(intptr_t length);
711
712 void SetArgument(intptr_t i, const char* name, char* argument);
713
714 void CopyArgument(intptr_t i, const char* name, const char* argument);
715
716 void FormatArgument(intptr_t i, const char* name, const char* fmt, ...)
717 PRINTF_ATTRIBUTE(4, 5);
718
719 protected:
720 TimelineEventScope(TimelineStream* stream, const char* label);
721
722 TimelineEventScope(Thread* thread, TimelineStream* stream, const char* label);
723
724 bool ShouldEmitEvent() const { return enabled_; }
725
726 void set_enabled(bool enabled) { enabled_ = enabled; }
727
728 const char* label() const { return label_; }
729
730 int64_t id() const { return id_; }
731
732 TimelineEventArgument* arguments() const { return arguments_.buffer(); }
733
734 intptr_t arguments_length() const { return arguments_.length(); }
735
736 TimelineStream* stream() const { return stream_; }
737
738 virtual ~TimelineEventScope();
739
740 void StealArguments(TimelineEvent* event);
741
742 private:
743 void Init();
744
745 TimelineStream* stream_;
746 const char* label_;
747 int64_t id_;
748 TimelineEventArguments arguments_;
749 bool enabled_;
750
751 DISALLOW_COPY_AND_ASSIGN(TimelineEventScope);
752};
753
754class TimelineBeginEndScope : public TimelineEventScope {
755 public:
756 TimelineBeginEndScope(TimelineStream* stream, const char* label);
757
758 TimelineBeginEndScope(Thread* thread,
759 TimelineStream* stream,
760 const char* label);
761
762 virtual ~TimelineBeginEndScope();
763
764 private:
765 void EmitBegin();
766 void EmitEnd();
767
768 DISALLOW_COPY_AND_ASSIGN(TimelineBeginEndScope);
769};
770
771// A block of |TimelineEvent|s. Not thread safe.
772class TimelineEventBlock : public MallocAllocated {
773 public:
774 static constexpr intptr_t kBlockSize = 64;
775
776 explicit TimelineEventBlock(intptr_t index);
777 ~TimelineEventBlock();
778
779 TimelineEventBlock* next() const { return next_; }
780 void set_next(TimelineEventBlock* next) { next_ = next; }
781
782 intptr_t length() const { return length_; }
783
784 intptr_t block_index() const { return block_index_; }
785
786 bool IsEmpty() const { return length_ == 0; }
787
788 bool IsFull() const { return length_ == kBlockSize; }
789
790 TimelineEvent* At(intptr_t index) {
791 ASSERT(index >= 0);
792 ASSERT(index < kBlockSize);
793 return &events_[index];
794 }
795
796 const TimelineEvent* At(intptr_t index) const {
797 ASSERT(index >= 0);
798 ASSERT(index < kBlockSize);
799 return &events_[index];
800 }
801
802 // Attempt to sniff the timestamp from the first event.
803 int64_t LowerTimeBound() const;
804
805 // Call Reset on all events and set length to 0.
806 void Reset();
807
808 // Only safe to access under the recorder's lock.
809 inline bool InUseLocked() const;
810
811 // Only safe to access under the recorder's lock.
812 inline bool ContainsEventsThatCanBeSerializedLocked() const;
813
814 protected:
815#ifndef PRODUCT
816 void PrintJSON(JSONStream* stream) const;
817#endif
818
819 // Only safe to call from the thread that owns this block, while the thread is
820 // holding its block lock.
821 TimelineEvent* StartEventLocked();
822
823 TimelineEvent events_[kBlockSize];
824 TimelineEventBlock* next_;
825 intptr_t length_;
826 intptr_t block_index_;
827
828 // Only safe to access under the recorder's lock.
829 OSThread* current_owner_;
830 bool in_use_;
831
832 void Open();
833
834 friend class Thread;
835 friend class TimelineEventRecorder;
836 friend class TimelineEventEndlessRecorder;
837 friend class TimelineEventRingRecorder;
838 friend class TimelineEventStartupRecorder;
839 friend class TimelineEventPlatformRecorder;
840 friend class TimelineTestHelper;
841 friend class JSONStream;
842
843 private:
844 void Finish();
845
846 DISALLOW_COPY_AND_ASSIGN(TimelineEventBlock);
847};
848
849class TimelineEventFilter : public ValueObject {
850 public:
851 TimelineEventFilter(int64_t time_origin_micros = -1,
852 int64_t time_extent_micros = -1);
853
854 virtual ~TimelineEventFilter();
855
856 virtual bool IncludeEvent(TimelineEvent* event) const {
857 if (event == nullptr) {
858 return false;
859 }
860 return event->IsValid();
861 }
862
863 int64_t time_origin_micros() const { return time_origin_micros_; }
864
865 int64_t time_extent_micros() const { return time_extent_micros_; }
866
867 private:
868 int64_t time_origin_micros_;
869 int64_t time_extent_micros_;
870};
871
872class IsolateTimelineEventFilter : public TimelineEventFilter {
873 public:
874 explicit IsolateTimelineEventFilter(Dart_Port isolate_id,
875 int64_t time_origin_micros = -1,
876 int64_t time_extent_micros = -1);
877
878 bool IncludeEvent(TimelineEvent* event) const final {
879 return event->IsValid() && (event->isolate_id() == isolate_id_);
880 }
881
882 private:
883 Dart_Port isolate_id_;
884};
885
886// Recorder of |TimelineEvent|s.
887class TimelineEventRecorder : public MallocAllocated {
888 public:
889 TimelineEventRecorder();
890 virtual ~TimelineEventRecorder();
891
892 // Interface method(s) which must be implemented.
893#ifndef PRODUCT
894 virtual void PrintJSON(JSONStream* js, TimelineEventFilter* filter) = 0;
895#if defined(SUPPORT_PERFETTO)
896 /*
897 * Prints a PerfettoTimeline service response into |js|.
898 */
899 virtual void PrintPerfettoTimeline(JSONStream* js,
900 const TimelineEventFilter& filter) = 0;
901#endif // defined(SUPPORT_PERFETTO)
902 virtual void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) = 0;
903#endif // !defined(PRODUCT)
904 virtual const char* name() const = 0;
905 virtual intptr_t Size() = 0;
906 // Only safe to call when holding |lock_|.
907 virtual TimelineEventBlock* GetNewBlockLocked() = 0;
908 void FinishBlock(TimelineEventBlock* block);
909 // This function must be called at least once for each thread that corresponds
910 // to a track in the trace.
911 void AddTrackMetadataBasedOnThread(const intptr_t process_id,
912 const intptr_t trace_id,
913 const char* thread_name);
914 void AddAsyncTrackMetadataBasedOnEvent(const TimelineEvent& event);
915
916 protected:
917 SimpleHashMap& track_uuid_to_track_metadata() {
918 return track_uuid_to_track_metadata_;
919 }
920 SimpleHashMap& async_track_uuid_to_track_metadata() {
921 return async_track_uuid_to_track_metadata_;
922 }
923#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
924 protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket>& packet() {
925 return packet_;
926 }
927#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
928
929#ifndef PRODUCT
930 void WriteTo(const char* directory);
931#endif
932
933 // Interface method(s) which must be implemented.
934 virtual TimelineEvent* StartEvent() = 0;
935 virtual void CompleteEvent(TimelineEvent* event) = 0;
936 // Only safe to call when holding |lock_|.
937 virtual TimelineEventBlock* GetHeadBlockLocked() = 0;
938 // Only safe to call when holding |lock_|.
939 virtual void ClearLocked() = 0;
940
941 // Utility method(s).
942#ifndef PRODUCT
943 void PrintJSONMeta(const JSONArray& jsarr_events);
944#if defined(SUPPORT_PERFETTO)
945 /*
946 * Appends metadata about the timeline in Perfetto's proto format to
947 * |jsonBase64String|.
948 */
949 void PrintPerfettoMeta(JSONBase64String* jsonBase64String);
950#endif // defined(SUPPORT_PERFETTO)
951#endif // !defined(PRODUCT)
952 TimelineEvent* ThreadBlockStartEvent();
953 void ThreadBlockCompleteEvent(TimelineEvent* event);
954
955 void ResetTimeTracking();
956 void ReportTime(int64_t micros);
957 int64_t TimeOriginMicros() const;
958 int64_t TimeExtentMicros() const;
959
960 Mutex lock_;
961 int64_t time_low_micros_;
962 int64_t time_high_micros_;
963
964 friend class TimelineEvent;
965 friend class TimelineEventBlock;
966 friend class TimelineStream;
967 friend class TimelineTestHelper;
968 friend class Timeline;
969 friend class OSThread;
970
971 private:
972 static constexpr intptr_t kTrackUuidToTrackMetadataInitialCapacity = 1 << 4;
973 Mutex track_uuid_to_track_metadata_lock_;
974 SimpleHashMap track_uuid_to_track_metadata_;
975 Mutex async_track_uuid_to_track_metadata_lock_;
976 SimpleHashMap async_track_uuid_to_track_metadata_;
977#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
978 // We allocate one heap-buffered packet as a class member, because it lets us
979 // continuously follow a cycle of resetting the buffer and writing its
980 // contents.
981 protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket> packet_;
982#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
983
984 DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder);
985};
986
987// An abstract recorder that stores events in a buffer of fixed capacity.
988class TimelineEventFixedBufferRecorder : public TimelineEventRecorder {
989 public:
990 static constexpr intptr_t kDefaultCapacity = 32 * KB; // Number of events.
991
992 explicit TimelineEventFixedBufferRecorder(intptr_t capacity);
993 virtual ~TimelineEventFixedBufferRecorder();
994
995#ifndef PRODUCT
996 void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
997#if defined(SUPPORT_PERFETTO)
998 void PrintPerfettoTimeline(JSONStream* js,
999 const TimelineEventFilter& filter) final;
1000#endif // defined(SUPPORT_PERFETTO)
1001 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
1002#endif // !defined(PRODUCT)
1003
1004 intptr_t Size();
1005
1006 protected:
1007 TimelineEvent* StartEvent();
1008 void CompleteEvent(TimelineEvent* event);
1009 TimelineEventBlock* GetHeadBlockLocked();
1010 // Only safe to call when holding |lock_|.
1011 intptr_t FindOldestBlockIndexLocked() const;
1012 void ClearLocked();
1013
1014#ifndef PRODUCT
1015 void PrintJSONEvents(const JSONArray& array,
1016 const TimelineEventFilter& filter);
1017#if defined(SUPPORT_PERFETTO)
1018 void PrintPerfettoEvents(JSONBase64String* jsonBase64String,
1019 const TimelineEventFilter& filter);
1020#endif // defined(SUPPORT_PERFETTO)
1021#endif // !defined(PRODUCT)
1022
1023 VirtualMemory* memory_;
1024 TimelineEventBlock* blocks_;
1025 intptr_t capacity_;
1026 intptr_t num_blocks_;
1027 intptr_t block_cursor_;
1028
1029 private:
1030#if !defined(PRODUCT)
1031 inline void PrintEventsCommon(
1032 const TimelineEventFilter& filter,
1033 std::function<void(const TimelineEvent&)>&& print_impl);
1034#endif // !defined(PRODUCT)
1035};
1036
1037// A recorder that stores events in a buffer of fixed capacity. When the buffer
1038// is full, new events overwrite old events.
1039class TimelineEventRingRecorder : public TimelineEventFixedBufferRecorder {
1040 public:
1041 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity)
1042 : TimelineEventFixedBufferRecorder(capacity) {}
1043 virtual ~TimelineEventRingRecorder() {}
1044
1045 const char* name() const { return RING_RECORDER_NAME; }
1046
1047 protected:
1048 TimelineEventBlock* GetNewBlockLocked();
1049};
1050
1051// A recorder that stores events in a buffer of fixed capacity. When the buffer
1052// is full, new events are dropped.
1053class TimelineEventStartupRecorder : public TimelineEventFixedBufferRecorder {
1054 public:
1055 explicit TimelineEventStartupRecorder(intptr_t capacity = kDefaultCapacity)
1056 : TimelineEventFixedBufferRecorder(capacity) {}
1057 virtual ~TimelineEventStartupRecorder() {}
1058
1059 const char* name() const { return STARTUP_RECORDER_NAME; }
1060
1061 protected:
1062 TimelineEventBlock* GetNewBlockLocked();
1063};
1064
1065// An abstract recorder that calls |OnEvent| whenever an event is complete.
1066// This should only be used for testing.
1067class TimelineEventCallbackRecorder : public TimelineEventRecorder {
1068 public:
1069 TimelineEventCallbackRecorder();
1070 virtual ~TimelineEventCallbackRecorder();
1071
1072#ifndef PRODUCT
1073 void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
1074#if defined(SUPPORT_PERFETTO)
1075 void PrintPerfettoTimeline(JSONStream* js,
1076 const TimelineEventFilter& filter) final;
1077#endif // defined(SUPPORT_PERFETTO)
1078 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
1079#endif // !defined(PRODUCT)
1080
1081 // Called when |event| is completed. It is unsafe to keep a reference to
1082 // |event| as it may be freed as soon as this function returns.
1083 virtual void OnEvent(TimelineEvent* event) = 0;
1084
1085 const char* name() const { return CALLBACK_RECORDER_NAME; }
1086 intptr_t Size() { return 0; }
1087
1088 protected:
1089 TimelineEventBlock* GetNewBlockLocked() { UNREACHABLE(); }
1090 TimelineEventBlock* GetHeadBlockLocked() { UNREACHABLE(); }
1091 void ClearLocked() { ASSERT(lock_.IsOwnedByCurrentThread()); }
1092 TimelineEvent* StartEvent();
1093 void CompleteEvent(TimelineEvent* event);
1094};
1095
1096// A recorder that forwards completed events to the callback provided by
1097// Dart_SetTimelineRecorderCallback.
1098class TimelineEventEmbedderCallbackRecorder
1099 : public TimelineEventCallbackRecorder {
1100 public:
1101 TimelineEventEmbedderCallbackRecorder() {}
1102 virtual ~TimelineEventEmbedderCallbackRecorder() {}
1103
1104 virtual void OnEvent(TimelineEvent* event);
1105};
1106
1107// A recorder that does nothing.
1108class TimelineEventNopRecorder : public TimelineEventCallbackRecorder {
1109 public:
1110 TimelineEventNopRecorder() {}
1111 virtual ~TimelineEventNopRecorder() {}
1112
1113 virtual void OnEvent(TimelineEvent* event);
1114};
1115
1116// A recorder that stores events in chains of blocks of events.
1117// NOTE: This recorder will continue to allocate blocks until it exhausts
1118// memory.
1119class TimelineEventEndlessRecorder : public TimelineEventRecorder {
1120 public:
1121 TimelineEventEndlessRecorder();
1122 virtual ~TimelineEventEndlessRecorder();
1123
1124#ifndef PRODUCT
1125 void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
1126#if defined(SUPPORT_PERFETTO)
1127 void PrintPerfettoTimeline(JSONStream* js,
1128 const TimelineEventFilter& filter) final;
1129#endif // defined(SUPPORT_PERFETTO)
1130 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
1131#endif // !defined(PRODUCT)
1132
1133 const char* name() const { return ENDLESS_RECORDER_NAME; }
1134 intptr_t Size() { return block_index_ * sizeof(TimelineEventBlock); }
1135
1136 protected:
1137 TimelineEvent* StartEvent();
1138 void CompleteEvent(TimelineEvent* event);
1139 TimelineEventBlock* GetNewBlockLocked();
1140 TimelineEventBlock* GetHeadBlockLocked();
1141 void ClearLocked();
1142
1143#ifndef PRODUCT
1144 void PrintJSONEvents(const JSONArray& array,
1145 const TimelineEventFilter& filter);
1146#if defined(SUPPORT_PERFETTO)
1147 void PrintPerfettoEvents(JSONBase64String* jsonBase64String,
1148 const TimelineEventFilter& filter);
1149#endif // defined(SUPPORT_PERFETTO)
1150#endif // !defined(PRODUCT)
1151
1152 TimelineEventBlock* head_;
1153 TimelineEventBlock* tail_;
1154 intptr_t block_index_;
1155
1156 private:
1157#if !defined(PRODUCT)
1158 inline void PrintEventsCommon(
1159 const TimelineEventFilter& filter,
1160 std::function<void(const TimelineEvent&)>&& print_impl);
1161#endif // !defined(PRODUCT)
1162
1163 friend class TimelineTestHelper;
1164};
1165
1166// The TimelineEventPlatformRecorder records timeline events to a platform
1167// specific destination. It's implementation is in the timeline_{linux,...}.cc
1168// files.
1169class TimelineEventPlatformRecorder : public TimelineEventRecorder {
1170 public:
1171 TimelineEventPlatformRecorder();
1172 virtual ~TimelineEventPlatformRecorder();
1173
1174#ifndef PRODUCT
1175 void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
1176#if defined(SUPPORT_PERFETTO)
1177 void PrintPerfettoTimeline(JSONStream* js,
1178 const TimelineEventFilter& filter) final;
1179#endif // defined(SUPPORT_PERFETTO)
1180 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
1181#endif // !defined(PRODUCT)
1182
1183 // Called when |event| is completed. It is unsafe to keep a reference to
1184 // |event| as it may be freed as soon as this function returns.
1185 virtual void OnEvent(TimelineEvent* event) = 0;
1186
1187 virtual const char* name() const = 0;
1188
1189 protected:
1190 TimelineEventBlock* GetNewBlockLocked() { UNREACHABLE(); }
1191 TimelineEventBlock* GetHeadBlockLocked() { UNREACHABLE(); }
1192 void ClearLocked() { ASSERT(lock_.IsOwnedByCurrentThread()); }
1193 TimelineEvent* StartEvent();
1194 void CompleteEvent(TimelineEvent* event);
1195};
1196
1197#if defined(DART_HOST_OS_FUCHSIA)
1198// A recorder that sends events to Fuchsia's tracing app.
1199class TimelineEventFuchsiaRecorder : public TimelineEventPlatformRecorder {
1200 public:
1201 TimelineEventFuchsiaRecorder() {}
1202 virtual ~TimelineEventFuchsiaRecorder() {}
1203
1204 const char* name() const { return FUCHSIA_RECORDER_NAME; }
1205 intptr_t Size() { return 0; }
1206
1207 private:
1208 void OnEvent(TimelineEvent* event);
1209};
1210#endif // defined(DART_HOST_OS_FUCHSIA)
1211
1212#if defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX)
1213// A recorder that writes events to Android Systrace. This class is exposed in
1214// this header file only so that PrintSystrace can be visible to
1215// timeline_test.cc.
1216class TimelineEventSystraceRecorder : public TimelineEventPlatformRecorder {
1217 public:
1218 TimelineEventSystraceRecorder();
1219 virtual ~TimelineEventSystraceRecorder();
1220
1221 static intptr_t PrintSystrace(TimelineEvent* event,
1222 char* buffer,
1223 intptr_t buffer_size);
1224
1225 const char* name() const { return SYSTRACE_RECORDER_NAME; }
1226 intptr_t Size() { return 0; }
1227
1228 private:
1229 void OnEvent(TimelineEvent* event);
1230
1231 int systrace_fd_;
1232};
1233#endif // defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX)
1234
1235#if defined(DART_HOST_OS_MACOS)
1236// A recorder that sends events to macOS's tracing app. See:
1237// https://developer.apple.com/documentation/os/logging?language=objc
1238class TimelineEventMacosRecorder : public TimelineEventPlatformRecorder {
1239 public:
1240 TimelineEventMacosRecorder();
1241 virtual ~TimelineEventMacosRecorder();
1242
1243 const char* name() const { return MACOS_RECORDER_NAME; }
1244 intptr_t Size() { return 0; }
1245
1246 private:
1247 void OnEvent(TimelineEvent* event);
1248};
1249#endif // defined(DART_HOST_OS_MACOS)
1250
1251class TimelineEventFileRecorderBase : public TimelineEventPlatformRecorder {
1252 public:
1253 explicit TimelineEventFileRecorderBase(const char* path);
1254 virtual ~TimelineEventFileRecorderBase();
1255
1256 intptr_t Size() final { return 0; }
1257 void OnEvent(TimelineEvent* event) final { UNREACHABLE(); }
1258 void Drain();
1259
1260 protected:
1261 void Write(const char* buffer, intptr_t len) const;
1262 void Write(const char* buffer) const { Write(buffer, strlen(buffer)); }
1263 void CompleteEvent(TimelineEvent* event) final;
1264 void ShutDown();
1265
1266 private:
1267 virtual void DrainImpl(const TimelineEvent& event) = 0;
1268
1269 Monitor monitor_;
1270 TimelineEvent* head_;
1271 TimelineEvent* tail_;
1272 void* file_;
1273 bool shutting_down_;
1274 bool drained_;
1275 ThreadJoinId thread_id_;
1276};
1277
1278class TimelineEventFileRecorder : public TimelineEventFileRecorderBase {
1279 public:
1280 explicit TimelineEventFileRecorder(const char* path);
1281 virtual ~TimelineEventFileRecorder();
1282
1283 const char* name() const final { return FILE_RECORDER_NAME; }
1284
1285 private:
1286 void DrainImpl(const TimelineEvent& event) final;
1287
1288 bool first_;
1289};
1290
1291#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
1292class TimelineEventPerfettoFileRecorder : public TimelineEventFileRecorderBase {
1293 public:
1294 explicit TimelineEventPerfettoFileRecorder(const char* path);
1295 virtual ~TimelineEventPerfettoFileRecorder();
1296
1297 const char* name() const final { return PERFETTO_FILE_RECORDER_NAME; }
1298
1299 private:
1300 void WritePacket(
1301 protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket>* packet)
1302 const;
1303 void DrainImpl(const TimelineEvent& event) final;
1304};
1305#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
1306
1307class DartTimelineEventHelpers : public AllStatic {
1308 public:
1309 // When reporting an event of type |kAsyncBegin|, |kAsyncEnd|, or
1310 // |kAsyncInstant|, the async ID associated with the event should be passed
1311 // through |id|. When reporting an event of type |kFlowBegin|, |kFlowStep|,
1312 // or |kFlowEnd|, the flow ID associated with the event should be passed
1313 // through |id|. When reporting an event of type |kBegin| or |kEnd|, the event
1314 // ID associated with the event should be passed through |id|. Note that this
1315 // event ID will only be used by the MacOS recorder.
1316 static void ReportTaskEvent(TimelineEvent* event,
1317 int64_t id,
1318 intptr_t flow_id_count,
1319 std::unique_ptr<const int64_t[]>& flow_ids,
1320 intptr_t type,
1321 char* name,
1322 char* args);
1323};
1324#endif // defined(SUPPORT_TIMELINE)
1325
1326} // namespace dart
1327
1328#endif // RUNTIME_VM_TIMELINE_H_
int count
Definition: FontMgrTest.cpp:50
static uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment)
static float next(float f)
ax::mojom::Event event_type
#define UNREACHABLE()
Definition: assert.h:248
GLenum type
static int64_t GetCurrentMonotonicMicrosForTimeline()
const char * name() const
Definition: timeline.h:93
static intptr_t enabled_offset()
Definition: timeline.h:114
TimelineEvent * StartEvent()
void set_enabled(bool enabled)
Definition: timeline.h:108
TimelineStream(const char *name, const char *fuchsia_name, bool static_labels, bool enabled)
const char * fuchsia_name() const
Definition: timeline.h:94
int64_t Dart_Port
Definition: dart_api.h:1525
void(* Dart_TimelineRecorderCallback)(Dart_TimelineRecorderEvent *event)
#define ASSERT(E)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlKeyEvent * event
uint8_t value
Dart_NativeFunction function
Definition: fuchsia.cc:51
void Init()
size_t length
std::variant< Lower, Cross, Upper > EventType
Definition: EventQueue.h:47
Definition: dart_vm.cc:33
static void Finish(Thread *thread)
Definition: bootstrap.cc:44
const char *const name
CAllocUniquePtr< char > CStringUniquePtr
Definition: utils.h:31
static constexpr const char * kNone
Definition: run_vm_tests.cc:43
pthread_t ThreadJoinId
static constexpr intptr_t kBlockSize
Definition: page.h:33
void(* callback_)(Dart_Handle)
constexpr intptr_t KB
Definition: globals.h:528
uintptr_t uword
Definition: globals.h:501
static void Free(FreeList *free_list, uword address, intptr_t size, bool is_protected)
pthread_t ThreadId
COMPILE_ASSERT(kUnreachableReference==WeakTable::kNoValue)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
void Reset(SkPath *path)
Definition: path_ops.cc:40
TSize< Scalar > Size
Definition: size.h:137
static SkString fmt(SkColor4f c)
Definition: p3.cpp:43
bool EMSCRIPTEN_KEEPALIVE IsEmpty(const SkPath &path)
#define PRINTF_ATTRIBUTE(string_index, first_to_check)
Definition: globals.h:697
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:581
static DecodeResult decode(std::string path)
Definition: png_codec.cpp:124
const uintptr_t id
#define OFFSET_OF(type, field)
Definition: globals.h:138