diff --git a/include/v8.h b/include/v8.h index 5e3dbffb68..d076f5710e 100644 --- a/include/v8.h +++ b/include/v8.h @@ -1971,12 +1971,15 @@ typedef Persistent (*ContextGenerator)(); * * In V8, profiler consists of several modules: CPU profiler, and different * kinds of heap profiling. Each can be turned on / off independently. + * When PROFILER_MODULE_HEAP_SNAPSHOT flag is passed to ResumeProfilerEx, + * modules are enabled only temporarily for making a snapshot of the heap. */ enum ProfilerModules { PROFILER_MODULE_NONE = 0, PROFILER_MODULE_CPU = 1, PROFILER_MODULE_HEAP_STATS = 1 << 1, - PROFILER_MODULE_JS_CONSTRUCTORS = 1 << 2 + PROFILER_MODULE_JS_CONSTRUCTORS = 1 << 2, + PROFILER_MODULE_HEAP_SNAPSHOT = 1 << 16 }; diff --git a/src/api.cc b/src/api.cc index 08281012bd..9bc623a63a 100644 --- a/src/api.cc +++ b/src/api.cc @@ -3214,21 +3214,21 @@ void V8::SetGlobalGCEpilogueCallback(GCCallback callback) { void V8::PauseProfiler() { #ifdef ENABLE_LOGGING_AND_PROFILING - i::Logger::PauseProfiler(); + i::Logger::PauseProfiler(PROFILER_MODULE_CPU); #endif } void V8::ResumeProfiler() { #ifdef ENABLE_LOGGING_AND_PROFILING - i::Logger::ResumeProfiler(); + i::Logger::ResumeProfiler(PROFILER_MODULE_CPU); #endif } bool V8::IsProfilerPaused() { #ifdef ENABLE_LOGGING_AND_PROFILING - return i::Logger::IsProfilerPaused(); + return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU; #else return true; #endif @@ -3237,11 +3237,19 @@ bool V8::IsProfilerPaused() { void V8::ResumeProfilerEx(int flags) { #ifdef ENABLE_LOGGING_AND_PROFILING - if (flags & PROFILER_MODULE_CPU) { - i::Logger::ResumeProfiler(); - } - if (flags & (PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS)) { - i::FLAG_log_gc = true; + if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) { + // Snapshot mode: resume modules, perform GC, then pause only + // those modules which haven't been started prior to making a + // snapshot. + + // 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::Heap::CollectAllGarbage(); + i::Logger::PauseProfiler(~current_flags & flags); + } else { + i::Logger::ResumeProfiler(flags); } #endif } @@ -3249,26 +3257,14 @@ void V8::ResumeProfilerEx(int flags) { void V8::PauseProfilerEx(int flags) { #ifdef ENABLE_LOGGING_AND_PROFILING - if (flags & PROFILER_MODULE_CPU) { - i::Logger::PauseProfiler(); - } - if (flags & (PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS)) { - i::FLAG_log_gc = false; - } + i::Logger::PauseProfiler(flags); #endif } int V8::GetActiveProfilerModules() { #ifdef ENABLE_LOGGING_AND_PROFILING - int result = PROFILER_MODULE_NONE; - if (!i::Logger::IsProfilerPaused()) { - result |= PROFILER_MODULE_CPU; - } - if (i::FLAG_log_gc) { - result |= PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS; - } - return result; + return i::Logger::GetActiveProfilerModules(); #else return PROFILER_MODULE_NONE; #endif diff --git a/src/log.cc b/src/log.cc index 0c1b76d7f4..6c188f45b1 100644 --- a/src/log.cc +++ b/src/log.cc @@ -957,38 +957,63 @@ void Logger::TickEvent(TickSample* sample, bool overflow) { } -bool Logger::IsProfilerPaused() { - return profiler_->paused(); +int Logger::GetActiveProfilerModules() { + int result = PROFILER_MODULE_NONE; + if (!profiler_->paused()) { + result |= PROFILER_MODULE_CPU; + } + if (FLAG_log_gc) { + result |= PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS; + } + return result; } -void Logger::PauseProfiler() { - if (profiler_->paused()) { - return; +void Logger::PauseProfiler(int flags) { + 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")); + } } - 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 & + (PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS)) { + FLAG_log_gc = false; + } + // Turn off logging if no active modules remain. + if (active_modules & ~flags == PROFILER_MODULE_NONE) { + is_logging_ = false; } - is_logging_ = false; } -void Logger::ResumeProfiler() { - if (!profiler_->paused() || !Log::IsEnabled()) { - return; +void Logger::ResumeProfiler(int flags) { + if (!Log::IsEnabled()) return; + const int modules_to_enable = ~GetActiveProfilerModules() & flags; + if (modules_to_enable != PROFILER_MODULE_NONE) { + is_logging_ = true; } - is_logging_ = true; - if (FLAG_prof_lazy) { - LOG(UncheckedStringEvent("profiler", "resume")); - FLAG_log_code = true; - LogCompiledFunctions(); - if (!FLAG_sliding_state_window) ticker_->Start(); + if (modules_to_enable & PROFILER_MODULE_CPU) { + if (FLAG_prof_lazy) { + LOG(UncheckedStringEvent("profiler", "resume")); + FLAG_log_code = true; + LogCompiledFunctions(); + if (!FLAG_sliding_state_window) ticker_->Start(); + } + profiler_->resume(); + } + if (modules_to_enable & + (PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS)) { + FLAG_log_gc = true; } - profiler_->resume(); } @@ -996,7 +1021,7 @@ void Logger::ResumeProfiler() { // either from main or Profiler's thread. void Logger::StopLoggingAndProfiling() { Log::stop(); - PauseProfiler(); + PauseProfiler(PROFILER_MODULE_CPU); } diff --git a/src/log.h b/src/log.h index 1692e77d21..89f6cdb391 100644 --- a/src/log.h +++ b/src/log.h @@ -249,11 +249,11 @@ class Logger { } // Pause/Resume collection of profiling data. - // When data collection is paused, Tick events are discarded until + // When data collection is paused, CPU Tick events are discarded until // data collection is Resumed. - static bool IsProfilerPaused(); - static void PauseProfiler(); - static void ResumeProfiler(); + static void PauseProfiler(int flags); + static void ResumeProfiler(int flags); + static int GetActiveProfilerModules(); // If logging is performed into a memory buffer, allows to // retrieve previously written messages. See v8.h. diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc index 46ae13b180..df5823416c 100644 --- a/test/cctest/test-log.cc +++ b/test/cctest/test-log.cc @@ -166,7 +166,7 @@ static void SigProfSignalHandler(int signal, siginfo_t* info, void* context) { static int CheckThatProfilerWorks(int log_pos) { - Logger::ResumeProfiler(); + Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU); CHECK(LoggerTestHelper::IsSamplerActive()); // Verify that the current map of compiled functions has been logged. @@ -207,7 +207,7 @@ static int CheckThatProfilerWorks(int log_pos) { i::OS::Sleep(1); } - Logger::PauseProfiler(); + Logger::PauseProfiler(v8::PROFILER_MODULE_CPU); CHECK(!LoggerTestHelper::IsSamplerActive()); // Wait 50 msecs to allow Profiler thread to process the last