// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/libplatform/v8-tracing.h"
#include "base/trace_event/common/trace_event_common.h"
#include "include/v8-platform.h"
#include "src/base/platform/platform.h"
#include "src/base/platform/time.h"
namespace v8 {
namespace platform {
namespace tracing {
// We perform checks for NULL strings since it is possible that a string arg
// value is NULL.
V8_INLINE static size_t GetAllocLength(const char* str) {
return str ? strlen(str) + 1 : 0;
}
// Copies |*member| into |*buffer|, sets |*member| to point to this new
// location, and then advances |*buffer| by the amount written.
V8_INLINE static void CopyTraceObjectParameter(char** buffer,
const char** member) {
if (*member) {
size_t length = strlen(*member) + 1;
strncpy(*buffer, *member, length);
*member = *buffer;
*buffer += length;
}
}
void TraceObject::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) {
pid_ = base::OS::GetCurrentProcessId();
tid_ = base::OS::GetCurrentThreadId();
phase_ = phase;
category_enabled_flag_ = category_enabled_flag;
name_ = name;
scope_ = scope;
id_ = id;
bind_id_ = bind_id;
flags_ = flags;
ts_ = base::TimeTicks::HighResolutionNow().ToInternalValue();
tts_ = base::ThreadTicks::Now().ToInternalValue();
duration_ = 0;
cpu_duration_ = 0;
// Clamp num_args since it may have been set by a third-party library.
num_args_ = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
for (int i = 0; i < num_args_; ++i) {
arg_names_[i] = arg_names[i];
arg_values_[i].as_uint = arg_values[i];
arg_types_[i] = arg_types[i];
if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE)
arg_convertables_[i] = std::move(arg_convertables[i]);
}
bool copy = !!(flags & TRACE_EVENT_FLAG_COPY);
// Allocate a long string to fit all string copies.
size_t alloc_size = 0;
if (copy) {
alloc_size += GetAllocLength(name) + GetAllocLength(scope);
for (int i = 0; i < num_args_; ++i) {
alloc_size += GetAllocLength(arg_names_[i]);
if (arg_types_[i] == TRACE_VALUE_TYPE_STRING)
arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING;
}
}
bool arg_is_copy[kTraceMaxNumArgs];
for (int i = 0; i < num_args_; ++i) {
// We only take a copy of arg_vals if they are of type COPY_STRING.
arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING);
if (arg_is_copy[i]) alloc_size += GetAllocLength(arg_values_[i].as_string);
}
if (alloc_size) {
// Since TraceObject can be initialized multiple times, we might need
// to free old memory.
delete[] parameter_copy_storage_;
char* ptr = parameter_copy_storage_ = new char[alloc_size];
if (copy) {
CopyTraceObjectParameter(&ptr, &name_);
CopyTraceObjectParameter(&ptr, &scope_);
for (int i = 0; i < num_args_; ++i) {
CopyTraceObjectParameter(&ptr, &arg_names_[i]);
}
}
for (int i = 0; i < num_args_; ++i) {
if (arg_is_copy[i]) {
CopyTraceObjectParameter(&ptr, &arg_values_[i].as_string);
}
}
}
}
TraceObject::~TraceObject() { delete[] parameter_copy_storage_; }
void TraceObject::UpdateDuration() {
duration_ = base::TimeTicks::HighResolutionNow().ToInternalValue() - ts_;
cpu_duration_ = base::ThreadTicks::Now().ToInternalValue() - tts_;
}
void TraceObject::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) {
pid_ = pid;
tid_ = tid;
phase_ = phase;
category_enabled_flag_ = category_enabled_flag;
name_ = name;
scope_ = scope;
id_ = id;
bind_id_ = bind_id;
num_args_ = num_args;
flags_ = flags;
ts_ = ts;
tts_ = tts;
duration_ = duration;
cpu_duration_ = cpu_duration;
}
} // namespace tracing
} // namespace platform
} // namespace v8