Commit a7e816db authored by alph@chromium.org's avatar alph@chromium.org

Introduce a separate event for CodeDeopt

The reuse of CodeCreateEvent for deopt events caused a CodeCreateEvent
fired twice for a code object. When the event was processed for the first
time it seized the no-fp-ranges from code object, so the second event
had no ranges info leaving code entry without them.
As a result when a cpu profile sample falls into the region it missed the
2nd stack frame.

LOG=N
BUG=
R=bmeurer@chromium.org, loislo@chromium.org

Review URL: https://codereview.chromium.org/290093005

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21418 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 6683b4b9
...@@ -28,6 +28,14 @@ void CodeMoveEventRecord::UpdateCodeMap(CodeMap* code_map) { ...@@ -28,6 +28,14 @@ void CodeMoveEventRecord::UpdateCodeMap(CodeMap* code_map) {
} }
void CodeDisableOptEventRecord::UpdateCodeMap(CodeMap* code_map) {
CodeEntry* entry = code_map->FindEntry(start);
if (entry != NULL) {
entry->set_bailout_reason(bailout_reason);
}
}
void SharedFunctionInfoMoveEventRecord::UpdateCodeMap(CodeMap* code_map) { void SharedFunctionInfoMoveEventRecord::UpdateCodeMap(CodeMap* code_map) {
code_map->MoveCode(from, to); code_map->MoveCode(from, to);
} }
......
...@@ -304,6 +304,15 @@ void CpuProfiler::CodeMoveEvent(Address from, Address to) { ...@@ -304,6 +304,15 @@ void CpuProfiler::CodeMoveEvent(Address from, Address to) {
} }
void CpuProfiler::CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_DISABLE_OPT);
CodeDisableOptEventRecord* rec = &evt_rec.CodeDisableOptEventRecord_;
rec->start = code->address();
rec->bailout_reason = GetBailoutReason(shared->DisableOptimizationReason());
processor_->Enqueue(evt_rec);
}
void CpuProfiler::CodeDeleteEvent(Address from) { void CpuProfiler::CodeDeleteEvent(Address from) {
} }
......
...@@ -26,6 +26,7 @@ class ProfileGenerator; ...@@ -26,6 +26,7 @@ class ProfileGenerator;
#define CODE_EVENTS_TYPE_LIST(V) \ #define CODE_EVENTS_TYPE_LIST(V) \
V(CODE_CREATION, CodeCreateEventRecord) \ V(CODE_CREATION, CodeCreateEventRecord) \
V(CODE_MOVE, CodeMoveEventRecord) \ V(CODE_MOVE, CodeMoveEventRecord) \
V(CODE_DISABLE_OPT, CodeDisableOptEventRecord) \
V(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord) \ V(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord) \
V(REPORT_BUILTIN, ReportBuiltinEventRecord) V(REPORT_BUILTIN, ReportBuiltinEventRecord)
...@@ -65,6 +66,15 @@ class CodeMoveEventRecord : public CodeEventRecord { ...@@ -65,6 +66,15 @@ class CodeMoveEventRecord : public CodeEventRecord {
}; };
class CodeDisableOptEventRecord : public CodeEventRecord {
public:
Address start;
const char* bailout_reason;
INLINE(void UpdateCodeMap(CodeMap* code_map));
};
class SharedFunctionInfoMoveEventRecord : public CodeEventRecord { class SharedFunctionInfoMoveEventRecord : public CodeEventRecord {
public: public:
Address from; Address from;
...@@ -225,6 +235,7 @@ class CpuProfiler : public CodeEventListener { ...@@ -225,6 +235,7 @@ class CpuProfiler : public CodeEventListener {
Code* code, int args_count); Code* code, int args_count);
virtual void CodeMovingGCEvent() {} virtual void CodeMovingGCEvent() {}
virtual void CodeMoveEvent(Address from, Address to); virtual void CodeMoveEvent(Address from, Address to);
virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared);
virtual void CodeDeleteEvent(Address from); virtual void CodeDeleteEvent(Address from);
virtual void GetterCallbackEvent(Name* name, Address entry_point); virtual void GetterCallbackEvent(Name* name, Address entry_point);
virtual void RegExpCodeCreateEvent(Code* code, String* source); virtual void RegExpCodeCreateEvent(Code* code, String* source);
......
...@@ -230,6 +230,7 @@ class PerfBasicLogger : public CodeEventLogger { ...@@ -230,6 +230,7 @@ class PerfBasicLogger : public CodeEventLogger {
virtual ~PerfBasicLogger(); virtual ~PerfBasicLogger();
virtual void CodeMoveEvent(Address from, Address to) { } virtual void CodeMoveEvent(Address from, Address to) { }
virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
virtual void CodeDeleteEvent(Address from) { } virtual void CodeDeleteEvent(Address from) { }
private: private:
...@@ -295,6 +296,7 @@ class PerfJitLogger : public CodeEventLogger { ...@@ -295,6 +296,7 @@ class PerfJitLogger : public CodeEventLogger {
virtual ~PerfJitLogger(); virtual ~PerfJitLogger();
virtual void CodeMoveEvent(Address from, Address to) { } virtual void CodeMoveEvent(Address from, Address to) { }
virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
virtual void CodeDeleteEvent(Address from) { } virtual void CodeDeleteEvent(Address from) { }
private: private:
...@@ -457,6 +459,7 @@ class LowLevelLogger : public CodeEventLogger { ...@@ -457,6 +459,7 @@ class LowLevelLogger : public CodeEventLogger {
virtual ~LowLevelLogger(); virtual ~LowLevelLogger();
virtual void CodeMoveEvent(Address from, Address to); virtual void CodeMoveEvent(Address from, Address to);
virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
virtual void CodeDeleteEvent(Address from); virtual void CodeDeleteEvent(Address from);
virtual void SnapshotPositionEvent(Address addr, int pos); virtual void SnapshotPositionEvent(Address addr, int pos);
virtual void CodeMovingGCEvent(); virtual void CodeMovingGCEvent();
...@@ -623,6 +626,7 @@ class JitLogger : public CodeEventLogger { ...@@ -623,6 +626,7 @@ class JitLogger : public CodeEventLogger {
explicit JitLogger(JitCodeEventHandler code_event_handler); explicit JitLogger(JitCodeEventHandler code_event_handler);
virtual void CodeMoveEvent(Address from, Address to); virtual void CodeMoveEvent(Address from, Address to);
virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
virtual void CodeDeleteEvent(Address from); virtual void CodeDeleteEvent(Address from);
virtual void AddCodeLinePosInfoEvent( virtual void AddCodeLinePosInfoEvent(
void* jit_handler_data, void* jit_handler_data,
...@@ -1446,6 +1450,24 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, ...@@ -1446,6 +1450,24 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
} }
void Logger::CodeDisableOptEvent(Code* code,
SharedFunctionInfo* shared) {
PROFILER_LOG(CodeDisableOptEvent(code, shared));
if (!is_logging_code_events()) return;
CALL_LISTENERS(CodeDisableOptEvent(code, shared));
if (!FLAG_log_code || !log_->IsEnabled()) return;
Log::MessageBuilder msg(log_);
msg.Append("%s,", kLogEventsNames[CODE_DISABLE_OPT_EVENT]);
SmartArrayPointer<char> name =
shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append("\"%s\",", name.get());
msg.Append("\"%s\"\n", GetBailoutReason(shared->DisableOptimizationReason()));
msg.WriteToLogFile();
}
void Logger::CodeMovingGCEvent() { void Logger::CodeMovingGCEvent() {
PROFILER_LOG(CodeMovingGCEvent()); PROFILER_LOG(CodeMovingGCEvent());
......
...@@ -79,6 +79,7 @@ struct TickSample; ...@@ -79,6 +79,7 @@ struct TickSample;
#define LOG_EVENTS_AND_TAGS_LIST(V) \ #define LOG_EVENTS_AND_TAGS_LIST(V) \
V(CODE_CREATION_EVENT, "code-creation") \ V(CODE_CREATION_EVENT, "code-creation") \
V(CODE_DISABLE_OPT_EVENT, "code-disable-optimization") \
V(CODE_MOVE_EVENT, "code-move") \ V(CODE_MOVE_EVENT, "code-move") \
V(CODE_DELETE_EVENT, "code-delete") \ V(CODE_DELETE_EVENT, "code-delete") \
V(CODE_MOVING_GC, "code-moving-gc") \ V(CODE_MOVING_GC, "code-moving-gc") \
...@@ -237,6 +238,8 @@ class Logger { ...@@ -237,6 +238,8 @@ class Logger {
CompilationInfo* info, CompilationInfo* info,
Name* source, int line, int column); Name* source, int line, int column);
void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count); void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
// Emits a code deoptimization event.
void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared);
void CodeMovingGCEvent(); void CodeMovingGCEvent();
// Emits a code create event for a RegExp. // Emits a code create event for a RegExp.
void RegExpCodeCreateEvent(Code* code, String* source); void RegExpCodeCreateEvent(Code* code, String* source);
...@@ -470,6 +473,7 @@ class CodeEventListener { ...@@ -470,6 +473,7 @@ class CodeEventListener {
virtual void CodeDeleteEvent(Address from) = 0; virtual void CodeDeleteEvent(Address from) = 0;
virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0; virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0;
virtual void CodeMovingGCEvent() = 0; virtual void CodeMovingGCEvent() = 0;
virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) = 0;
}; };
......
...@@ -10706,9 +10706,7 @@ void SharedFunctionInfo::DisableOptimization(BailoutReason reason) { ...@@ -10706,9 +10706,7 @@ void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
if (code()->kind() == Code::FUNCTION) { if (code()->kind() == Code::FUNCTION) {
code()->set_optimizable(false); code()->set_optimizable(false);
} }
PROFILE(GetIsolate(), PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
LogExistingFunction(Handle<SharedFunctionInfo>(this),
Handle<Code>(code())));
if (FLAG_trace_opt) { if (FLAG_trace_opt) {
PrintF("[disabled optimization for "); PrintF("[disabled optimization for ");
ShortPrint(); ShortPrint();
......
...@@ -630,6 +630,9 @@ class CodeAddressMap: public CodeEventLogger { ...@@ -630,6 +630,9 @@ class CodeAddressMap: public CodeEventLogger {
address_to_name_map_.Move(from, to); address_to_name_map_.Move(from, to);
} }
virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) {
}
virtual void CodeDeleteEvent(Address from) { virtual void CodeDeleteEvent(Address from) {
address_to_name_map_.Remove(from); address_to_name_map_.Remove(from);
} }
......
...@@ -587,6 +587,72 @@ TEST(CollectCpuProfile) { ...@@ -587,6 +587,72 @@ TEST(CollectCpuProfile) {
} }
static const char* hot_deopt_no_frame_entry_test_source =
"function foo(a, b) {\n"
" try {\n"
" return a + b;\n"
" } catch (e) { }\n"
"}\n"
"function start(timeout) {\n"
" var start = Date.now();\n"
" do {\n"
" for (var i = 1; i < 1000; ++i) foo(1, i);\n"
" var duration = Date.now() - start;\n"
" } while (duration < timeout);\n"
" return duration;\n"
"}\n";
// Check that the profile tree for the script above will look like the
// following:
//
// [Top down]:
// 1062 0 (root) [-1]
// 1054 0 start [-1]
// 1054 1 foo [-1]
// 2 2 (program) [-1]
// 6 6 (garbage collector) [-1]
//
// The test checks no FP ranges are present in a deoptimized funcion.
// If 'foo' has no ranges the samples falling into the prologue will miss the
// 'start' function on the stack, so 'foo' will be attached to the (root).
TEST(HotDeoptNoFrameEntry) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
v8::Script::Compile(v8::String::NewFromUtf8(
env->GetIsolate(),
hot_deopt_no_frame_entry_test_source))->Run();
v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
int32_t profiling_interval_ms = 200;
v8::Handle<v8::Value> args[] = {
v8::Integer::New(env->GetIsolate(), profiling_interval_ms)
};
v8::CpuProfile* profile =
RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 200);
function->Call(env->Global(), ARRAY_SIZE(args), args);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
ScopedVector<v8::Handle<v8::String> > names(3);
names[0] = v8::String::NewFromUtf8(
env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
ProfileGenerator::kProgramEntryName);
names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
CheckChildrenNames(root, names);
const v8::CpuProfileNode* startNode =
GetChild(env->GetIsolate(), root, "start");
CHECK_EQ(1, startNode->GetChildrenCount());
GetChild(env->GetIsolate(), startNode, "foo");
profile->Delete();
}
TEST(CollectCpuProfileSamples) { TEST(CollectCpuProfileSamples) {
LocalContext env; LocalContext env;
v8::HandleScope scope(env->GetIsolate()); v8::HandleScope scope(env->GetIsolate());
......
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