Reland "[VM/Timeline] Make timestamp1_or_id variables more understandable"

Relanding without changes because the cbuild failure was unrelated.

TEST=Checked that duration events still looked correct in traces written
by the Perfetto file recorder. Checked that events still looked correct
in traces recorded to the MacOS recorder.

This is a reland of commit 354e1d22cb1cd4cc6b8f7beb60d690b5351a169d

Original change's description:
> [VM/Timeline] Make timestamp1_or_id variables more understandable
>
> This CL improves documentation, and renames fields/methods to make it
> more understandable that timestamp1 and id are stored in the same field
> of dart::TimelineEvent (because the event types that need to store
> timestamp1 are disjoint from the ones that need to store id).
>
> TEST=Checked that duration events still looked correct in traces written
> by the Perfetto file recorder. Checked that events still looked correct
> in traces recorded to the MacOS recorder.
>
> Change-Id: I25ff1f4c6cc432f035ac2be99fa7f162290ea77f
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/305880
> Reviewed-by: Ben Konyi <bkonyi@google.com>
> Commit-Queue: Derek Xu <derekx@google.com>

Change-Id: I28c0c3af9869900cc8bb2b3b416904a231d143e0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/306301
Reviewed-by: Ben Konyi <bkonyi@google.com>
Commit-Queue: Derek Xu <derekx@google.com>
diff --git a/runtime/include/dart_tools_api.h b/runtime/include/dart_tools_api.h
index aab2fa5..0197f33 100644
--- a/runtime/include/dart_tools_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -359,8 +359,17 @@
  * \param label The name of the event. Its lifetime must extend at least until
  *     Dart_Cleanup.
  * \param timestamp0 The first timestamp of the event.
- * \param timestamp1_or_async_id The second timestamp of the event or
- *     the async id.
+ * \param timestamp1_or_id When reporting an event of type
+ *     |Dart_Timeline_Event_Duration|, the second (end) timestamp of the event
+ *     should be passed through |timestamp1_or_id|. When reporting an event of
+ *     type |Dart_Timeline_Event_Async_Begin|, |Dart_Timeline_Event_Async_End|,
+ *     or |Dart_Timeline_Event_Async_Instant|, the async ID associated with the
+ *     event should be passed through |timestamp1_or_id|. When reporting an
+ *     event of type |Dart_Timeline_Event_Begin| or |Dart_Timeline_Event_End|,
+ *     the event ID associated with the event should be passed through
+ *     |timestamp1_or_id|. Note that this event ID will only be used by the
+ *     MacOS recorder. The argument to |timestamp1_or_id| will not be used when
+ *     reporting events of other types.
  * \param argument_count The number of argument names and values.
  * \param argument_names An array of names of the arguments. The lifetime of the
  *     names must extend at least until Dart_Cleanup. The array may be reclaimed
