| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include "vm/globals.h" |
| #if defined(DART_HOST_OS_FUCHSIA) && defined(SUPPORT_TIMELINE) |
| #include <lib/trace-engine/context.h> |
| #include <lib/trace-engine/instrumentation.h> |
| #include <zircon/syscalls.h> |
| |
| #include "platform/utils.h" |
| #include "vm/object.h" |
| #include "vm/timeline.h" |
| |
| namespace dart { |
| |
| void TimelineEventFuchsiaRecorder::OnEvent(TimelineEvent* event) { |
| if (event == NULL) { |
| return; |
| } |
| TimelineStream* stream = event->stream_; |
| trace_string_ref_t category; |
| trace_context_t* context = trace_acquire_context_for_category_cached( |
| stream->fuchsia_name(), stream->trace_site(), &category); |
| if (context == NULL) { |
| return; |
| } |
| |
| trace_string_ref_t name; |
| if (event->owns_label()) { |
| // If the event owns the name, then the name will be deallocated, so |
| // instruct the system trace to make a copy. |
| name = trace_context_make_registered_string_copy( |
| context, event->label(), strlen(event->label())); |
| } else { |
| // If the event doesn't own the name, then it is a string literal, and |
| // the system trace can use the pointer and not a copy. |
| name = trace_context_make_registered_string_literal( |
| context, event->label()); |
| } |
| |
| trace_thread_ref_t thread; |
| trace_context_register_current_thread(context, &thread); |
| |
| trace_arg_t args[TRACE_MAX_ARGS]; |
| const intptr_t num_args = Utils::Minimum( |
| event->arguments_length(), static_cast<intptr_t>(TRACE_MAX_ARGS)); |
| |
| for (intptr_t i = 0; i < num_args; i++) { |
| const char* name = event->arguments()[i].name; |
| const char* value = event->arguments()[i].value; |
| trace_string_ref_t arg_name = |
| trace_context_make_registered_string_literal(context, name); |
| trace_string_ref_t arg_value = |
| trace_make_inline_string_ref(value, strlen(value)); |
| args[i] = trace_make_arg(arg_name, trace_make_string_arg_value(arg_value)); |
| } |
| |
| const uint64_t time_scale = zx_ticks_per_second() / kMicrosecondsPerSecond; |
| const uint64_t start_time = event->LowTime() * time_scale; |
| const uint64_t end_time = event->HighTime() * time_scale; |
| |
| // TODO(zra): The functions below emit Dart's timeline events all as category |
| // "dart". Instead, we could have finer-grained categories that make use of |
| // the name of the timeline stream, e.g. "VM", "GC", etc. |
| switch (event->event_type()) { |
| case TimelineEvent::kBegin: |
| trace_context_write_duration_begin_event_record( |
| context, start_time, &thread, &category, &name, args, num_args); |
| break; |
| case TimelineEvent::kEnd: |
| trace_context_write_duration_end_event_record( |
| context, start_time, &thread, &category, &name, args, num_args); |
| break; |
| case TimelineEvent::kInstant: |
| trace_context_write_instant_event_record( |
| context, start_time, &thread, &category, &name, TRACE_SCOPE_THREAD, |
| args, num_args); |
| break; |
| case TimelineEvent::kAsyncBegin: |
| trace_context_write_async_begin_event_record( |
| context, start_time, &thread, &category, &name, event->AsyncId(), |
| args, num_args); |
| break; |
| case TimelineEvent::kAsyncEnd: |
| trace_context_write_async_end_event_record( |
| context, end_time, &thread, &category, &name, event->AsyncId(), args, |
| num_args); |
| break; |
| case TimelineEvent::kAsyncInstant: |
| trace_context_write_async_instant_event_record( |
| context, start_time, &thread, &category, &name, event->AsyncId(), |
| args, num_args); |
| break; |
| case TimelineEvent::kDuration: |
| trace_context_write_duration_event_record(context, start_time, end_time, |
| &thread, &category, &name, args, |
| num_args); |
| break; |
| case TimelineEvent::kFlowBegin: |
| trace_context_write_flow_begin_event_record( |
| context, start_time, &thread, &category, &name, event->AsyncId(), |
| args, num_args); |
| break; |
| case TimelineEvent::kFlowStep: |
| trace_context_write_flow_step_event_record( |
| context, start_time, &thread, &category, &name, event->AsyncId(), |
| args, num_args); |
| break; |
| case TimelineEvent::kFlowEnd: |
| trace_context_write_flow_end_event_record( |
| context, start_time, &thread, &category, &name, event->AsyncId(), |
| args, num_args); |
| break; |
| default: |
| // TODO(zra): Figure out what to do with kCounter and kMetadata. |
| break; |
| } |
| trace_release_context(context); |
| } |
| |
| } // namespace dart |
| |
| #endif // defined(DART_HOST_OS_FUCHSIA) && defined(SUPPORT_TIMELINE) |