Commit 70a7c754 authored by fmeawad's avatar fmeawad Committed by Commit bot

Implement tracing interface for v8

This is based on the Skia Implementation.

More on the project can be found here:
https://docs.google.com/a/chromium.org/document/d/1_4LAnInOB8tM_DLjptWiszRwa4qwiSsDzMkO4tU-Qes/edit#heading=h.p97rw6yt8o2j

The V8 Tracing platform will replace the isolate->event_logger().
But since the current embedders (namely chromium) currently use the isolate->event_logger, I made the default implementation (event-tracer) call into isolate->event_logger if an event_logger was set.
Once the embedders properly implement the interface (for example in chromium it would look like this: https://codereview.chromium.org/707273005/), the default implementation will be doing nothing.

Once the embedders side is fixed, we will change how V8 uses the tracing framework beyond the call from Logger:CallEventLogger. (which would also include a d8 implementation)

BUG=v8:4560
LOG=N

Review URL: https://codereview.chromium.org/988893003

Cr-Commit-Position: refs/heads/master@{#32959}
parent 9e8b7564
......@@ -595,6 +595,8 @@ source_set("v8_base") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
sources = [
# TODO(fmeawad): This needs to be updated to support standalone V8 builds.
"../base/trace_event/common/trace_event_common.h",
"include/v8-debug.h",
"include/v8-experimental.h",
"include/v8-platform.h",
......@@ -1247,6 +1249,8 @@ source_set("v8_base") {
"src/string-stream.h",
"src/strtod.cc",
"src/strtod.h",
"src/tracing/trace-event.cc",
"src/tracing/trace-event.h",
"src/transitions-inl.h",
"src/transitions.cc",
"src/transitions.h",
......
......@@ -13,7 +13,6 @@ deps = {
Var("git_url") + "/chromium/deps/icu.git" + "@" + "8d342a405be5ae8aacb1e16f0bc31c3a4fbf26a2",
"v8/buildtools":
Var("git_url") + "/chromium/buildtools.git" + "@" + "68e3c238a5ab347436762cb929316aa55ca72563",
# TODO(fmeawad): this dependency is not currently used. Added to allow for developement of the V8 Tracing system.
"v8/base/trace_event/common":
Var("git_url") + "/chromium/src/base/trace_event/common.git" + "@" + "d83d44b13d07c2fd0a40101a7deef9b93b841732",
"v8/tools/swarming_client":
......
......@@ -686,6 +686,7 @@
'-pedantic',
# Don't warn about the "struct foo f = {0};" initialization pattern.
'-Wno-missing-field-initializers',
'-Wno-gnu-zero-variadic-macro-arguments',
],
'cflags_cc': [
'-Wnon-virtual-dtor',
......@@ -695,6 +696,16 @@
],
'ldflags': [ '-pthread', ],
'conditions': [
# Don't warn about TRACE_EVENT_* macros with zero arguments passed to
# ##__VA_ARGS__. C99 strict mode prohibits having zero variadic macro
# arguments in gcc.
[ 'clang==0', {
'cflags!' : [
'-pedantic' ,
# Don't warn about unrecognized command line option.
'-Wno-gnu-zero-variadic-macro-arguments',
],
}],
[ 'clang==1 and (v8_target_arch=="x64" or v8_target_arch=="arm64" \
or v8_target_arch=="mips64el")', {
'cflags': [ '-Wshorten-64-to-32' ],
......@@ -726,6 +737,7 @@
'-Wno-unused-parameter',
# Don't warn about the "struct foo f = {0};" initialization pattern.
'-Wno-missing-field-initializers',
'-Wno-gnu-zero-variadic-macro-arguments',
],
'cflags_cc': [
'-Wnon-virtual-dtor',
......@@ -950,6 +962,7 @@
'-Wno-unused-parameter',
# Don't warn about the "struct foo f = {0};" initialization pattern.
'-Wno-missing-field-initializers',
'-Wno-gnu-zero-variadic-macro-arguments',
],
},
'conditions': [
......
......@@ -5,6 +5,8 @@
#ifndef V8_V8_PLATFORM_H_
#define V8_V8_PLATFORM_H_
#include <stdint.h>
namespace v8 {
class Isolate;
......@@ -107,6 +109,51 @@ class Platform {
* the epoch.
**/
virtual double MonotonicallyIncreasingTime() = 0;
/**
* Called by TRACE_EVENT* macros, don't call this directly.
* The name parameter is a category group for example:
* TRACE_EVENT0("v8,parse", "V8.Parse")
* The pointer returned points to a value with zero or more of the bits
* defined in CategoryGroupEnabledFlags.
**/
virtual const uint8_t* GetCategoryGroupEnabled(const char* name) {
static uint8_t no = 0;
return &no;
}
/**
* Gets the category group name of the given category_enabled_flag pointer.
* Usually used while serliazing TRACE_EVENTs.
**/
virtual const char* GetCategoryGroupName(
const uint8_t* category_enabled_flag) {
static const char dummy[] = "dummy";
return dummy;
}
/**
* Adds a trace event to the platform tracing system. This function call is
* usually the result of a TRACE_* macro from trace_event_common.h when
* tracing and the category of the particular trace are enabled. It is not
* advisable to call this function on its own; it is really only meant to be
* used by the trace macros. The returned handle can be used by
* UpdateTraceEventDuration to update the duration of COMPLETE events.
*/
virtual uint64_t AddTraceEvent(
char phase, const uint8_t* category_enabled_flag, const char* name,
uint64_t id, uint64_t bind_id, int32_t num_args, const char** arg_names,
const uint8_t* arg_types, const uint64_t* arg_values,
unsigned int flags) {
return 0;
}
/**
* Sets the duration field of a COMPLETE trace event. It must be called with
* the handle returned from AddTraceEvent().
**/
virtual void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
const char* name, uint64_t handle) {}
};
} // namespace v8
......
include_rules = [
"+base/trace_event/common/trace_event_common.h",
"+src",
"-src/compiler",
"+src/compiler/pipeline.h",
......
......@@ -135,6 +135,28 @@ class PredictablePlatform : public Platform {
return synthetic_time_in_sec_ += 0.00001;
}
uint64_t AddTraceEvent(char phase, const uint8_t* categoryEnabledFlag,
const char* name, uint64_t id, uint64_t bind_id,
int numArgs, const char** argNames,
const uint8_t* argTypes, const uint64_t* argValues,
unsigned int flags) override {
return 0;
}
void UpdateTraceEventDuration(const uint8_t* categoryEnabledFlag,
const char* name, uint64_t handle) override {}
const uint8_t* GetCategoryGroupEnabled(const char* name) override {
static uint8_t no = 0;
return &no;
}
const char* GetCategoryGroupName(
const uint8_t* categoryEnabledFlag) override {
static const char* dummy = "dummy";
return dummy;
}
private:
double synthetic_time_in_sec_ = 0.0;
......
......@@ -168,5 +168,30 @@ double DefaultPlatform::MonotonicallyIncreasingTime() {
return base::TimeTicks::HighResolutionNow().ToInternalValue() /
static_cast<double>(base::Time::kMicrosecondsPerSecond);
}
uint64_t DefaultPlatform::AddTraceEvent(
char phase, const uint8_t* category_enabled_flag, const char* name,
uint64_t id, uint64_t bind_id, int num_args, const char** arg_names,
const uint8_t* arg_types, const uint64_t* arg_values, unsigned int flags) {
return 0;
}
void DefaultPlatform::UpdateTraceEventDuration(
const uint8_t* category_enabled_flag, const char* name, uint64_t handle) {}
const uint8_t* DefaultPlatform::GetCategoryGroupEnabled(const char* name) {
static uint8_t no = 0;
return &no;
}
const char* DefaultPlatform::GetCategoryGroupName(
const uint8_t* category_enabled_flag) {
static const char dummy[] = "dummy";
return dummy;
}
} // namespace platform
} // namespace v8
......@@ -42,6 +42,17 @@ class DefaultPlatform : public Platform {
void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) override;
bool IdleTasksEnabled(Isolate* isolate) override;
double MonotonicallyIncreasingTime() override;
const uint8_t* GetCategoryGroupEnabled(const char* name) override;
const char* GetCategoryGroupName(
const uint8_t* category_enabled_flag) override;
uint64_t AddTraceEvent(char phase, const uint8_t* category_enabled_flag,
const char* name, uint64_t id, uint64_t bind_id,
int32_t num_args, const char** arg_names,
const uint8_t* arg_types, const uint64_t* arg_values,
unsigned int flags) override;
void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
const char* name, uint64_t handle) override;
private:
static const int kMaxThreadPoolSize;
......
......@@ -8,6 +8,7 @@
#include "src/log.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/tracing/trace-event.h"
namespace v8 {
namespace internal {
......@@ -37,6 +38,19 @@ void Logger::CallEventLogger(Isolate* isolate, const char* name, StartEnd se,
isolate->event_logger()(name, se);
}
}
if (expose_to_api) {
if (se == START) {
TRACE_EVENT_BEGIN0("v8", name);
} else {
TRACE_EVENT_END0("v8", name);
}
} else {
if (se == START) {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("v8"), name);
} else {
TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("v8"), name);
}
}
}
} // namespace internal
} // namespace v8
......
// Copyright 2015 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 "src/tracing/trace-event.h"
#include "src/v8.h"
namespace v8 {
namespace internal {
namespace tracing {
v8::Platform* TraceEventHelper::GetCurrentPlatform() {
return v8::internal::V8::GetCurrentPlatform();
}
} // namespace tracing
} // namespace internal
} // namespace v8
This diff is collapsed.
......@@ -170,6 +170,7 @@
'test-strtod.cc',
'test-thread-termination.cc',
'test-threads.cc',
'test-trace-event.cc',
'test-transitions.cc',
'test-typedarrays.cc',
'test-types.cc',
......
......@@ -85,6 +85,28 @@ class MockPlatform : public v8::Platform {
delete task;
}
uint64_t AddTraceEvent(char phase, const uint8_t* categoryEnabledFlag,
const char* name, uint64_t id, uint64_t bind_id,
int numArgs, const char** argNames,
const uint8_t* argTypes, const uint64_t* argValues,
unsigned int flags) override {
return 0;
}
void UpdateTraceEventDuration(const uint8_t* categoryEnabledFlag,
const char* name, uint64_t handle) override {}
const uint8_t* GetCategoryGroupEnabled(const char* name) override {
static uint8_t no = 0;
return &no;
}
const char* GetCategoryGroupName(
const uint8_t* categoryEnabledFlag) override {
static const char* dummy = "dummy";
return dummy;
}
private:
v8::Platform* platform_;
IdleTask* idle_task_;
......
// Copyright 2015 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 <stdlib.h>
#include <string.h>
#include "src/v8.h"
#include "src/list.h"
#include "src/list-inl.h"
#include "test/cctest/cctest.h"
using v8::IdleTask;
using v8::Task;
using v8::Isolate;
#include "src/tracing/trace-event.h"
#define GET_TRACE_OBJECTS_LIST platform.GetMockTraceObjects()
#define GET_TRACE_OBJECT(Index) GET_TRACE_OBJECTS_LIST->at(Index)
struct MockTraceObject {
char phase;
std::string name;
uint64_t id;
uint64_t bind_id;
int num_args;
unsigned int flags;
MockTraceObject(char phase, std::string name, uint64_t id, uint64_t bind_id,
int num_args, int flags)
: phase(phase),
name(name),
id(id),
bind_id(bind_id),
num_args(num_args),
flags(flags) {}
};
typedef v8::internal::List<MockTraceObject*> MockTraceObjectList;
class MockTracingPlatform : public v8::Platform {
public:
explicit MockTracingPlatform(v8::Platform* platform) {}
virtual ~MockTracingPlatform() {
for (int i = 0; i < trace_object_list_.length(); ++i) {
delete trace_object_list_[i];
}
trace_object_list_.Clear();
}
void CallOnBackgroundThread(Task* task,
ExpectedRuntime expected_runtime) override {}
void CallOnForegroundThread(Isolate* isolate, Task* task) override {}
void CallDelayedOnForegroundThread(Isolate* isolate, Task* task,
double delay_in_seconds) override {}
double MonotonicallyIncreasingTime() override { return 0.0; }
void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) override {}
bool IdleTasksEnabled(Isolate* isolate) override { return false; }
bool PendingIdleTask() { return false; }
void PerformIdleTask(double idle_time_in_seconds) {}
bool PendingDelayedTask() { return false; }
void PerformDelayedTask() {}
uint64_t AddTraceEvent(char phase, const uint8_t* category_enabled_flag,
const char* name, uint64_t id, uint64_t bind_id,
int num_args, const char** arg_names,
const uint8_t* arg_types, const uint64_t* arg_values,
unsigned int flags) override {
MockTraceObject* to = new MockTraceObject(phase, std::string(name), id,
bind_id, num_args, flags);
trace_object_list_.Add(to);
return 0;
}
void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
const char* name, uint64_t handle) override {}
const uint8_t* GetCategoryGroupEnabled(const char* name) override {
if (strcmp(name, "v8-cat")) {
static uint8_t no = 0;
return &no;
} else {
static uint8_t yes = 0x7;
return &yes;
}
}
const char* GetCategoryGroupName(
const uint8_t* category_enabled_flag) override {
static const char dummy[] = "dummy";
return dummy;
}
MockTraceObjectList* GetMockTraceObjects() { return &trace_object_list_; }
private:
MockTraceObjectList trace_object_list_;
};
TEST(TraceEventDisabledCategory) {
v8::Platform* old_platform = i::V8::GetCurrentPlatform();
MockTracingPlatform platform(old_platform);
i::V8::SetPlatformForTesting(&platform);
// Disabled category, will not add events.
TRACE_EVENT_BEGIN0("cat", "e1");
TRACE_EVENT_END0("cat", "e1");
CHECK_EQ(0, GET_TRACE_OBJECTS_LIST->length());
i::V8::SetPlatformForTesting(old_platform);
}
TEST(TraceEventNoArgs) {
v8::Platform* old_platform = i::V8::GetCurrentPlatform();
MockTracingPlatform platform(old_platform);
i::V8::SetPlatformForTesting(&platform);
// Enabled category will add 2 events.
TRACE_EVENT_BEGIN0("v8-cat", "e1");
TRACE_EVENT_END0("v8-cat", "e1");
CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->length());
CHECK_EQ('B', GET_TRACE_OBJECT(0)->phase);
CHECK_EQ("e1", GET_TRACE_OBJECT(0)->name);
CHECK_EQ(0, GET_TRACE_OBJECT(0)->num_args);
CHECK_EQ('E', GET_TRACE_OBJECT(1)->phase);
CHECK_EQ("e1", GET_TRACE_OBJECT(1)->name);
CHECK_EQ(0, GET_TRACE_OBJECT(1)->num_args);
i::V8::SetPlatformForTesting(old_platform);
}
TEST(TraceEventWithOneArg) {
v8::Platform* old_platform = i::V8::GetCurrentPlatform();
MockTracingPlatform platform(old_platform);
i::V8::SetPlatformForTesting(&platform);
TRACE_EVENT_BEGIN1("v8-cat", "e1", "arg1", 42);
TRACE_EVENT_END1("v8-cat", "e1", "arg1", 42);
TRACE_EVENT_BEGIN1("v8-cat", "e2", "arg1", "abc");
TRACE_EVENT_END1("v8-cat", "e2", "arg1", "abc");
CHECK_EQ(4, GET_TRACE_OBJECTS_LIST->length());
CHECK_EQ(1, GET_TRACE_OBJECT(0)->num_args);
CHECK_EQ(1, GET_TRACE_OBJECT(1)->num_args);
CHECK_EQ(1, GET_TRACE_OBJECT(2)->num_args);
CHECK_EQ(1, GET_TRACE_OBJECT(3)->num_args);
i::V8::SetPlatformForTesting(old_platform);
}
TEST(TraceEventWithTwoArgs) {
v8::Platform* old_platform = i::V8::GetCurrentPlatform();
MockTracingPlatform platform(old_platform);
i::V8::SetPlatformForTesting(&platform);
TRACE_EVENT_BEGIN2("v8-cat", "e1", "arg1", 42, "arg2", "abc");
TRACE_EVENT_END2("v8-cat", "e1", "arg1", 42, "arg2", "abc");
TRACE_EVENT_BEGIN2("v8-cat", "e2", "arg1", "abc", "arg2", 43);
TRACE_EVENT_END2("v8-cat", "e2", "arg1", "abc", "arg2", 43);
CHECK_EQ(4, GET_TRACE_OBJECTS_LIST->length());
CHECK_EQ(2, GET_TRACE_OBJECT(0)->num_args);
CHECK_EQ(2, GET_TRACE_OBJECT(1)->num_args);
CHECK_EQ(2, GET_TRACE_OBJECT(2)->num_args);
CHECK_EQ(2, GET_TRACE_OBJECT(3)->num_args);
i::V8::SetPlatformForTesting(old_platform);
}
TEST(ScopedTraceEvent) {
v8::Platform* old_platform = i::V8::GetCurrentPlatform();
MockTracingPlatform platform(old_platform);
i::V8::SetPlatformForTesting(&platform);
{ TRACE_EVENT0("v8-cat", "e"); }
CHECK_EQ(1, GET_TRACE_OBJECTS_LIST->length());
CHECK_EQ(0, GET_TRACE_OBJECT(0)->num_args);
{ TRACE_EVENT1("v8-cat", "e1", "arg1", "abc"); }
CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->length());
CHECK_EQ(1, GET_TRACE_OBJECT(1)->num_args);
{ TRACE_EVENT2("v8-cat", "e1", "arg1", "abc", "arg2", 42); }
CHECK_EQ(3, GET_TRACE_OBJECTS_LIST->length());
CHECK_EQ(2, GET_TRACE_OBJECT(2)->num_args);
i::V8::SetPlatformForTesting(old_platform);
}
TEST(TestEventWithFlow) {
v8::Platform* old_platform = i::V8::GetCurrentPlatform();
MockTracingPlatform platform(old_platform);
i::V8::SetPlatformForTesting(&platform);
static uint64_t bind_id = 21;
{
TRACE_EVENT_WITH_FLOW0("v8-cat", "f1", bind_id, TRACE_EVENT_FLAG_FLOW_OUT);
}
{
TRACE_EVENT_WITH_FLOW0(
"v8-cat", "f2", bind_id,
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
}
{ TRACE_EVENT_WITH_FLOW0("v8-cat", "f3", bind_id, TRACE_EVENT_FLAG_FLOW_IN); }
CHECK_EQ(3, GET_TRACE_OBJECTS_LIST->length());
CHECK_EQ(bind_id, GET_TRACE_OBJECT(0)->bind_id);
CHECK_EQ(TRACE_EVENT_FLAG_FLOW_OUT, GET_TRACE_OBJECT(0)->flags);
CHECK_EQ(bind_id, GET_TRACE_OBJECT(1)->bind_id);
CHECK_EQ(TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
GET_TRACE_OBJECT(1)->flags);
CHECK_EQ(bind_id, GET_TRACE_OBJECT(2)->bind_id);
CHECK_EQ(TRACE_EVENT_FLAG_FLOW_IN, GET_TRACE_OBJECT(2)->flags);
i::V8::SetPlatformForTesting(old_platform);
}
TEST(TestEventWithId) {
v8::Platform* old_platform = i::V8::GetCurrentPlatform();
MockTracingPlatform platform(old_platform);
i::V8::SetPlatformForTesting(&platform);
static uint64_t event_id = 21;
TRACE_EVENT_ASYNC_BEGIN0("v8-cat", "a1", event_id);
TRACE_EVENT_ASYNC_END0("v8-cat", "a1", event_id);
CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->length());
CHECK_EQ(TRACE_EVENT_PHASE_ASYNC_BEGIN, GET_TRACE_OBJECT(0)->phase);
CHECK_EQ(event_id, GET_TRACE_OBJECT(0)->id);
CHECK_EQ(TRACE_EVENT_PHASE_ASYNC_END, GET_TRACE_OBJECT(1)->phase);
CHECK_EQ(event_id, GET_TRACE_OBJECT(1)->id);
i::V8::SetPlatformForTesting(old_platform);
}
......@@ -367,6 +367,8 @@
},
'include_dirs+': [
'../..',
# To be able to find base/trace_event/common/trace_event_common.h
'../../..',
],
'defines': [
# TODO(jochen): Remove again after this is globally turned on.
......@@ -1030,6 +1032,8 @@
'../../src/strtod.h',
'../../src/ic/stub-cache.cc',
'../../src/ic/stub-cache.h',
'../../src/tracing/trace-event.cc',
'../../src/tracing/trace-event.h',
'../../src/transitions-inl.h',
'../../src/transitions.cc',
'../../src/transitions.h',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment