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 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2619 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f2faaa5c34
commit
5470f9b132
@ -1971,12 +1971,15 @@ typedef Persistent<Context> (*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
|
||||
};
|
||||
|
||||
|
||||
|
40
src/api.cc
40
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
|
||||
|
71
src/log.cc
71
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user