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
12 namespace v8 {
13 namespace platform {
14 namespace tracing {
15
16 // We perform checks for nullptr strings since it is possible that a string arg
17 // value is nullptr.
GetAllocLength(const char * str)18 V8_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.
CopyTraceObjectParameter(char ** buffer,const char ** member)24 V8_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
Initialize(char phase,const uint8_t * category_enabled_flag,const char * name,const char * scope,uint64_t id,uint64_t bind_id,int num_args,const char ** arg_names,const uint8_t * arg_types,const uint64_t * arg_values,std::unique_ptr<v8::ConvertableToTraceFormat> * arg_convertables,unsigned int flags,int64_t timestamp,int64_t cpu_timestamp)33 void 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
~TraceObject()103 TraceObject::~TraceObject() { delete[] parameter_copy_storage_; }
104
UpdateDuration(int64_t timestamp,int64_t cpu_timestamp)105 void TraceObject::UpdateDuration(int64_t timestamp, int64_t cpu_timestamp) {
106 duration_ = timestamp - ts_;
107 cpu_duration_ = cpu_timestamp - tts_;
108 }
109
InitializeForTesting(char phase,const uint8_t * category_enabled_flag,const char * name,const char * scope,uint64_t id,uint64_t bind_id,int num_args,const char ** arg_names,const uint8_t * arg_types,const uint64_t * arg_values,std::unique_ptr<v8::ConvertableToTraceFormat> * arg_convertables,unsigned int flags,int pid,int tid,int64_t ts,int64_t tts,uint64_t duration,uint64_t cpu_duration)110 void 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