From d3a16a2e2a4db65606a23d54ddb656fc864ca583 Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Mon, 10 Mar 2014 08:56:48 +0000 Subject: [PATCH] Add support for allowing an embedder to get the V8 profile timer event logs. Contributed by fmeawad@chromium.org R=yangguo@chromium.org Review URL: https://codereview.chromium.org/186163002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19745 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 8 ++++++++ src/api.cc | 5 +++++ src/counters.cc | 8 ++------ src/isolate.cc | 6 ++++++ src/isolate.h | 1 + src/log.cc | 8 +++++++- src/log.h | 7 +++++-- test/cctest/test-api.cc | 24 ++++++++++++++++++++++++ 8 files changed, 58 insertions(+), 9 deletions(-) diff --git a/include/v8.h b/include/v8.h index ec442bdad..c7364b43f 100644 --- a/include/v8.h +++ b/include/v8.h @@ -3799,6 +3799,9 @@ typedef void (*FatalErrorCallback)(const char* location, const char* message); typedef void (*MessageCallback)(Handle message, Handle error); +// --- Tracing --- + +typedef void (*LogEventCallback)(const char* name, int event); /** * Create new error objects by calling the corresponding error object @@ -4185,6 +4188,11 @@ class V8_EXPORT Isolate { */ void RequestGarbageCollectionForTesting(GarbageCollectionType type); + /** + * Set the callback to invoke for logging event. + */ + void SetEventLogger(LogEventCallback that); + private: Isolate(); Isolate(const Isolate&); diff --git a/src/api.cc b/src/api.cc index 1fe8b5612..f2b4cb328 100644 --- a/src/api.cc +++ b/src/api.cc @@ -6381,6 +6381,11 @@ void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) { } +void Isolate::SetEventLogger(LogEventCallback that) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->set_event_logger(that); +} + String::Utf8Value::Utf8Value(v8::Handle obj) : str_(NULL), length_(0) { i::Isolate* isolate = i::Isolate::Current(); diff --git a/src/counters.cc b/src/counters.cc index e0a6a60a0..e7fab1c3d 100644 --- a/src/counters.cc +++ b/src/counters.cc @@ -62,9 +62,7 @@ void HistogramTimer::Start() { if (Enabled()) { timer_.Start(); } - if (FLAG_log_internal_timer_events) { - LOG(isolate(), TimerEvent(Logger::START, name())); - } + isolate()->event_logger()(name(), Logger::START); } @@ -75,9 +73,7 @@ void HistogramTimer::Stop() { AddSample(static_cast(timer_.Elapsed().InMilliseconds())); timer_.Stop(); } - if (FLAG_log_internal_timer_events) { - LOG(isolate(), TimerEvent(Logger::END, name())); - } + isolate()->event_logger()(name(), Logger::END); } } } // namespace v8::internal diff --git a/src/isolate.cc b/src/isolate.cc index 2d45d78b0..9dd2c5f12 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -2016,6 +2016,12 @@ bool Isolate::Init(Deserializer* des) { bootstrapper_->Initialize(create_heap_objects); builtins_.SetUp(this, create_heap_objects); + if (FLAG_log_internal_timer_events) { + set_event_logger(Logger::LogInternalEvents); + } else { + set_event_logger(Logger::EmptyLogInternalEvents); + } + // Set default value if not yet set. // TODO(yangguo): move this to ResourceConstraints::ConfigureDefaults // once ResourceConstraints becomes an argument to the Isolate constructor. diff --git a/src/isolate.h b/src/isolate.h index 5dd099873..5df84a2e5 100644 --- a/src/isolate.h +++ b/src/isolate.h @@ -340,6 +340,7 @@ typedef List DebugObjectCache; /* A previously allocated buffer of kMinimalBufferSize bytes, or NULL. */ \ V(byte*, assembler_spare_buffer, NULL) \ V(FatalErrorCallback, exception_behavior, NULL) \ + V(LogEventCallback, event_logger, NULL) \ V(AllowCodeGenerationFromStringsCallback, allow_code_gen_callback, NULL) \ /* To distinguish the function templates, so that we can find them in the */ \ /* function cache of the native context. */ \ diff --git a/src/log.cc b/src/log.cc index 1c332d173..76fef5cd2 100644 --- a/src/log.cc +++ b/src/log.cc @@ -1124,8 +1124,14 @@ void Logger::LeaveExternal(Isolate* isolate) { } +void Logger::LogInternalEvents(const char* name, int se) { + Isolate* isolate = Isolate::Current(); + LOG(isolate, TimerEvent(static_cast(se), name)); +} + + void Logger::TimerEventScope::LogTimerEvent(StartEnd se) { - LOG(isolate_, TimerEvent(se, name_)); + isolate_->event_logger()(name_, se); } diff --git a/src/log.h b/src/log.h index d4dc76a21..09b6b7774 100644 --- a/src/log.h +++ b/src/log.h @@ -316,15 +316,18 @@ class Logger { static void EnterExternal(Isolate* isolate); static void LeaveExternal(Isolate* isolate); + static void EmptyLogInternalEvents(const char* name, int se) { } + static void LogInternalEvents(const char* name, int se); + class TimerEventScope { public: TimerEventScope(Isolate* isolate, const char* name) : isolate_(isolate), name_(name) { - if (FLAG_log_internal_timer_events) LogTimerEvent(START); + LogTimerEvent(START); } ~TimerEventScope() { - if (FLAG_log_internal_timer_events) LogTimerEvent(END); + LogTimerEvent(END); } void LogTimerEvent(StartEnd se); diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 5a990e46a..35f2d91f6 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -22116,3 +22116,27 @@ TEST(TestFunctionCallOptimization) { ApiCallOptimizationChecker checker; checker.RunAll(); } + + +static const char* last_event_message; +static int last_event_status; +void StoringEventLoggerCallback(const char* message, int status) { + last_event_message = message; + last_event_status = status; +} + + +TEST(EventLogging) { + v8::Isolate* isolate = CcTest::isolate(); + isolate->SetEventLogger(StoringEventLoggerCallback); + v8::internal::HistogramTimer* histogramTimer = + new v8::internal::HistogramTimer( + "V8.Test", 0, 10000, 50, + reinterpret_cast(isolate)); + histogramTimer->Start(); + CHECK_EQ("V8.Test", last_event_message); + CHECK_EQ(0, last_event_status); + histogramTimer->Stop(); + CHECK_EQ("V8.Test", last_event_message); + CHECK_EQ(1, last_event_status); +} -- 2.34.1