1// Copyright 2016 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/trace_event/common/trace_event_common.h"
6#include "include/libplatform/v8-tracing.h"
7#include "include/v8-platform.h"
8#include "src/base/platform/platform.h"
9#include "src/base/platform/time.h"
10#include "src/base/platform/wrappers.h"
11
12namespace v8 {
13namespace platform {
14namespace tracing {
15
16// We perform checks for nullptr strings since it is possible that a string arg
17// value is nullptr.
18V8_INLINE static size_t GetAllocLength(const char* str) {
19  return str ? strlen(str) + 1 : 0;
20}
21
22// Copies |*member| into |*buffer|, sets |*member| to point to this new
23// location, and then advances |*buffer| by the amount written.
24V8_INLINE static void CopyTraceObjectParameter(char** buffer,
25                                               const char** member) {
26  if (*member == nullptr) return;
27  size_t length = strlen(*member) + 1;
28  memcpy(*buffer, *member, length);
29  *member = *buffer;
30  *buffer += length;
31}
32
33void TraceObject::Initialize(
34    char phase, const uint8_t* category_enabled_flag, const char* name,
35    const char* scope, uint64_t id, uint64_t bind_id, int num_args,
36    const char** arg_names, const uint8_t* arg_types,
37    const uint64_t* arg_values,
38    std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
39    unsigned int flags, int64_t timestamp, int64_t cpu_timestamp) {
40  pid_ = base::OS::GetCurrentProcessId();
41  tid_ = base::OS::GetCurrentThreadId();
42  phase_ = phase;
43  category_enabled_flag_ = category_enabled_flag;
44  name_ = name;
45  scope_ = scope;
46  id_ = id;
47  bind_id_ = bind_id;
48  flags_ = flags;
49  ts_ = timestamp;
50  tts_ = cpu_timestamp;
51  duration_ = 0;
52  cpu_duration_ = 0;
53
54  // Clamp num_args since it may have been set by a third-party library.
55  num_args_ = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
56  for (int i = 0; i < num_args_; ++i) {
57    arg_names_[i] = arg_names[i];
58    arg_values_[i].as_uint = arg_values[i];
59    arg_types_[i] = arg_types[i];
60    if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE)
61      arg_convertables_[i] = std::move(arg_convertables[i]);
62  }
63
64  bool copy = !!(flags & TRACE_EVENT_FLAG_COPY);
65  // Allocate a long string to fit all string copies.
66  size_t alloc_size = 0;
67  if (copy) {
68    alloc_size += GetAllocLength(name) + GetAllocLength(scope);
69    for (int i = 0; i < num_args_; ++i) {
70      alloc_size += GetAllocLength(arg_names_[i]);
71      if (arg_types_[i] == TRACE_VALUE_TYPE_STRING)
72        arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING;
73    }
74  }
75
76  bool arg_is_copy[kTraceMaxNumArgs];
77  for (int i = 0; i < num_args_; ++i) {
78    // We only take a copy of arg_vals if they are of type COPY_STRING.
79    arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING);
80    if (arg_is_copy[i]) alloc_size += GetAllocLength(arg_values_[i].as_string);
81  }
82
83  if (alloc_size) {
84    // Since TraceObject can be initialized multiple times, we might need
85    // to free old memory.
86    delete[] parameter_copy_storage_;
87    char* ptr = parameter_copy_storage_ = new char[alloc_size];
88    if (copy) {
89      CopyTraceObjectParameter(&ptr, &name_);
90      CopyTraceObjectParameter(&ptr, &scope_);
91      for (int i = 0; i < num_args_; ++i) {
92        CopyTraceObjectParameter(&ptr, &arg_names_[i]);
93      }
94    }
95    for (int i = 0; i < num_args_; ++i) {
96      if (arg_is_copy[i]) {
97        CopyTraceObjectParameter(&ptr, &arg_values_[i].as_string);
98      }
99    }
100  }
101}
102
103TraceObject::~TraceObject() { delete[] parameter_copy_storage_; }
104
105void TraceObject::UpdateDuration(int64_t timestamp, int64_t cpu_timestamp) {
106  duration_ = timestamp - ts_;
107  cpu_duration_ = cpu_timestamp - tts_;
108}
109
110void TraceObject::InitializeForTesting(
111    char phase, const uint8_t* category_enabled_flag, const char* name,
112    const char* scope, uint64_t id, uint64_t bind_id, int num_args,
113    const char** arg_names, const uint8_t* arg_types,
114    const uint64_t* arg_values,
115    std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
116    unsigned int flags, int pid, int tid, int64_t ts, int64_t tts,
117    uint64_t duration, uint64_t cpu_duration) {
118  pid_ = pid;
119  tid_ = tid;
120  phase_ = phase;
121  category_enabled_flag_ = category_enabled_flag;
122  name_ = name;
123  scope_ = scope;
124  id_ = id;
125  bind_id_ = bind_id;
126  num_args_ = num_args;
127  flags_ = flags;
128  ts_ = ts;
129  tts_ = tts;
130  duration_ = duration;
131  cpu_duration_ = cpu_duration;
132}
133
134}  // namespace tracing
135}  // namespace platform
136}  // namespace v8
137