1 | // Copyright (c) 2017, 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 | #include "vm/globals.h" |
6 | #if defined(HOST_OS_FUCHSIA) && defined(SUPPORT_TIMELINE) |
7 | #include <lib/trace-engine/context.h> |
8 | #include <lib/trace-engine/instrumentation.h> |
9 | #include <zircon/syscalls.h> |
10 | |
11 | #include "platform/utils.h" |
12 | #include "vm/object.h" |
13 | #include "vm/timeline.h" |
14 | |
15 | namespace dart { |
16 | |
17 | void TimelineEventFuchsiaRecorder::OnEvent(TimelineEvent* event) { |
18 | if (event == NULL) { |
19 | return; |
20 | } |
21 | TimelineStream* stream = event->stream_; |
22 | trace_string_ref_t category; |
23 | trace_context_t* context = trace_acquire_context_for_category_cached( |
24 | stream->fuchsia_name(), stream->trace_site(), &category); |
25 | if (context == NULL) { |
26 | return; |
27 | } |
28 | |
29 | trace_string_ref_t name; |
30 | if (event->owns_label()) { |
31 | // If the event owns the name, then the name will be deallocated, so |
32 | // instruct the system trace to make a copy. |
33 | name = trace_context_make_registered_string_copy( |
34 | context, event->label(), strlen(event->label())); |
35 | } else { |
36 | // If the event doesn't own the name, then it is a string literal, and |
37 | // the system trace can use the pointer and not a copy. |
38 | name = trace_context_make_registered_string_literal( |
39 | context, event->label()); |
40 | } |
41 | |
42 | trace_thread_ref_t thread; |
43 | trace_context_register_current_thread(context, &thread); |
44 | |
45 | trace_arg_t args[TRACE_MAX_ARGS]; |
46 | const intptr_t num_args = Utils::Minimum( |
47 | event->arguments_length(), static_cast<intptr_t>(TRACE_MAX_ARGS)); |
48 | |
49 | for (intptr_t i = 0; i < num_args; i++) { |
50 | const char* name = event->arguments()[i].name; |
51 | const char* value = event->arguments()[i].value; |
52 | trace_string_ref_t arg_name = |
53 | trace_context_make_registered_string_literal(context, name); |
54 | trace_string_ref_t arg_value = |
55 | trace_make_inline_string_ref(value, strlen(value)); |
56 | args[i] = trace_make_arg(arg_name, trace_make_string_arg_value(arg_value)); |
57 | } |
58 | |
59 | const uint64_t time_scale = zx_ticks_per_second() / kMicrosecondsPerSecond; |
60 | const uint64_t start_time = event->LowTime() * time_scale; |
61 | const uint64_t end_time = event->HighTime() * time_scale; |
62 | |
63 | // TODO(zra): The functions below emit Dart's timeline events all as category |
64 | // "dart". Instead, we could have finer-grained categories that make use of |
65 | // the name of the timeline stream, e.g. "VM", "GC", etc. |
66 | switch (event->event_type()) { |
67 | case TimelineEvent::kBegin: |
68 | trace_context_write_duration_begin_event_record( |
69 | context, start_time, &thread, &category, &name, args, num_args); |
70 | break; |
71 | case TimelineEvent::kEnd: |
72 | trace_context_write_duration_end_event_record( |
73 | context, start_time, &thread, &category, &name, args, num_args); |
74 | break; |
75 | case TimelineEvent::kInstant: |
76 | trace_context_write_instant_event_record( |
77 | context, start_time, &thread, &category, &name, TRACE_SCOPE_THREAD, |
78 | args, num_args); |
79 | break; |
80 | case TimelineEvent::kAsyncBegin: |
81 | trace_context_write_async_begin_event_record( |
82 | context, start_time, &thread, &category, &name, event->AsyncId(), |
83 | args, num_args); |
84 | break; |
85 | case TimelineEvent::kAsyncEnd: |
86 | trace_context_write_async_end_event_record( |
87 | context, end_time, &thread, &category, &name, event->AsyncId(), args, |
88 | num_args); |
89 | break; |
90 | case TimelineEvent::kAsyncInstant: |
91 | trace_context_write_async_instant_event_record( |
92 | context, start_time, &thread, &category, &name, event->AsyncId(), |
93 | args, num_args); |
94 | break; |
95 | case TimelineEvent::kDuration: |
96 | trace_context_write_duration_event_record(context, start_time, end_time, |
97 | &thread, &category, &name, args, |
98 | num_args); |
99 | break; |
100 | case TimelineEvent::kFlowBegin: |
101 | trace_context_write_flow_begin_event_record( |
102 | context, start_time, &thread, &category, &name, event->AsyncId(), |
103 | args, num_args); |
104 | break; |
105 | case TimelineEvent::kFlowStep: |
106 | trace_context_write_flow_step_event_record( |
107 | context, start_time, &thread, &category, &name, event->AsyncId(), |
108 | args, num_args); |
109 | break; |
110 | case TimelineEvent::kFlowEnd: |
111 | trace_context_write_flow_end_event_record( |
112 | context, start_time, &thread, &category, &name, event->AsyncId(), |
113 | args, num_args); |
114 | break; |
115 | default: |
116 | // TODO(zra): Figure out what to do with kCounter and kMetadata. |
117 | break; |
118 | } |
119 | trace_release_context(context); |
120 | } |
121 | |
122 | } // namespace dart |
123 | |
124 | #endif // defined(HOST_OS_FUCHSIA) && defined(SUPPORT_TIMELINE) |
125 | |