@@ -370,7 +379,7 @@
  */
 DART_EXPORT void Dart_TimelineEvent(const char* label,
                                     int64_t timestamp0,
-                                    int64_t timestamp1_or_async_id,
+                                    int64_t timestamp1_or_id,
                                     Dart_Timeline_Event_Type type,
                                     intptr_t argument_count,
                                     const char** argument_names,
@@ -403,9 +412,12 @@
    */
   int64_t timestamp0;
 
-  /* For a duration event, this is the end time. For an async event, this is the
-   * async id. */
-  int64_t timestamp1_or_async_id;
+  /**
+   * For a duration event, this is the end time. For an async event, this is the
+   * async ID. For a begin or end event, this is the event ID (which is only
+   * referenced by the MacOS recorder).
+   */
+  int64_t timestamp1_or_id;
 
   /* The current isolate of the event, as if by Dart_GetMainPortId, or
    * ILLEGAL_PORT if the event had no current isolate. */
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 7c42f26..bdd37b1 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -6419,7 +6419,7 @@
 
 DART_EXPORT void Dart_TimelineEvent(const char* label,
                                     int64_t timestamp0,
-                                    int64_t timestamp1_or_async_id,
+                                    int64_t timestamp1_or_id,
                                     Dart_Timeline_Event_Type type,
                                     intptr_t argument_count,
                                     const char** argument_names,
@@ -6443,37 +6443,37 @@
         // TODO(derekx): Dart_TimelineEvent() needs to be updated so that arrows
         // corresponding to flow events reported by embedders get included in
         // Perfetto traces.
-        event->Begin(label, timestamp1_or_async_id, timestamp0);
+        event->Begin(label, timestamp1_or_id, timestamp0);
         break;
       case Dart_Timeline_Event_End:
-        event->End(label, timestamp1_or_async_id, timestamp0);
+        event->End(label, timestamp1_or_id, timestamp0);
         break;
       case Dart_Timeline_Event_Instant:
         event->Instant(label, timestamp0);
         break;
       case Dart_Timeline_Event_Duration:
-        event->Duration(label, timestamp0, timestamp1_or_async_id);
+        event->Duration(label, timestamp0, timestamp1_or_id);
         break;
       case Dart_Timeline_Event_Async_Begin:
-        event->AsyncBegin(label, timestamp1_or_async_id, timestamp0);
+        event->AsyncBegin(label, timestamp1_or_id, timestamp0);
         break;
       case Dart_Timeline_Event_Async_End:
-        event->AsyncEnd(label, timestamp1_or_async_id, timestamp0);
+        event->AsyncEnd(label, timestamp1_or_id, timestamp0);
         break;
       case Dart_Timeline_Event_Async_Instant:
-        event->AsyncInstant(label, timestamp1_or_async_id, timestamp0);
+        event->AsyncInstant(label, timestamp1_or_id, timestamp0);
         break;
       case Dart_Timeline_Event_Counter:
         event->Counter(label, timestamp0);
         break;
       case Dart_Timeline_Event_Flow_Begin:
-        event->FlowBegin(label, timestamp1_or_async_id, timestamp0);
+        event->FlowBegin(label, timestamp0);
         break;
       case Dart_Timeline_Event_Flow_Step:
-        event->FlowStep(label, timestamp1_or_async_id, timestamp0);
+        event->FlowStep(label, timestamp0);
         break;
       case Dart_Timeline_Event_Flow_End:
-        event->FlowEnd(label, timestamp1_or_async_id, timestamp0);
+        event->FlowEnd(label, timestamp0);
         break;
       default:
         FATAL("Unknown Dart_Timeline_Event_Type");
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 11ff657..7e53aea 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -10387,25 +10387,45 @@
   do {
     Dart_TimelineEvent("T1", 0, 1, Dart_Timeline_Event_Begin, 0, nullptr,
                        nullptr);
-    Dart_TimelineEvent("T1", 0, 9, Dart_Timeline_Event_End, 0, nullptr,
+    Dart_TimelineEvent("T1", 10, 1, Dart_Timeline_Event_End, 0, nullptr,
                        nullptr);
-    Dart_TimelineEvent("T2", 0, 1, Dart_Timeline_Event_Instant, 0, nullptr,
+
+    Dart_TimelineEvent("T2", 20, 2, Dart_Timeline_Event_Instant, 0, nullptr,
                        nullptr);
-    Dart_TimelineEvent("T3", 0, 2, Dart_Timeline_Event_Duration, 0, nullptr,
+
+    Dart_TimelineEvent("T3", 30, /*timestamp1=*/40,
+                       Dart_Timeline_Event_Duration, 0, nullptr, nullptr);
+
+    Dart_TimelineEvent("T4", 50, 4, Dart_Timeline_Event_Async_Begin, 0, nullptr,
                        nullptr);
-    Dart_TimelineEvent("T4", 0, 3, Dart_Timeline_Event_Async_Begin, 0, nullptr,
+    Dart_TimelineEvent("T4", 60, 4, Dart_Timeline_Event_Async_End, 0, nullptr,
                        nullptr);
-    Dart_TimelineEvent("T4", 9, 3, Dart_Timeline_Event_Async_End, 0, nullptr,
-                       nullptr);
-    Dart_TimelineEvent("T5", 1, 4, Dart_Timeline_Event_Async_Instant, 0,
+
+    Dart_TimelineEvent("T5", 70, 5, Dart_Timeline_Event_Async_Instant, 0,
                        nullptr, nullptr);
-    Dart_TimelineEvent("T7", 1, 4, Dart_Timeline_Event_Counter, 0, nullptr,
+
+    Dart_TimelineEvent("T6", 80, /*timestamp1_or_id=*/-1,
+                       Dart_Timeline_Event_Counter, 0, nullptr, nullptr);
+
+    Dart_TimelineEvent("T7", 90, 7, Dart_Timeline_Event_Begin, 0, nullptr,
                        nullptr);
-    Dart_TimelineEvent("T8", 1, 4, Dart_Timeline_Event_Flow_Begin, 0, nullptr,
+    Dart_TimelineEvent("F", 90, /*timestamp1_or_id=*/-1,
+                       Dart_Timeline_Event_Flow_Begin, 0, nullptr, nullptr);
+    Dart_TimelineEvent("T7", 100, 7, Dart_Timeline_Event_End, 0, nullptr,
                        nullptr);
-    Dart_TimelineEvent("T8", 1, 4, Dart_Timeline_Event_Flow_Step, 0, nullptr,
+
+    Dart_TimelineEvent("T8", 110, 8, Dart_Timeline_Event_Begin, 0, nullptr,
                        nullptr);
-    Dart_TimelineEvent("T8", 1, 4, Dart_Timeline_Event_Flow_End, 0, nullptr,
+    Dart_TimelineEvent("F", 110, /*timestamp1_or_id=*/-1,
+                       Dart_Timeline_Event_Flow_Step, 0, nullptr, nullptr);
+    Dart_TimelineEvent("T8", 120, 8, Dart_Timeline_Event_End, 0, nullptr,
+                       nullptr);
+
+    Dart_TimelineEvent("T9", 130, 9, Dart_Timeline_Event_Begin, 0, nullptr,
+                       nullptr);
+    Dart_TimelineEvent("F", 130, /*timestamp1_or_id=*/-1,
+                       Dart_Timeline_Event_Flow_End, 0, nullptr, nullptr);
+    Dart_TimelineEvent("T9", 140, 9, Dart_Timeline_Event_End, 0, nullptr,
                        nullptr);
   } while (true);
 }
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 1f63bef..419cc59 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -504,7 +504,7 @@
 
 TimelineEvent::TimelineEvent()
     : timestamp0_(0),
-      timestamp1_(0),
+      timestamp1_or_id_(0),
       flow_id_count_(0),
       flow_ids_(),
       state_(0),
@@ -540,7 +540,7 @@
   Init(kAsyncBegin, label);
   set_timestamp0(micros);
   // Overload timestamp1_ with the async_id.
-  set_timestamp1(async_id);
+  set_timestamp1_or_id(async_id);
 }
 
 void TimelineEvent::AsyncInstant(const char* label,
@@ -549,7 +549,7 @@
   Init(kAsyncInstant, label);
   set_timestamp0(micros);
   // Overload timestamp1_ with the async_id.
-  set_timestamp1(async_id);
+  set_timestamp1_or_id(async_id);
 }
 
 void TimelineEvent::AsyncEnd(const char* label,
@@ -558,7 +558,7 @@
   Init(kAsyncEnd, label);
   set_timestamp0(micros);
   // Overload timestamp1_ with the async_id.
-  set_timestamp1(async_id);
+  set_timestamp1_or_id(async_id);
 }
 
 void TimelineEvent::DurationBegin(const char* label, int64_t micros) {
@@ -566,11 +566,6 @@
   set_timestamp0(micros);
 }
 
-void TimelineEvent::DurationEnd(int64_t micros) {
-  ASSERT(timestamp1_ == 0);
-  set_timestamp1(micros);
-}
-
 void TimelineEvent::Instant(const char* label, int64_t micros) {
   Init(kInstant, label);
   set_timestamp0(micros);
@@ -581,7 +576,7 @@
                              int64_t end_micros) {
   Init(kDuration, label);
   set_timestamp0(start_micros);
-  set_timestamp1(end_micros);
+  set_timestamp1_or_id(end_micros);
 }
 
 void TimelineEvent::Begin(const char* label,
@@ -589,17 +584,17 @@
                           int64_t micros) {
   Init(kBegin, label);
   set_timestamp0(micros);
-  // Overload timestamp1_ with the task id. This is required for the MacOS
+  // Overload timestamp1_ with the event ID. This is required for the MacOS
   // recorder to work.
-  set_timestamp1(id);
+  set_timestamp1_or_id(id);
 }
 
 void TimelineEvent::End(const char* label, int64_t id, int64_t micros) {
   Init(kEnd, label);
   set_timestamp0(micros);
-  // Overload timestamp1_ with the task id. This is required for the MacOS
+  // Overload timestamp1_ with the event ID. This is required for the MacOS
   // recorder to work.
-  set_timestamp1(id);
+  set_timestamp1_or_id(id);
 }
 
 void TimelineEvent::Counter(const char* label, int64_t micros) {
@@ -608,30 +603,21 @@
 }
 
 void TimelineEvent::FlowBegin(const char* label,
-                              int64_t async_id,
                               int64_t micros) {
   Init(kFlowBegin, label);
   set_timestamp0(micros);
-  // Overload timestamp1_ with the async_id.
-  set_timestamp1(async_id);
 }
 
 void TimelineEvent::FlowStep(const char* label,
-                             int64_t async_id,
                              int64_t micros) {
   Init(kFlowStep, label);
   set_timestamp0(micros);
-  // Overload timestamp1_ with the async_id.
-  set_timestamp1(async_id);
 }
 
 void TimelineEvent::FlowEnd(const char* label,
-                            int64_t async_id,
                             int64_t micros) {
   Init(kFlowEnd, label);
   set_timestamp0(micros);
-  // Overload timestamp1_ with the async_id.
-  set_timestamp1(async_id);
 }
 
 void TimelineEvent::Metadata(const char* label, int64_t micros) {
@@ -668,7 +654,7 @@
   ASSERT(label != nullptr);
   state_ = 0;
   timestamp0_ = 0;
-  timestamp1_ = 0;
+  timestamp1_or_id_ = 0;
   flow_id_count_ = 0;
   flow_ids_.reset();
   OSThread* os_thread = OSThread::Current();
@@ -971,18 +957,19 @@
 
 int64_t TimelineEvent::HighTime() const {
   if (event_type() == kDuration) {
-    return timestamp1_;
+    return timestamp1_or_id_;
   } else {
     return timestamp0_;
   }
 }
 
 int64_t TimelineEvent::TimeDuration() const {
-  if (timestamp1_ == 0) {
+  ASSERT(event_type() == kDuration);
+  if (timestamp1_or_id_ == 0) {
     // This duration is still open, use current time as end.
     return OS::GetCurrentMonotonicMicrosForTimeline() - timestamp0_;
   }
-  return timestamp1_ - timestamp0_;
+  return timestamp1_or_id_ - timestamp0_;
 }
 
 bool TimelineEvent::HasIsolateId() const {
@@ -1926,7 +1913,7 @@
       return;
   }
   recorder_event.timestamp0 = event->timestamp0();
-  recorder_event.timestamp1_or_async_id = event->timestamp1();
+  recorder_event.timestamp1_or_id = event->timestamp1_or_id();
   recorder_event.isolate = event->isolate_id();
   recorder_event.isolate_group = event->isolate_group_id();
   recorder_event.isolate_data = event->isolate_data();
@@ -2438,13 +2425,13 @@
       event->End(name, id, start);
       break;
     case TimelineEvent::kFlowBegin:
-      event->FlowBegin(name, id, start);
+      event->FlowBegin(name, start);
       break;
     case TimelineEvent::kFlowStep:
-      event->FlowStep(name, id, start);
+      event->FlowStep(name, start);
       break;
     case TimelineEvent::kFlowEnd:
-      event->FlowEnd(name, id, start);
+      event->FlowEnd(name, start);
       break;
     case TimelineEvent::kInstant:
       event->Instant(name, start);
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index 6650599..10de947 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -364,7 +364,6 @@
   void DurationBegin(
       const char* label,
       int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
-  void DurationEnd(int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
 
   void Instant(const char* label,
                int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
@@ -383,13 +382,10 @@
                int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
 
   void FlowBegin(const char* label,
-                 int64_t async_id,
                  int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
   void FlowStep(const char* label,
-                int64_t async_id,
                 int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
   void FlowEnd(const char* label,
-               int64_t async_id,
                int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline());
 
   void Metadata(const char* label,
@@ -422,23 +418,26 @@
 
   TimelineStream* stream() const { return stream_; }
 
-  bool IsFinishedDuration() const {
-    return (event_type() == kDuration) && (timestamp1_ > timestamp0_);
-  }
-
   int64_t TimeOrigin() const { return timestamp0_; }
   int64_t Id() const {
-    ASSERT(event_type() != kDuration);
-    return timestamp1_;
+    ASSERT(event_type() == kBegin || event_type() == kEnd ||
+           event_type() == kAsyncBegin || event_type() == kAsyncEnd ||
+           event_type() == kAsyncInstant);
+    return timestamp1_or_id_;
   }
   int64_t TimeDuration() const;
+  void SetTimeEnd(int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline()) {
+    ASSERT(event_type() == kDuration);
+    ASSERT(timestamp1_or_id_ == 0);
+    set_timestamp1_or_id(micros);
+  }
   int64_t TimeEnd() const {
     ASSERT(IsFinishedDuration());
-    return timestamp1_;
+    return timestamp1_or_id_;
   }
 
   int64_t timestamp0() const { return timestamp0_; }
-  int64_t timestamp1() const { return timestamp1_; }
+  int64_t timestamp1_or_id() const { return timestamp1_or_id_; }
 
   void SetFlowIds(intptr_t flow_id_count,
                   std::unique_ptr<const int64_t[]>& flow_ids) {
@@ -562,9 +561,13 @@
     ASSERT(timestamp0_ == 0);
     timestamp0_ = value;
   }
-  void set_timestamp1(int64_t value) {
-    ASSERT(timestamp1_ == 0);
-    timestamp1_ = value;
+  void set_timestamp1_or_id(int64_t value) {
+    ASSERT(timestamp1_or_id_ == 0);
+    timestamp1_or_id_ = value;
+  }
+
+  bool IsFinishedDuration() const {
+    return (event_type() == kDuration) && (timestamp1_or_id_ > timestamp0_);
   }
 
   void set_pre_serialized_args(bool pre_serialized_args) {
@@ -586,7 +589,10 @@
   class OwnsLabelBit : public BitField<uword, bool, kOwnsLabelBit, 1> {};
 
   int64_t timestamp0_;
-  int64_t timestamp1_;
+  // For an event of type |kDuration|, this is the end time. For an event of
+  // type |kBegin| or |kEnd|, this is the event ID (which is only referenced by
+  // the MacOS recorder). For an async event, this is the async ID.
+  int64_t timestamp1_or_id_;
   intptr_t flow_id_count_;
   // This field is only used by the Perfetto recorders, because Perfetto's trace
   // format handles flow events by processing flow IDs attached to
@@ -1291,6 +1297,11 @@
 
 class DartTimelineEventHelpers : public AllStatic {
  public:
+  // When reporting an event of type |kAsyncBegin|, |kAsyncEnd|, or
+  // |kAsyncInstant|, the async ID associated with the event should be passed
+  // through |id|. When reporting an event of type |kBegin| or |kEnd|, the event
+  // ID associated with the event should be passed through |id|. Note that this
+  // event ID will only be used by the MacOS recorder.
   static void ReportTaskEvent(TimelineEvent* event,
                               int64_t id,
                               intptr_t flow_id_count,
diff --git a/runtime/vm/timeline_test.cc b/runtime/vm/timeline_test.cc
index 1050073..8d768ff 100644
--- a/runtime/vm/timeline_test.cc
+++ b/runtime/vm/timeline_test.cc
@@ -133,7 +133,7 @@
   event.DurationBegin("apple");
   // Measure the duration.
   int64_t current_duration = event.TimeDuration();
-  event.DurationEnd();
+  event.SetTimeEnd();
   // Verify that duration is larger.
   EXPECT_GE(event.TimeDuration(), current_duration);
 }
@@ -161,7 +161,7 @@
     // Check that dur key is present.
     EXPECT_SUBSTRING("\"dur\":", js.ToCString());
   }
-  event.DurationEnd();
+  event.SetTimeEnd();
 }
 
 #if defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX)
@@ -229,7 +229,7 @@
   event.SetNumArguments(2);
   event.CopyArgument(0, "arg1", "value1");
   event.CopyArgument(1, "arg2", "value2");
-  event.DurationEnd();
+  event.SetTimeEnd();
 }
 
 TEST_CASE(TimelineEventArgumentsPrintJSON) {
@@ -244,7 +244,7 @@
   event.SetNumArguments(2);
   event.CopyArgument(0, "arg1", "value1");
   event.CopyArgument(1, "arg2", "value2");
-  event.DurationEnd();
+  event.SetTimeEnd();
 
   {
     // Test printing to JSON.
@@ -303,7 +303,7 @@
   EXPECT_EQ(0, override.recorder()->CountFor(TimelineEvent::kDuration));
   event->DurationBegin("cabbage");
   EXPECT_EQ(0, override.recorder()->CountFor(TimelineEvent::kDuration));
-  event->DurationEnd();
+  event->SetTimeEnd();
   EXPECT_EQ(0, override.recorder()->CountFor(TimelineEvent::kDuration));
   event->Complete();
   EXPECT_EQ(1, override.recorder()->CountFor(TimelineEvent::kDuration));