11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "base/trace_event/common/trace_event_common.h"
61cb0ef41Sopenharmony_ci#include "include/libplatform/v8-tracing.h"
71cb0ef41Sopenharmony_ci#include "include/v8-platform.h"
81cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h"
91cb0ef41Sopenharmony_ci#include "src/base/platform/time.h"
101cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace v8 {
131cb0ef41Sopenharmony_cinamespace platform {
141cb0ef41Sopenharmony_cinamespace tracing {
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci// We perform checks for nullptr strings since it is possible that a string arg
171cb0ef41Sopenharmony_ci// value is nullptr.
181cb0ef41Sopenharmony_ciV8_INLINE static size_t GetAllocLength(const char* str) {
191cb0ef41Sopenharmony_ci  return str ? strlen(str) + 1 : 0;
201cb0ef41Sopenharmony_ci}
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci// Copies |*member| into |*buffer|, sets |*member| to point to this new
231cb0ef41Sopenharmony_ci// location, and then advances |*buffer| by the amount written.
241cb0ef41Sopenharmony_ciV8_INLINE static void CopyTraceObjectParameter(char** buffer,
251cb0ef41Sopenharmony_ci                                               const char** member) {
261cb0ef41Sopenharmony_ci  if (*member == nullptr) return;
271cb0ef41Sopenharmony_ci  size_t length = strlen(*member) + 1;
281cb0ef41Sopenharmony_ci  memcpy(*buffer, *member, length);
291cb0ef41Sopenharmony_ci  *member = *buffer;
301cb0ef41Sopenharmony_ci  *buffer += length;
311cb0ef41Sopenharmony_ci}
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_civoid TraceObject::Initialize(
341cb0ef41Sopenharmony_ci    char phase, const uint8_t* category_enabled_flag, const char* name,
351cb0ef41Sopenharmony_ci    const char* scope, uint64_t id, uint64_t bind_id, int num_args,
361cb0ef41Sopenharmony_ci    const char** arg_names, const uint8_t* arg_types,
371cb0ef41Sopenharmony_ci    const uint64_t* arg_values,
381cb0ef41Sopenharmony_ci    std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
391cb0ef41Sopenharmony_ci    unsigned int flags, int64_t timestamp, int64_t cpu_timestamp) {
401cb0ef41Sopenharmony_ci  pid_ = base::OS::GetCurrentProcessId();
411cb0ef41Sopenharmony_ci  tid_ = base::OS::GetCurrentThreadId();
421cb0ef41Sopenharmony_ci  phase_ = phase;
431cb0ef41Sopenharmony_ci  category_enabled_flag_ = category_enabled_flag;
441cb0ef41Sopenharmony_ci  name_ = name;
451cb0ef41Sopenharmony_ci  scope_ = scope;
461cb0ef41Sopenharmony_ci  id_ = id;
471cb0ef41Sopenharmony_ci  bind_id_ = bind_id;
481cb0ef41Sopenharmony_ci  flags_ = flags;
491cb0ef41Sopenharmony_ci  ts_ = timestamp;
501cb0ef41Sopenharmony_ci  tts_ = cpu_timestamp;
511cb0ef41Sopenharmony_ci  duration_ = 0;
521cb0ef41Sopenharmony_ci  cpu_duration_ = 0;
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  // Clamp num_args since it may have been set by a third-party library.
551cb0ef41Sopenharmony_ci  num_args_ = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
561cb0ef41Sopenharmony_ci  for (int i = 0; i < num_args_; ++i) {
571cb0ef41Sopenharmony_ci    arg_names_[i] = arg_names[i];
581cb0ef41Sopenharmony_ci    arg_values_[i].as_uint = arg_values[i];
591cb0ef41Sopenharmony_ci    arg_types_[i] = arg_types[i];
601cb0ef41Sopenharmony_ci    if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE)
611cb0ef41Sopenharmony_ci      arg_convertables_[i] = std::move(arg_convertables[i]);
621cb0ef41Sopenharmony_ci  }
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  bool copy = !!(flags & TRACE_EVENT_FLAG_COPY);
651cb0ef41Sopenharmony_ci  // Allocate a long string to fit all string copies.
661cb0ef41Sopenharmony_ci  size_t alloc_size = 0;
671cb0ef41Sopenharmony_ci  if (copy) {
681cb0ef41Sopenharmony_ci    alloc_size += GetAllocLength(name) + GetAllocLength(scope);
691cb0ef41Sopenharmony_ci    for (int i = 0; i < num_args_; ++i) {
701cb0ef41Sopenharmony_ci      alloc_size += GetAllocLength(arg_names_[i]);
711cb0ef41Sopenharmony_ci      if (arg_types_[i] == TRACE_VALUE_TYPE_STRING)
721cb0ef41Sopenharmony_ci        arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING;
731cb0ef41Sopenharmony_ci    }
741cb0ef41Sopenharmony_ci  }
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  bool arg_is_copy[kTraceMaxNumArgs];
771cb0ef41Sopenharmony_ci  for (int i = 0; i < num_args_; ++i) {
781cb0ef41Sopenharmony_ci    // We only take a copy of arg_vals if they are of type COPY_STRING.
791cb0ef41Sopenharmony_ci    arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING);
801cb0ef41Sopenharmony_ci    if (arg_is_copy[i]) alloc_size += GetAllocLength(arg_values_[i].as_string);
811cb0ef41Sopenharmony_ci  }
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  if (alloc_size) {
841cb0ef41Sopenharmony_ci    // Since TraceObject can be initialized multiple times, we might need
851cb0ef41Sopenharmony_ci    // to free old memory.
861cb0ef41Sopenharmony_ci    delete[] parameter_copy_storage_;
871cb0ef41Sopenharmony_ci    char* ptr = parameter_copy_storage_ = new char[alloc_size];
881cb0ef41Sopenharmony_ci    if (copy) {
891cb0ef41Sopenharmony_ci      CopyTraceObjectParameter(&ptr, &name_);
901cb0ef41Sopenharmony_ci      CopyTraceObjectParameter(&ptr, &scope_);
911cb0ef41Sopenharmony_ci      for (int i = 0; i < num_args_; ++i) {
921cb0ef41Sopenharmony_ci        CopyTraceObjectParameter(&ptr, &arg_names_[i]);
931cb0ef41Sopenharmony_ci      }
941cb0ef41Sopenharmony_ci    }
951cb0ef41Sopenharmony_ci    for (int i = 0; i < num_args_; ++i) {
961cb0ef41Sopenharmony_ci      if (arg_is_copy[i]) {
971cb0ef41Sopenharmony_ci        CopyTraceObjectParameter(&ptr, &arg_values_[i].as_string);
981cb0ef41Sopenharmony_ci      }
991cb0ef41Sopenharmony_ci    }
1001cb0ef41Sopenharmony_ci  }
1011cb0ef41Sopenharmony_ci}
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ciTraceObject::~TraceObject() { delete[] parameter_copy_storage_; }
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_civoid TraceObject::UpdateDuration(int64_t timestamp, int64_t cpu_timestamp) {
1061cb0ef41Sopenharmony_ci  duration_ = timestamp - ts_;
1071cb0ef41Sopenharmony_ci  cpu_duration_ = cpu_timestamp - tts_;
1081cb0ef41Sopenharmony_ci}
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_civoid TraceObject::InitializeForTesting(
1111cb0ef41Sopenharmony_ci    char phase, const uint8_t* category_enabled_flag, const char* name,
1121cb0ef41Sopenharmony_ci    const char* scope, uint64_t id, uint64_t bind_id, int num_args,
1131cb0ef41Sopenharmony_ci    const char** arg_names, const uint8_t* arg_types,
1141cb0ef41Sopenharmony_ci    const uint64_t* arg_values,
1151cb0ef41Sopenharmony_ci    std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
1161cb0ef41Sopenharmony_ci    unsigned int flags, int pid, int tid, int64_t ts, int64_t tts,
1171cb0ef41Sopenharmony_ci    uint64_t duration, uint64_t cpu_duration) {
1181cb0ef41Sopenharmony_ci  pid_ = pid;
1191cb0ef41Sopenharmony_ci  tid_ = tid;
1201cb0ef41Sopenharmony_ci  phase_ = phase;
1211cb0ef41Sopenharmony_ci  category_enabled_flag_ = category_enabled_flag;
1221cb0ef41Sopenharmony_ci  name_ = name;
1231cb0ef41Sopenharmony_ci  scope_ = scope;
1241cb0ef41Sopenharmony_ci  id_ = id;
1251cb0ef41Sopenharmony_ci  bind_id_ = bind_id;
1261cb0ef41Sopenharmony_ci  num_args_ = num_args;
1271cb0ef41Sopenharmony_ci  flags_ = flags;
1281cb0ef41Sopenharmony_ci  ts_ = ts;
1291cb0ef41Sopenharmony_ci  tts_ = tts;
1301cb0ef41Sopenharmony_ci  duration_ = duration;
1311cb0ef41Sopenharmony_ci  cpu_duration_ = cpu_duration;
1321cb0ef41Sopenharmony_ci}
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci}  // namespace tracing
1351cb0ef41Sopenharmony_ci}  // namespace platform
1361cb0ef41Sopenharmony_ci}  // namespace v8
137