Implement tagging of profiler log event blocks.

This change allows to associate integer tags with blocks of profiler
log events, and repeat calls to 'ResumeProfiler' / 'PauseProfiler' in
order to establsh nested (not necessary properly nested) blocks. By
supporting this, we will be able to match WebInspector's CPU profiler
abilities in DevTools.

I also refactored some testing code.

Review URL: http://codereview.chromium.org/619004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3889 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1b526cc7
...@@ -2349,22 +2349,30 @@ class V8EXPORT V8 { ...@@ -2349,22 +2349,30 @@ class V8EXPORT V8 {
static bool IsProfilerPaused(); static bool IsProfilerPaused();
/** /**
* Resumes specified profiler modules. * Resumes specified profiler modules. Can be called several times to
* mark the opening of a profiler events block with the given tag.
*
* "ResumeProfiler" is equivalent to "ResumeProfilerEx(PROFILER_MODULE_CPU)". * "ResumeProfiler" is equivalent to "ResumeProfilerEx(PROFILER_MODULE_CPU)".
* See ProfilerModules enum. * See ProfilerModules enum.
* *
* \param flags Flags specifying profiler modules. * \param flags Flags specifying profiler modules.
* \param tag Profile tag.
*/ */
static void ResumeProfilerEx(int flags); static void ResumeProfilerEx(int flags, int tag = 0);
/** /**
* Pauses specified profiler modules. * Pauses specified profiler modules. Each call to "PauseProfilerEx" closes
* a block of profiler events opened by a call to "ResumeProfilerEx" with the
* same tag value. There is no need for blocks to be properly nested.
* The profiler is paused when the last opened block is closed.
*
* "PauseProfiler" is equivalent to "PauseProfilerEx(PROFILER_MODULE_CPU)". * "PauseProfiler" is equivalent to "PauseProfilerEx(PROFILER_MODULE_CPU)".
* See ProfilerModules enum. * See ProfilerModules enum.
* *
* \param flags Flags specifying profiler modules. * \param flags Flags specifying profiler modules.
* \param tag Profile tag.
*/ */
static void PauseProfilerEx(int flags); static void PauseProfilerEx(int flags, int tag = 0);
/** /**
* Returns active (resumed) profiler modules. * Returns active (resumed) profiler modules.
......
...@@ -3469,14 +3469,14 @@ void V8::SetGlobalGCEpilogueCallback(GCCallback callback) { ...@@ -3469,14 +3469,14 @@ void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
void V8::PauseProfiler() { void V8::PauseProfiler() {
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
i::Logger::PauseProfiler(PROFILER_MODULE_CPU); PauseProfilerEx(PROFILER_MODULE_CPU);
#endif #endif
} }
void V8::ResumeProfiler() { void V8::ResumeProfiler() {
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
i::Logger::ResumeProfiler(PROFILER_MODULE_CPU); ResumeProfilerEx(PROFILER_MODULE_CPU);
#endif #endif
} }
...@@ -3490,7 +3490,7 @@ bool V8::IsProfilerPaused() { ...@@ -3490,7 +3490,7 @@ bool V8::IsProfilerPaused() {
} }
void V8::ResumeProfilerEx(int flags) { void V8::ResumeProfilerEx(int flags, int tag) {
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) { if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
// Snapshot mode: resume modules, perform GC, then pause only // Snapshot mode: resume modules, perform GC, then pause only
...@@ -3500,19 +3500,19 @@ void V8::ResumeProfilerEx(int flags) { ...@@ -3500,19 +3500,19 @@ void V8::ResumeProfilerEx(int flags) {
// Reset snapshot flag and CPU module flags. // Reset snapshot flag and CPU module flags.
flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU); flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
const int current_flags = i::Logger::GetActiveProfilerModules(); const int current_flags = i::Logger::GetActiveProfilerModules();
i::Logger::ResumeProfiler(flags); i::Logger::ResumeProfiler(flags, tag);
i::Heap::CollectAllGarbage(false); i::Heap::CollectAllGarbage(false);
i::Logger::PauseProfiler(~current_flags & flags); i::Logger::PauseProfiler(~current_flags & flags, tag);
} else { } else {
i::Logger::ResumeProfiler(flags); i::Logger::ResumeProfiler(flags, tag);
} }
#endif #endif
} }
void V8::PauseProfilerEx(int flags) { void V8::PauseProfilerEx(int flags, int tag) {
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
i::Logger::PauseProfiler(flags); i::Logger::PauseProfiler(flags, tag);
#endif #endif
} }
......
...@@ -125,7 +125,9 @@ static inline void CheckEqualsHelper(const char* file, ...@@ -125,7 +125,9 @@ static inline void CheckEqualsHelper(const char* file,
const char* expected, const char* expected,
const char* value_source, const char* value_source,
const char* value) { const char* value) {
if (strcmp(expected, value) != 0) { if ((expected == NULL && value != NULL) ||
(expected != NULL && value == NULL) ||
(expected != NULL && value != NULL && strcmp(expected, value) != 0)) {
V8_Fatal(file, line, V8_Fatal(file, line,
"CHECK_EQ(%s, %s) failed\n# Expected: %s\n# Found: %s", "CHECK_EQ(%s, %s) failed\n# Expected: %s\n# Found: %s",
expected_source, value_source, expected, value); expected_source, value_source, expected, value);
......
...@@ -1934,10 +1934,14 @@ DebugCommandProcessor.prototype.profileRequest_ = function(request, response) { ...@@ -1934,10 +1934,14 @@ DebugCommandProcessor.prototype.profileRequest_ = function(request, response) {
if (isNaN(modules)) { if (isNaN(modules)) {
return response.failed('Modules is not an integer'); return response.failed('Modules is not an integer');
} }
var tag = parseInt(request.arguments.tag);
if (isNaN(tag)) {
tag = 0;
}
if (request.arguments.command == 'resume') { if (request.arguments.command == 'resume') {
%ProfilerResume(modules); %ProfilerResume(modules, tag);
} else if (request.arguments.command == 'pause') { } else if (request.arguments.command == 'pause') {
%ProfilerPause(modules); %ProfilerPause(modules, tag);
} else { } else {
return response.failed('Unknown command'); return response.failed('Unknown command');
} }
......
...@@ -330,6 +330,8 @@ SlidingStateWindow* Logger::sliding_state_window_ = NULL; ...@@ -330,6 +330,8 @@ SlidingStateWindow* Logger::sliding_state_window_ = NULL;
const char** Logger::log_events_ = NULL; const char** Logger::log_events_ = NULL;
CompressionHelper* Logger::compression_helper_ = NULL; CompressionHelper* Logger::compression_helper_ = NULL;
bool Logger::is_logging_ = false; bool Logger::is_logging_ = false;
int Logger::cpu_profiler_nesting_ = 0;
int Logger::heap_profiler_nesting_ = 0;
#define DECLARE_LONG_EVENT(ignore1, long_name, ignore2) long_name, #define DECLARE_LONG_EVENT(ignore1, long_name, ignore2) long_name,
const char* kLongLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = { const char* kLongLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
...@@ -1164,53 +1166,61 @@ int Logger::GetActiveProfilerModules() { ...@@ -1164,53 +1166,61 @@ int Logger::GetActiveProfilerModules() {
} }
void Logger::PauseProfiler(int flags) { void Logger::PauseProfiler(int flags, int tag) {
if (!Log::IsEnabled()) return; if (!Log::IsEnabled()) return;
const int active_modules = GetActiveProfilerModules(); if (flags & PROFILER_MODULE_CPU) {
const int modules_to_disable = active_modules & flags; // It is OK to have negative nesting.
if (modules_to_disable == PROFILER_MODULE_NONE) return; if (--cpu_profiler_nesting_ == 0) {
profiler_->pause();
if (modules_to_disable & PROFILER_MODULE_CPU) { if (FLAG_prof_lazy) {
profiler_->pause(); if (!FLAG_sliding_state_window) ticker_->Stop();
if (FLAG_prof_lazy) { FLAG_log_code = false;
if (!FLAG_sliding_state_window) ticker_->Stop(); // Must be the same message as Log::kDynamicBufferSeal.
FLAG_log_code = false; LOG(UncheckedStringEvent("profiler", "pause"));
// Must be the same message as Log::kDynamicBufferSeal. }
LOG(UncheckedStringEvent("profiler", "pause"));
} }
} }
if (modules_to_disable & if (flags &
(PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS)) { (PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS)) {
FLAG_log_gc = false; if (--heap_profiler_nesting_ == 0) {
FLAG_log_gc = false;
}
} }
// Turn off logging if no active modules remain. if (tag != 0) {
if ((active_modules & ~flags) == PROFILER_MODULE_NONE) { IntEvent("close-tag", tag);
}
if (GetActiveProfilerModules() == PROFILER_MODULE_NONE) {
is_logging_ = false; is_logging_ = false;
} }
} }
void Logger::ResumeProfiler(int flags) { void Logger::ResumeProfiler(int flags, int tag) {
if (!Log::IsEnabled()) return; if (!Log::IsEnabled()) return;
const int modules_to_enable = ~GetActiveProfilerModules() & flags; if (tag != 0) {
if (modules_to_enable != PROFILER_MODULE_NONE) { IntEvent("open-tag", tag);
is_logging_ = true;
} }
if (modules_to_enable & PROFILER_MODULE_CPU) { if (flags & PROFILER_MODULE_CPU) {
if (FLAG_prof_lazy) { if (cpu_profiler_nesting_++ == 0) {
profiler_->Engage(); is_logging_ = true;
LOG(UncheckedStringEvent("profiler", "resume")); if (FLAG_prof_lazy) {
FLAG_log_code = true; profiler_->Engage();
LogCompiledFunctions(); LOG(UncheckedStringEvent("profiler", "resume"));
LogFunctionObjects(); FLAG_log_code = true;
LogAccessorCallbacks(); LogCompiledFunctions();
if (!FLAG_sliding_state_window) ticker_->Start(); LogFunctionObjects();
LogAccessorCallbacks();
if (!FLAG_sliding_state_window) ticker_->Start();
}
profiler_->resume();
} }
profiler_->resume();
} }
if (modules_to_enable & if (flags &
(PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS)) { (PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS)) {
FLAG_log_gc = true; if (heap_profiler_nesting_++ == 0) {
is_logging_ = true;
FLAG_log_gc = true;
}
} }
} }
...@@ -1219,7 +1229,7 @@ void Logger::ResumeProfiler(int flags) { ...@@ -1219,7 +1229,7 @@ void Logger::ResumeProfiler(int flags) {
// either from main or Profiler's thread. // either from main or Profiler's thread.
void Logger::StopLoggingAndProfiling() { void Logger::StopLoggingAndProfiling() {
Log::stop(); Log::stop();
PauseProfiler(PROFILER_MODULE_CPU); PauseProfiler(PROFILER_MODULE_CPU, 0);
} }
......
...@@ -277,8 +277,8 @@ class Logger { ...@@ -277,8 +277,8 @@ class Logger {
// Pause/Resume collection of profiling data. // Pause/Resume collection of profiling data.
// When data collection is paused, CPU Tick events are discarded until // When data collection is paused, CPU Tick events are discarded until
// data collection is Resumed. // data collection is Resumed.
static void PauseProfiler(int flags); static void PauseProfiler(int flags, int tag);
static void ResumeProfiler(int flags); static void ResumeProfiler(int flags, int tag);
static int GetActiveProfilerModules(); static int GetActiveProfilerModules();
// If logging is performed into a memory buffer, allows to // If logging is performed into a memory buffer, allows to
...@@ -379,6 +379,8 @@ class Logger { ...@@ -379,6 +379,8 @@ class Logger {
friend class LoggerTestHelper; friend class LoggerTestHelper;
static bool is_logging_; static bool is_logging_;
static int cpu_profiler_nesting_;
static int heap_profiler_nesting_;
#else #else
static bool is_logging() { return false; } static bool is_logging() { return false; }
#endif #endif
......
...@@ -7917,20 +7917,22 @@ static Object* Runtime_FunctionGetInferredName(Arguments args) { ...@@ -7917,20 +7917,22 @@ static Object* Runtime_FunctionGetInferredName(Arguments args) {
static Object* Runtime_ProfilerResume(Arguments args) { static Object* Runtime_ProfilerResume(Arguments args) {
NoHandleAllocation ha; NoHandleAllocation ha;
ASSERT(args.length() == 1); ASSERT(args.length() == 2);
CONVERT_CHECKED(Smi, smi_modules, args[0]); CONVERT_CHECKED(Smi, smi_modules, args[0]);
v8::V8::ResumeProfilerEx(smi_modules->value()); CONVERT_CHECKED(Smi, smi_tag, args[1]);
v8::V8::ResumeProfilerEx(smi_modules->value(), smi_tag->value());
return Heap::undefined_value(); return Heap::undefined_value();
} }
static Object* Runtime_ProfilerPause(Arguments args) { static Object* Runtime_ProfilerPause(Arguments args) {
NoHandleAllocation ha; NoHandleAllocation ha;
ASSERT(args.length() == 1); ASSERT(args.length() == 2);
CONVERT_CHECKED(Smi, smi_modules, args[0]); CONVERT_CHECKED(Smi, smi_modules, args[0]);
v8::V8::PauseProfilerEx(smi_modules->value()); CONVERT_CHECKED(Smi, smi_tag, args[1]);
v8::V8::PauseProfilerEx(smi_modules->value(), smi_tag->value());
return Heap::undefined_value(); return Heap::undefined_value();
} }
......
...@@ -328,8 +328,8 @@ namespace internal { ...@@ -328,8 +328,8 @@ namespace internal {
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
#define RUNTIME_FUNCTION_LIST_PROFILER_SUPPORT(F) \ #define RUNTIME_FUNCTION_LIST_PROFILER_SUPPORT(F) \
F(ProfilerResume, 1, 1) \ F(ProfilerResume, 2, 1) \
F(ProfilerPause, 1, 1) F(ProfilerPause, 2, 1)
#else #else
#define RUNTIME_FUNCTION_LIST_PROFILER_SUPPORT(F) #define RUNTIME_FUNCTION_LIST_PROFILER_SUPPORT(F)
#endif #endif
......
This diff is collapsed.
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