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 {
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)".
* See ProfilerModules enum.
*
* \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)".
* See ProfilerModules enum.
*
* \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.
......
......@@ -3469,14 +3469,14 @@ void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
void V8::PauseProfiler() {
#ifdef ENABLE_LOGGING_AND_PROFILING
i::Logger::PauseProfiler(PROFILER_MODULE_CPU);
PauseProfilerEx(PROFILER_MODULE_CPU);
#endif
}
void V8::ResumeProfiler() {
#ifdef ENABLE_LOGGING_AND_PROFILING
i::Logger::ResumeProfiler(PROFILER_MODULE_CPU);
ResumeProfilerEx(PROFILER_MODULE_CPU);
#endif
}
......@@ -3490,7 +3490,7 @@ bool V8::IsProfilerPaused() {
}
void V8::ResumeProfilerEx(int flags) {
void V8::ResumeProfilerEx(int flags, int tag) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
// Snapshot mode: resume modules, perform GC, then pause only
......@@ -3500,19 +3500,19 @@ void V8::ResumeProfilerEx(int flags) {
// Reset snapshot flag and CPU module flags.
flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
const int current_flags = i::Logger::GetActiveProfilerModules();
i::Logger::ResumeProfiler(flags);
i::Logger::ResumeProfiler(flags, tag);
i::Heap::CollectAllGarbage(false);
i::Logger::PauseProfiler(~current_flags & flags);
i::Logger::PauseProfiler(~current_flags & flags, tag);
} else {
i::Logger::ResumeProfiler(flags);
i::Logger::ResumeProfiler(flags, tag);
}
#endif
}
void V8::PauseProfilerEx(int flags) {
void V8::PauseProfilerEx(int flags, int tag) {
#ifdef ENABLE_LOGGING_AND_PROFILING
i::Logger::PauseProfiler(flags);
i::Logger::PauseProfiler(flags, tag);
#endif
}
......
......@@ -125,7 +125,9 @@ static inline void CheckEqualsHelper(const char* file,
const char* expected,
const char* value_source,
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,
"CHECK_EQ(%s, %s) failed\n# Expected: %s\n# Found: %s",
expected_source, value_source, expected, value);
......
......@@ -1934,10 +1934,14 @@ DebugCommandProcessor.prototype.profileRequest_ = function(request, response) {
if (isNaN(modules)) {
return response.failed('Modules is not an integer');
}
var tag = parseInt(request.arguments.tag);
if (isNaN(tag)) {
tag = 0;
}
if (request.arguments.command == 'resume') {
%ProfilerResume(modules);
%ProfilerResume(modules, tag);
} else if (request.arguments.command == 'pause') {
%ProfilerPause(modules);
%ProfilerPause(modules, tag);
} else {
return response.failed('Unknown command');
}
......
......@@ -330,6 +330,8 @@ SlidingStateWindow* Logger::sliding_state_window_ = NULL;
const char** Logger::log_events_ = NULL;
CompressionHelper* Logger::compression_helper_ = NULL;
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,
const char* kLongLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
......@@ -1164,53 +1166,61 @@ int Logger::GetActiveProfilerModules() {
}
void Logger::PauseProfiler(int flags) {
void Logger::PauseProfiler(int flags, int tag) {
if (!Log::IsEnabled()) return;
const int active_modules = GetActiveProfilerModules();
const int modules_to_disable = active_modules & flags;
if (modules_to_disable == PROFILER_MODULE_NONE) return;
if (modules_to_disable & PROFILER_MODULE_CPU) {
profiler_->pause();
if (FLAG_prof_lazy) {
if (!FLAG_sliding_state_window) ticker_->Stop();
FLAG_log_code = false;
// Must be the same message as Log::kDynamicBufferSeal.
LOG(UncheckedStringEvent("profiler", "pause"));
if (flags & PROFILER_MODULE_CPU) {
// It is OK to have negative nesting.
if (--cpu_profiler_nesting_ == 0) {
profiler_->pause();
if (FLAG_prof_lazy) {
if (!FLAG_sliding_state_window) ticker_->Stop();
FLAG_log_code = false;
// 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)) {
FLAG_log_gc = false;
if (--heap_profiler_nesting_ == 0) {
FLAG_log_gc = false;
}
}
// Turn off logging if no active modules remain.
if ((active_modules & ~flags) == PROFILER_MODULE_NONE) {
if (tag != 0) {
IntEvent("close-tag", tag);
}
if (GetActiveProfilerModules() == PROFILER_MODULE_NONE) {
is_logging_ = false;
}
}
void Logger::ResumeProfiler(int flags) {
void Logger::ResumeProfiler(int flags, int tag) {
if (!Log::IsEnabled()) return;
const int modules_to_enable = ~GetActiveProfilerModules() & flags;
if (modules_to_enable != PROFILER_MODULE_NONE) {
is_logging_ = true;
if (tag != 0) {
IntEvent("open-tag", tag);
}
if (modules_to_enable & PROFILER_MODULE_CPU) {
if (FLAG_prof_lazy) {
profiler_->Engage();
LOG(UncheckedStringEvent("profiler", "resume"));
FLAG_log_code = true;
LogCompiledFunctions();
LogFunctionObjects();
LogAccessorCallbacks();
if (!FLAG_sliding_state_window) ticker_->Start();
if (flags & PROFILER_MODULE_CPU) {
if (cpu_profiler_nesting_++ == 0) {
is_logging_ = true;
if (FLAG_prof_lazy) {
profiler_->Engage();
LOG(UncheckedStringEvent("profiler", "resume"));
FLAG_log_code = true;
LogCompiledFunctions();
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)) {
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) {
// either from main or Profiler's thread.
void Logger::StopLoggingAndProfiling() {
Log::stop();
PauseProfiler(PROFILER_MODULE_CPU);
PauseProfiler(PROFILER_MODULE_CPU, 0);
}
......
......@@ -277,8 +277,8 @@ class Logger {
// Pause/Resume collection of profiling data.
// When data collection is paused, CPU Tick events are discarded until
// data collection is Resumed.
static void PauseProfiler(int flags);
static void ResumeProfiler(int flags);
static void PauseProfiler(int flags, int tag);
static void ResumeProfiler(int flags, int tag);
static int GetActiveProfilerModules();
// If logging is performed into a memory buffer, allows to
......@@ -379,6 +379,8 @@ class Logger {
friend class LoggerTestHelper;
static bool is_logging_;
static int cpu_profiler_nesting_;
static int heap_profiler_nesting_;
#else
static bool is_logging() { return false; }
#endif
......
......@@ -7917,20 +7917,22 @@ static Object* Runtime_FunctionGetInferredName(Arguments args) {
static Object* Runtime_ProfilerResume(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
ASSERT(args.length() == 2);
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();
}
static Object* Runtime_ProfilerPause(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
ASSERT(args.length() == 2);
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();
}
......
......@@ -328,8 +328,8 @@ namespace internal {
#ifdef ENABLE_LOGGING_AND_PROFILING
#define RUNTIME_FUNCTION_LIST_PROFILER_SUPPORT(F) \
F(ProfilerResume, 1, 1) \
F(ProfilerPause, 1, 1)
F(ProfilerResume, 2, 1) \
F(ProfilerPause, 2, 1)
#else
#define RUNTIME_FUNCTION_LIST_PROFILER_SUPPORT(F)
#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