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