Revision: 2619 Author: [email protected] Date: Tue Aug 4 07:14:01 2009 Log: Add an ability to initiate GC through V8 API.
I'm planning to use it in DevTools heap profiler. It is a common scenario in debugging memory leaks to enforce GC, then perform an operation, then enforce GC again to check for non-collected (that is, leaked) objects. Using the existing GC extension isn't possible because it doesn't exposed in the normal operation mode of Chromium. Review URL: http://codereview.chromium.org/159787 http://code.google.com/p/v8/source/detail?r=2619 Modified: /branches/bleeding_edge/include/v8.h /branches/bleeding_edge/src/api.cc /branches/bleeding_edge/src/log.cc /branches/bleeding_edge/src/log.h /branches/bleeding_edge/test/cctest/test-log.cc ======================================= --- /branches/bleeding_edge/include/v8.h Wed Jul 29 04:23:36 2009 +++ /branches/bleeding_edge/include/v8.h Tue Aug 4 07:14:01 2009 @@ -1971,12 +1971,15 @@ * * 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 }; ======================================= --- /branches/bleeding_edge/src/api.cc Wed Jul 29 04:23:36 2009 +++ /branches/bleeding_edge/src/api.cc Tue Aug 4 07:14:01 2009 @@ -3214,21 +3214,21 @@ 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 @@ 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::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 ======================================= --- /branches/bleeding_edge/src/log.cc Wed Jul 29 01:10:19 2009 +++ /branches/bleeding_edge/src/log.cc Tue Aug 4 07:14:01 2009 @@ -957,38 +957,63 @@ } -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; - } - 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")); - } - is_logging_ = false; +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")); + } + } + 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; + } } -void Logger::ResumeProfiler() { - if (!profiler_->paused() || !Log::IsEnabled()) { - return; - } - is_logging_ = true; - if (FLAG_prof_lazy) { - LOG(UncheckedStringEvent("profiler", "resume")); - FLAG_log_code = true; - LogCompiledFunctions(); - if (!FLAG_sliding_state_window) ticker_->Start(); - } - profiler_->resume(); +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; + } + 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; + } } @@ -996,7 +1021,7 @@ // either from main or Profiler's thread. void Logger::StopLoggingAndProfiling() { Log::stop(); - PauseProfiler(); + PauseProfiler(PROFILER_MODULE_CPU); } ======================================= --- /branches/bleeding_edge/src/log.h Wed Jul 29 01:10:19 2009 +++ /branches/bleeding_edge/src/log.h Tue Aug 4 07:14:01 2009 @@ -249,11 +249,11 @@ } // 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. ======================================= --- /branches/bleeding_edge/test/cctest/test-log.cc Tue Jul 28 02:10:29 2009 +++ /branches/bleeding_edge/test/cctest/test-log.cc Tue Aug 4 07:14:01 2009 @@ -166,7 +166,7 @@ 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 @@ 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 --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
