Allow new CPU profiling subsystem to coexist nicely with the old one.
authormikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 12 Apr 2010 07:23:43 +0000 (07:23 +0000)
committermikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 12 Apr 2010 07:23:43 +0000 (07:23 +0000)
This is to make possible enabling usage of the new profiling subsystem
in Chromium without much hassle. The idea is pretty simple: unless the
new profiling API is used, all works as usual, as soon as Chromium
starts to use the new API, it will work too.

Review URL: http://codereview.chromium.org/1635005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4382 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

15 files changed:
SConstruct
src/cpu-profiler-inl.h
src/cpu-profiler.cc
src/cpu-profiler.h
src/flag-definitions.h
src/globals.h
src/log.cc
src/log.h
src/platform-linux.cc
src/platform-macos.cc
src/platform-win32.cc
src/v8.cc
test/cctest/test-cpu-profiler.cc
test/cctest/test-profile-generator.cc
tools/gyp/v8.gyp

index b81efcb..efdd15c 100644 (file)
@@ -695,7 +695,7 @@ SIMPLE_OPTIONS = {
   },
   'cppprofilesprocessor': {
     'values': ['on', 'off'],
-    'default': 'off',
+    'default': 'on',
     'help': 'enable C++ profiles processor'
   },
   'debuggersupport': {
index 0e83315..036e110 100644 (file)
@@ -39,28 +39,40 @@ namespace v8 {
 namespace internal {
 
 void CodeCreateEventRecord::UpdateCodeMap(CodeMap* code_map) {
-    code_map->AddCode(start, entry, size);
+  code_map->AddCode(start, entry, size);
 }
 
 
 void CodeMoveEventRecord::UpdateCodeMap(CodeMap* code_map) {
-    code_map->MoveCode(from, to);
+  code_map->MoveCode(from, to);
 }
 
 
 void CodeDeleteEventRecord::UpdateCodeMap(CodeMap* code_map) {
-    code_map->DeleteCode(start);
+  code_map->DeleteCode(start);
 }
 
 
 void CodeAliasEventRecord::UpdateCodeMap(CodeMap* code_map) {
-    code_map->AddAlias(alias, start);
+  code_map->AddAlias(alias, start);
+}
+
+
+TickSampleEventRecord* TickSampleEventRecord::init(void* value) {
+  TickSampleEventRecord* result =
+      reinterpret_cast<TickSampleEventRecord*>(value);
+  result->filler = 1;
+  ASSERT(result->filler != SamplingCircularQueue::kClear);
+  // Init the required fields only.
+  result->sample.pc = NULL;
+  result->sample.frames_count = 0;
+  return result;
 }
 
 
 TickSample* ProfilerEventsProcessor::TickSampleEvent() {
   TickSampleEventRecord* evt =
-      TickSampleEventRecord::cast(ticks_buffer_.Enqueue());
+      TickSampleEventRecord::init(ticks_buffer_.Enqueue());
   evt->order = enqueue_order_;  // No increment!
   return &evt->sample;
 }
index 5b86227..22937c0 100644 (file)
@@ -283,8 +283,7 @@ CpuProfile* CpuProfiler::FindProfile(unsigned uid) {
 
 
 TickSample* CpuProfiler::TickSampleEvent() {
-  ASSERT(singleton_ != NULL);
-  if (singleton_->is_profiling()) {
+  if (CpuProfiler::is_profiling()) {
     return singleton_->processor_->TickSampleEvent();
   } else {
     return NULL;
@@ -417,6 +416,9 @@ void CpuProfiler::StartCollectingProfile(String* title) {
 
 void CpuProfiler::StartProcessorIfNotStarted() {
   if (processor_ == NULL) {
+    // Disable logging when using the new implementation.
+    saved_logging_nesting_ = Logger::logging_nesting_;
+    Logger::logging_nesting_ = 0;
     generator_ = new ProfileGenerator(profiles_);
     processor_ = new ProfilerEventsProcessor(generator_);
     processor_->Start();
@@ -428,7 +430,7 @@ void CpuProfiler::StartProcessorIfNotStarted() {
       Logger::LogAccessorCallbacks();
     }
     // Enable stack sampling.
-    Logger::ticker_->Start();
+    reinterpret_cast<Sampler*>(Logger::ticker_)->Start();
   }
 }
 
@@ -451,13 +453,14 @@ CpuProfile* CpuProfiler::StopCollectingProfile(String* title) {
 
 void CpuProfiler::StopProcessorIfLastProfile() {
   if (profiles_->is_last_profile()) {
-    Logger::ticker_->Stop();
+    reinterpret_cast<Sampler*>(Logger::ticker_)->Stop();
     processor_->Stop();
     processor_->Join();
     delete processor_;
     delete generator_;
     processor_ = NULL;
     generator_ = NULL;
+    Logger::logging_nesting_ = saved_logging_nesting_;
   }
 }
 
index 5f263d1..594e44e 100644 (file)
@@ -103,18 +103,21 @@ class CodeAliasEventRecord : public CodeEventRecord {
 
 class TickSampleEventRecord BASE_EMBEDDED {
  public:
-  // In memory, the first machine word of a TickSampleEventRecord will be the
-  // first entry of TickSample, that is -- the VM state field.
-  // TickSample is put first, because 'order' can become equal to
-  // SamplingCircularQueue::kClear, while VM state can't, see
-  // the definition of 'enum StateTag'.
-  TickSample sample;
+  // The first machine word of a TickSampleEventRecord must not ever
+  // become equal to SamplingCircularQueue::kClear.  As both order and
+  // TickSample's first field are not reliable in this sense (order
+  // can overflow, TickSample can have all fields reset), we are
+  // forced to use an artificial filler field.
+  int filler;
   unsigned order;
+  TickSample sample;
 
   static TickSampleEventRecord* cast(void* value) {
     return reinterpret_cast<TickSampleEventRecord*>(value);
   }
 
+  INLINE(static TickSampleEventRecord* init(void* value));
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(TickSampleEventRecord);
 };
@@ -256,6 +259,7 @@ class CpuProfiler {
   unsigned next_profile_uid_;
   ProfileGenerator* generator_;
   ProfilerEventsProcessor* processor_;
+  int saved_logging_nesting_;
 
   static CpuProfiler* singleton_;
 
index cd2a6c1..2e2074b 100644 (file)
@@ -391,7 +391,7 @@ DEFINE_bool(prof_auto, true,
 DEFINE_bool(prof_lazy, false,
             "Used with --prof, only does sampling and logging"
             " when profiler is active (implies --noprof_auto).")
-DEFINE_bool(prof_browser_mode, false,
+DEFINE_bool(prof_browser_mode, true,
             "Used with --prof, turns on browser-compatible mode for profiling.")
 DEFINE_bool(log_regexp, false, "Log regular expression execution.")
 DEFINE_bool(sliding_state_window, false,
index fe08ada..3d48e2d 100644 (file)
@@ -458,7 +458,7 @@ struct AccessorDescriptor {
 
 // Logging and profiling.
 // A StateTag represents a possible state of the VM.  When compiled with
-// ENABLE_LOGGING_AND_PROFILING, the logger maintains a stack of these.
+// ENABLE_VMSTATE_TRACKING, the logger maintains a stack of these.
 // Creating a VMState object enters a state by pushing on the stack, and
 // destroying a VMState object leaves a state by popping the current state
 // from the stack.
@@ -471,11 +471,6 @@ struct AccessorDescriptor {
   V(EXTERNAL)
 
 enum StateTag {
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
-  // This is to ensure that VM state field value of TickSample
-  // never gets equal to SamplingCircularQueue::kClear.
-  NULL_STATE = 0,
-#endif
 #define DEF_STATE_TAG(name) name,
   STATE_TAG_LIST(DEF_STATE_TAG)
 #undef DEF_STATE_TAG
index 34c9633..e1ebc87 100644 (file)
@@ -181,8 +181,6 @@ void StackTracer::Trace(TickSample* sample) {
 // Ticker used to provide ticks to the profiler and the sliding state
 // window.
 //
-#ifndef ENABLE_CPP_PROFILES_PROCESSOR
-
 class Ticker: public Sampler {
  public:
   explicit Ticker(int interval):
@@ -224,8 +222,6 @@ class Ticker: public Sampler {
   Profiler* profiler_;
 };
 
-#endif  // ENABLE_CPP_PROFILES_PROCESSOR
-
 
 //
 // SlidingStateWindow implementation.
@@ -1508,11 +1504,6 @@ bool Logger::Setup() {
     }
   }
 
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
-  // Disable old logging, as we are using the same '--prof' flag.
-  logging_nesting_ = 0;
-#endif
-
   LogMessageBuilder::set_write_failure_handler(StopLoggingAndProfiling);
 
   return true;
index fb93403..b54428a 100644 (file)
--- a/src/log.h
+++ b/src/log.h
@@ -87,7 +87,7 @@ class CompressionHelper;
 #define LOG(Call) ((void) 0)
 #endif
 
-#define LOG_EVENTS_AND_TAGS_LIST(V) \
+#define LOG_EVENTS_AND_TAGS_LIST_NO_NATIVES(V) \
   V(CODE_CREATION_EVENT,            "code-creation",          "cc")       \
   V(CODE_MOVE_EVENT,                "code-move",              "cm")       \
   V(CODE_DELETE_EVENT,              "code-delete",            "cd")       \
@@ -118,17 +118,24 @@ class CompressionHelper;
   V(STORE_IC_TAG,                   "StoreIC",                "sic")      \
   V(STUB_TAG,                       "Stub",                   "s")
 
+#ifdef ENABLE_CPP_PROFILES_PROCESSOR
+// Add 'NATIVE_' cases for functions and scripts, but map them to
+// original tags when writing to the log.
+#define LOG_EVENTS_AND_TAGS_LIST(V) \
+  LOG_EVENTS_AND_TAGS_LIST_NO_NATIVES(V)                                  \
+  V(NATIVE_FUNCTION_TAG,            "Function",               "f")        \
+  V(NATIVE_LAZY_COMPILE_TAG,        "LazyCompile",            "lc")       \
+  V(NATIVE_SCRIPT_TAG,              "Script",                 "sc")
+#else
+#define LOG_EVENTS_AND_TAGS_LIST(V) LOG_EVENTS_AND_TAGS_LIST_NO_NATIVES(V)
+#endif
+
 class Logger {
  public:
 #define DECLARE_ENUM(enum_item, ignore1, ignore2) enum_item,
   enum LogEventsAndTags {
     LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM)
     NUMBER_OF_LOG_EVENTS
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
-    , NATIVE_FUNCTION_TAG
-    , NATIVE_LAZY_COMPILE_TAG
-    , NATIVE_SCRIPT_TAG
-#endif
   };
 #undef DECLARE_ENUM
 
@@ -365,26 +372,6 @@ class StackTracer : public AllStatic {
   static void Trace(TickSample* sample);
 };
 
-
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
-
-class Ticker: public Sampler {
- public:
-  explicit Ticker(int interval):
-      Sampler(interval, FLAG_prof) {}
-
-  void SampleStack(TickSample* sample) {
-    StackTracer::Trace(sample);
-  }
-  void Tick(TickSample* sample) { }
-  void SetWindow(SlidingStateWindow* window) { }
-  void ClearWindow() { }
-  void SetProfiler(Profiler* profiler) { }
-  void ClearProfiler() { }
-};
-
-#endif  // ENABLE_CPP_PROFILES_PROCESSOR
-
 } }  // namespace v8::internal
 
 
index 9bba93b..185b2fe 100644 (file)
@@ -727,15 +727,12 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
   if (signal != SIGPROF) return;
   if (active_sampler_ == NULL) return;
 
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
-  TickSample* sample = CpuProfiler::TickSampleEvent();
-  if (sample == NULL) return;
-  sample->pc = NULL;  // Impossible value if sampling succeeds.
-  sample->frames_count = 0;
-#else
   TickSample sample_obj;
-  TickSample* sample = &sample_obj;
+  TickSample* sample = NULL;
+#ifdef ENABLE_CPP_PROFILES_PROCESSOR
+  sample = CpuProfiler::TickSampleEvent();
 #endif
+  if (sample == NULL) sample = &sample_obj;
 
   // We always sample the VM state.
   sample->state = VMState::current_state();
@@ -771,10 +768,9 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
       active_sampler_->SampleStack(sample);
     }
   }
-#ifndef ENABLE_CPP_PROFILES_PROCESSOR
+
   active_sampler_->Tick(sample);
 #endif
-#endif
 }
 
 
index b3ee49e..e50517c 100644 (file)
@@ -546,15 +546,12 @@ class Sampler::PlatformData : public Malloced {
   void Runner() {
     // Loop until the sampler is disengaged, keeping the specified samling freq.
     for ( ; sampler_->IsActive(); OS::Sleep(sampler_->interval_)) {
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
-      TickSample* sample = CpuProfiler::TickSampleEvent();
-      if (sample == NULL) continue;
-      sample->pc = NULL;  // Impossible value if sampling succeeds.
-      sample->frames_count = 0;
-#else
       TickSample sample_obj;
-      TickSample* sample = &sample_obj;
-#endif  // ENABLE_CPP_PROFILES_PROCESSOR
+      TickSample* sample = NULL;
+#ifdef ENABLE_CPP_PROFILES_PROCESSOR
+      sample = CpuProfiler::TickSampleEvent();
+#endif
+      if (sample == NULL) sample = &sample_obj;
 
       // We always sample the VM state.
       sample->state = VMState::current_state();
@@ -595,10 +592,8 @@ class Sampler::PlatformData : public Malloced {
         thread_resume(profiled_thread_);
       }
 
-#ifndef ENABLE_CPP_PROFILES_PROCESSOR
       // Invoke tick handler with program counter and stack pointer.
       sampler_->Tick(sample);
-#endif
     }
   }
 };
index fcf1f8f..7f3d95a 100644 (file)
@@ -1805,15 +1805,12 @@ class Sampler::PlatformData : public Malloced {
     memset(&context, 0, sizeof(context));
     // Loop until the sampler is disengaged, keeping the specified samling freq.
     for ( ; sampler_->IsActive(); Sleep(sampler_->interval_)) {
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
-      TickSample* sample = CpuProfiler::TickSampleEvent();
-      if (sample == NULL) continue;
-      sample->pc = NULL;  // Impossible value if sampling succeeds.
-      sample->frames_count = 0;
-#else
       TickSample sample_obj;
-      TickSample* sample = &sample_obj;
-#endif  // ENABLE_CPP_PROFILES_PROCESSOR
+      TickSample* sample = NULL;
+#ifdef ENABLE_CPP_PROFILES_PROCESSOR
+      sample = CpuProfiler::TickSampleEvent();
+#endif
+      if (sample == NULL) sample = &sample_obj;
 
       // We always sample the VM state.
       sample->state = VMState::current_state();
@@ -1836,10 +1833,8 @@ class Sampler::PlatformData : public Malloced {
         ResumeThread(profiled_thread_);
       }
 
-#ifndef ENABLE_CPP_PROFILES_PROCESSOR
       // Invoke tick handler with program counter and stack pointer.
       sampler_->Tick(sample);
-#endif
     }
   }
 };
index dd98e61..b000c05 100644 (file)
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -62,12 +62,6 @@ bool V8::Initialize(Deserializer* des) {
 
   CpuProfiler::Setup();
 
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
-  if (FLAG_prof && FLAG_prof_auto) {
-    CpuProfiler::StartProfiling("internal.auto");
-  }
-#endif
-
   // Setup the platform OS support.
   OS::Setup();
 
@@ -143,12 +137,6 @@ void V8::SetFatalError() {
 void V8::TearDown() {
   if (!has_been_setup_ || has_been_disposed_) return;
 
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
-  if (FLAG_prof && FLAG_prof_auto) {
-    CpuProfiler::StopProfiling("internal.auto");
-  }
-#endif
-
   OProfileAgent::TearDown();
 
   if (FLAG_preemption) {
index a8f5b16..4e4cf28 100644 (file)
@@ -47,7 +47,6 @@ static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
                                    i::Address frame2 = NULL,
                                    i::Address frame3 = NULL) {
   i::TickSample* sample = proc->TickSampleEvent();
-  sample->state = i::OTHER;
   sample->pc = frame1;
   sample->function = frame1;
   sample->frames_count = 0;
@@ -61,8 +60,28 @@ static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
   }
 }
 
+namespace {
+
+class TestSetup {
+ public:
+  TestSetup()
+      : old_flag_prof_browser_mode_(i::FLAG_prof_browser_mode) {
+    i::FLAG_prof_browser_mode = false;
+  }
+
+  ~TestSetup() {
+    i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_;
+  }
+
+ private:
+  bool old_flag_prof_browser_mode_;
+};
+
+}  // namespace
+
 TEST(CodeEvents) {
   InitializeVM();
+  TestSetup test_setup;
   CpuProfilesCollection profiles;
   profiles.StartProfiling("", 1);
   ProfileGenerator generator(&profiles);
@@ -129,6 +148,7 @@ static int CompareProfileNodes(const T* p1, const T* p2) {
 }
 
 TEST(TickEvents) {
+  TestSetup test_setup;
   CpuProfilesCollection profiles;
   profiles.StartProfiling("", 1);
   ProfileGenerator generator(&profiles);
index 2e45994..15a5b5a 100644 (file)
@@ -367,7 +367,27 @@ TEST(CodeMapMoveAndDeleteCode) {
 }
 
 
+namespace {
+
+class TestSetup {
+ public:
+  TestSetup()
+      : old_flag_prof_browser_mode_(i::FLAG_prof_browser_mode) {
+    i::FLAG_prof_browser_mode = false;
+  }
+
+  ~TestSetup() {
+    i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_;
+  }
+
+ private:
+  bool old_flag_prof_browser_mode_;
+};
+
+}  // namespace
+
 TEST(RecordTickSample) {
+  TestSetup test_setup;
   CpuProfilesCollection profiles;
   profiles.StartProfiling("", 1);
   ProfileGenerator generator(&profiles);
index be8a81c..7897e35 100644 (file)
@@ -38,6 +38,7 @@
       'ENABLE_LOGGING_AND_PROFILING',
       'ENABLE_DEBUGGER_SUPPORT',
       'ENABLE_VMSTATE_TRACKING',
+      'ENABLE_CPP_PROFILES_PROCESSOR',
     ],
     'conditions': [
       ['target_arch=="arm"', {