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