Allow new CPU profiling subsystem to coexist nicely with the old one.

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
parent 400b1be4
......@@ -695,7 +695,7 @@ SIMPLE_OPTIONS = {
},
'cppprofilesprocessor': {
'values': ['on', 'off'],
'default': 'off',
'default': 'on',
'help': 'enable C++ profiles processor'
},
'debuggersupport': {
......
......@@ -58,9 +58,21 @@ void CodeAliasEventRecord::UpdateCodeMap(CodeMap* code_map) {
}
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;
}
......
......@@ -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_;
}
}
......
......@@ -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_;
......
......@@ -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,
......
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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
}
......
......@@ -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
}
}
};
......
......@@ -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
}
}
};
......
......@@ -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) {
......
......@@ -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);
......
......@@ -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);
......
......@@ -38,6 +38,7 @@
'ENABLE_LOGGING_AND_PROFILING',
'ENABLE_DEBUGGER_SUPPORT',
'ENABLE_VMSTATE_TRACKING',
'ENABLE_CPP_PROFILES_PROCESSOR',
],
'conditions': [
['target_arch=="arm"', {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment