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
-~----------~----~----~----~------~----~------~--~---

Reply via email to