Commit be8e8f75 authored by danno@chromium.org's avatar danno@chromium.org

Improve the JitCodeEventHandler API to add support for line position information.

This includes:

* adding the CODE_ADD_LINE_POS_INFO, CODE_START_LINE_INFO_RECORDING, CODE_END_LINE_INFO_RECORDING event and the corresponding functionality.
 * adding the JITCodeLineInfo struct to record the code line info. I added this definition because Danno mentioned that "we'd like to cleanup and decouple the external debugging functionality"
 * some other small changes.

Review URL: https://chromiumcodereview.appspot.com/12223027
Patch from Chunyang Dai <chunyang.dai@intel.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13686 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 261def53
......@@ -3040,7 +3040,19 @@ struct JitCodeEvent {
enum EventType {
CODE_ADDED,
CODE_MOVED,
CODE_REMOVED
CODE_REMOVED,
CODE_ADD_LINE_POS_INFO,
CODE_START_LINE_INFO_RECORDING,
CODE_END_LINE_INFO_RECORDING
};
// Definition of the code position type. The "POSITION" type means the place
// in the source code which are of interest when making stack traces to
// pin-point the source location of a stack frame as close as possible.
// The "STATEMENT_POSITION" means the place at the beginning of each
// statement, and is used to indicate possible break locations.
enum PositionType {
POSITION,
STATEMENT_POSITION
};
// Type of event.
......@@ -3049,6 +3061,13 @@ struct JitCodeEvent {
void* code_start;
// Size of the instructions.
size_t code_len;
// Script info for CODE_ADDED event.
Handle<Script> script;
// User-defined data for *_LINE_INFO_* event. It's used to hold the source
// code line information which is returned from the
// CODE_START_LINE_INFO_RECORDING event. And it's passed to subsequent
// CODE_ADD_LINE_POS_INFO and CODE_END_LINE_INFO_RECORDING events.
void* user_data;
union {
// Only valid for CODE_ADDED.
......@@ -3059,6 +3078,17 @@ struct JitCodeEvent {
// Number of chars in str.
size_t len;
} name;
// Only valid for CODE_ADD_LINE_POS_INFO
struct {
// PC offset
size_t offset;
// Code postion
size_t pos;
// The position type.
PositionType position_type;
} line_info;
// New location of instructions. Only valid for CODE_MOVED.
void* new_code_start;
};
......
......@@ -1522,6 +1522,10 @@ void PositionsRecorder::RecordPosition(int pos) {
gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, false);
}
#endif
LOG_CODE_EVENT(assembler_->isolate(),
CodeLinePosInfoAddPositionEvent(jit_handler_data_,
assembler_->pc_offset(),
pos));
}
......@@ -1534,6 +1538,11 @@ void PositionsRecorder::RecordStatementPosition(int pos) {
gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, true);
}
#endif
LOG_CODE_EVENT(assembler_->isolate(),
CodeLinePosInfoAddStatementPositionEvent(
jit_handler_data_,
assembler_->pc_offset(),
pos));
}
......
......@@ -844,6 +844,7 @@ class PositionsRecorder BASE_EMBEDDED {
#ifdef ENABLE_GDB_JIT_INTERFACE
gdbjit_lineinfo_ = NULL;
#endif
jit_handler_data_ = NULL;
}
#ifdef ENABLE_GDB_JIT_INTERFACE
......@@ -863,7 +864,15 @@ class PositionsRecorder BASE_EMBEDDED {
return lineinfo;
}
#endif
void AttachJITHandlerData(void* user_data) {
jit_handler_data_ = user_data;
}
void* DetachJITHandlerData() {
void* old_data = jit_handler_data_;
jit_handler_data_ = NULL;
return old_data;
}
// Set current position to pos.
void RecordPosition(int pos);
......@@ -886,6 +895,9 @@ class PositionsRecorder BASE_EMBEDDED {
GDBJITLineInfo* gdbjit_lineinfo_;
#endif
// Currently jit_handler_data_ is used to store JITHandler-specific data
// over the lifetime of a PositionsRecorder
void* jit_handler_data_;
friend class PreservePositionScope;
DISALLOW_COPY_AND_ASSIGN(PositionsRecorder);
......
......@@ -307,6 +307,8 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
#ifdef ENABLE_GDB_JIT_INTERFACE
masm.positions_recorder()->StartGDBJITLineInfoRecording();
#endif
LOG_CODE_EVENT(isolate,
CodeStartLinePosInfoRecordEvent(masm.positions_recorder()));
FullCodeGenerator cgen(&masm, info);
cgen.Generate();
......@@ -344,6 +346,11 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
GDBJIT(RegisterDetailedLineInfo(*code, lineinfo));
}
#endif
if (!code.is_null()) {
void* line_info =
masm.positions_recorder()->DetachJITHandlerData();
LOG_CODE_EVENT(isolate, CodeEndLinePosInfoRecordEvent(*code, line_info));
}
return !code.is_null();
}
......
......@@ -444,6 +444,9 @@ LChunk* LChunk::NewChunk(HGraph* graph) {
Handle<Code> LChunk::Codegen(Code::Kind kind) {
MacroAssembler assembler(info()->isolate(), NULL, 0);
LOG_CODE_EVENT(info()->isolate(),
CodeStartLinePosInfoRecordEvent(
assembler.positions_recorder()));
LCodeGen generator(this, &assembler, info());
MarkEmptyBlocks();
......@@ -457,6 +460,14 @@ Handle<Code> LChunk::Codegen(Code::Kind kind) {
Handle<Code> code =
CodeGenerator::MakeCodeEpilogue(&assembler, flags, info());
generator.FinishCode(code);
if (!code.is_null()) {
void* jit_handler_data =
assembler.positions_recorder()->DetachJITHandlerData();
LOG_CODE_EVENT(info()->isolate(),
CodeEndLinePosInfoRecordEvent(*code, jit_handler_data));
}
CodeGenerator::PrintCode(code, info());
return code;
}
......
......@@ -469,12 +469,17 @@ Logger::~Logger() {
void Logger::IssueCodeAddedEvent(Code* code,
Script* script,
const char* name,
size_t name_len) {
JitCodeEvent event;
memset(&event, 0, sizeof(event));
event.type = JitCodeEvent::CODE_ADDED;
event.code_start = code->instruction_start();
event.code_len = code->instruction_size();
Handle<Script> script_handle =
script != NULL ? Handle<Script>(script) : Handle<Script>();
event.script = v8::Handle<v8::Script>(ToApi<v8::Script>(script_handle));
event.name.str = name;
event.name.len = name_len;
......@@ -513,6 +518,40 @@ void Logger::IssueCodeRemovedEvent(Address from) {
code_event_handler_(&event);
}
void Logger::IssueAddCodeLinePosInfoEvent(
void* jit_handler_data,
int pc_offset,
int position,
JitCodeEvent::PositionType position_type) {
JitCodeEvent event;
memset(&event, 0, sizeof(event));
event.type = JitCodeEvent::CODE_ADD_LINE_POS_INFO;
event.user_data = jit_handler_data;
event.line_info.offset = pc_offset;
event.line_info.pos = position;
event.line_info.position_type = position_type;
code_event_handler_(&event);
}
void* Logger::IssueStartCodePosInfoEvent() {
JitCodeEvent event;
memset(&event, 0, sizeof(event));
event.type = JitCodeEvent::CODE_START_LINE_INFO_RECORDING;
code_event_handler_(&event);
return event.user_data;
}
void Logger::IssueEndCodePosInfoEvent(Code* code, void* jit_handler_data) {
JitCodeEvent event;
memset(&event, 0, sizeof(event));
event.type = JitCodeEvent::CODE_END_LINE_INFO_RECORDING;
event.code_start = code->instruction_start();
event.user_data = jit_handler_data;
code_event_handler_(&event);
}
#define DECLARE_EVENT(ignore1, name) name,
static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
......@@ -884,7 +923,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
name_buffer_->AppendBytes(comment);
}
if (code_event_handler_ != NULL) {
IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
IssueCodeAddedEvent(code, NULL, name_buffer_->get(), name_buffer_->size());
}
if (!log_->IsEnabled()) return;
if (FLAG_ll_prof) {
......@@ -924,7 +963,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
name_buffer_->AppendString(name);
}
if (code_event_handler_ != NULL) {
IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
IssueCodeAddedEvent(code, NULL, name_buffer_->get(), name_buffer_->size());
}
if (!log_->IsEnabled()) return;
if (FLAG_ll_prof) {
......@@ -971,7 +1010,12 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
name_buffer_->AppendString(name);
}
if (code_event_handler_ != NULL) {
IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
Script* script =
shared->script()->IsScript() ? Script::cast(shared->script()) : NULL;
IssueCodeAddedEvent(code,
script,
name_buffer_->get(),
name_buffer_->size());
}
if (!log_->IsEnabled()) return;
if (FLAG_ll_prof) {
......@@ -1021,7 +1065,12 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
name_buffer_->AppendInt(line);
}
if (code_event_handler_ != NULL) {
IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
Script* script =
shared->script()->IsScript() ? Script::cast(shared->script()) : NULL;
IssueCodeAddedEvent(code,
script,
name_buffer_->get(),
name_buffer_->size());
}
if (!log_->IsEnabled()) return;
if (FLAG_ll_prof) {
......@@ -1062,7 +1111,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) {
name_buffer_->AppendInt(args_count);
}
if (code_event_handler_ != NULL) {
IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
IssueCodeAddedEvent(code, NULL, name_buffer_->get(), name_buffer_->size());
}
if (!log_->IsEnabled()) return;
if (FLAG_ll_prof) {
......@@ -1100,7 +1149,7 @@ void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
name_buffer_->AppendString(source);
}
if (code_event_handler_ != NULL) {
IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
IssueCodeAddedEvent(code, NULL, name_buffer_->get(), name_buffer_->size());
}
if (!log_->IsEnabled()) return;
if (FLAG_ll_prof) {
......@@ -1144,6 +1193,40 @@ void Logger::CodeDeleteEvent(Address from) {
DeleteEventInternal(CODE_DELETE_EVENT, from);
}
void Logger::CodeLinePosInfoAddPositionEvent(void* jit_handler_data,
int pc_offset,
int position) {
if (code_event_handler_ != NULL) {
IssueAddCodeLinePosInfoEvent(jit_handler_data,
pc_offset,
position,
JitCodeEvent::POSITION);
}
}
void Logger::CodeLinePosInfoAddStatementPositionEvent(void* jit_handler_data,
int pc_offset,
int position) {
if (code_event_handler_ != NULL) {
IssueAddCodeLinePosInfoEvent(jit_handler_data,
pc_offset,
position,
JitCodeEvent::STATEMENT_POSITION);
}
}
void Logger::CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder) {
if (code_event_handler_ != NULL) {
pos_recorder->AttachJITHandlerData(IssueStartCodePosInfoEvent());
}
}
void Logger::CodeEndLinePosInfoRecordEvent(Code* code,
void* jit_handler_data) {
if (code_event_handler_ != NULL) {
IssueEndCodePosInfoEvent(code, jit_handler_data);
}
}
void Logger::SnapshotPositionEvent(Address addr, int pos) {
if (!log_->IsEnabled()) return;
......
......@@ -76,6 +76,7 @@ class Profiler;
class Semaphore;
class Ticker;
class Isolate;
class PositionsRecorder;
#undef LOG
#define LOG(isolate, Call) \
......@@ -246,6 +247,19 @@ class Logger {
void CodeMoveEvent(Address from, Address to);
// Emits a code delete event.
void CodeDeleteEvent(Address from);
// Emits a code line info add event with Postion type.
void CodeLinePosInfoAddPositionEvent(void* jit_handler_data,
int pc_offset,
int position);
// Emits a code line info add event with StatementPostion type.
void CodeLinePosInfoAddStatementPositionEvent(void* jit_handler_data,
int pc_offset,
int position);
// Emits a code line info start to record event
void CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder);
// Emits a code line info finish record event.
// It's the callee's responsibility to dispose the parameter jit_handler_data.
void CodeEndLinePosInfoRecordEvent(Code* code, void* jit_handler_data);
void SharedFunctionInfoMoveEvent(Address from, Address to);
......@@ -316,6 +330,10 @@ class Logger {
return logging_nesting_ > 0;
}
bool is_code_event_handler_enabled() {
return code_event_handler_ != NULL;
}
bool is_logging_code_events() {
return is_logging() || code_event_handler_ != NULL;
}
......@@ -359,10 +377,18 @@ class Logger {
~Logger();
// Issue code notifications.
void IssueCodeAddedEvent(Code* code, const char* name, size_t name_len);
void IssueCodeAddedEvent(Code* code,
Script* script,
const char* name,
size_t name_len);
void IssueCodeMovedEvent(Address from, Address to);
void IssueCodeRemovedEvent(Address from);
void IssueAddCodeLinePosInfoEvent(void* jit_handler_data,
int pc_offset,
int position,
JitCodeEvent::PositionType position_Type);
void* IssueStartCodePosInfoEvent();
void IssueEndCodePosInfoEvent(Code* code, void* jit_handler_data);
// Emits the profiler's first message.
void ProfilerBeginEvent();
......
......@@ -11588,6 +11588,7 @@ TEST(SetFunctionEntryHook) {
static i::HashMap* code_map = NULL;
static i::HashMap* jitcode_line_info = NULL;
static int saw_bar = 0;
static int move_events = 0;
......@@ -11627,6 +11628,10 @@ static bool FunctionNameIs(const char* expected,
static void event_handler(const v8::JitCodeEvent* event) {
CHECK(event != NULL);
CHECK(code_map != NULL);
CHECK(jitcode_line_info != NULL);
class DummyJitCodeLineInfo {
};
switch (event->type) {
case v8::JitCodeEvent::CODE_ADDED: {
......@@ -11675,6 +11680,43 @@ static void event_handler(const v8::JitCodeEvent* event) {
// Object/code removal events are currently not dispatched from the GC.
CHECK(false);
break;
// For CODE_START_LINE_INFO_RECORDING event, we will create one
// DummyJitCodeLineInfo data structure pointed by event->user_dat. We
// record it in jitcode_line_info.
case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
temp_event->user_data = line_info;
i::HashMap::Entry* entry =
jitcode_line_info->Lookup(line_info,
i::ComputePointerHash(line_info),
true);
entry->value = reinterpret_cast<void*>(line_info);
}
break;
// For these two events, we will check whether the event->user_data
// data structure is created before during CODE_START_LINE_INFO_RECORDING
// event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
CHECK(event->user_data != NULL);
uint32_t hash = i::ComputePointerHash(event->user_data);
i::HashMap::Entry* entry =
jitcode_line_info->Lookup(event->user_data, hash, false);
CHECK(entry != NULL);
delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
}
break;
case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
CHECK(event->user_data != NULL);
uint32_t hash = i::ComputePointerHash(event->user_data);
i::HashMap::Entry* entry =
jitcode_line_info->Lookup(event->user_data, hash, false);
CHECK(entry != NULL);
}
break;
default:
// Impossible event.
CHECK(false);
......@@ -11710,6 +11752,9 @@ TEST(SetJitCodeEventHandler) {
i::HashMap code(MatchPointers);
code_map = &code;
i::HashMap lineinfo(MatchPointers);
jitcode_line_info = &lineinfo;
saw_bar = 0;
move_events = 0;
......@@ -11743,6 +11788,7 @@ TEST(SetJitCodeEventHandler) {
CHECK_LT(0, move_events);
code_map = NULL;
jitcode_line_info = NULL;
}
isolate->Exit();
......@@ -11763,9 +11809,13 @@ TEST(SetJitCodeEventHandler) {
i::HashMap code(MatchPointers);
code_map = &code;
i::HashMap lineinfo(MatchPointers);
jitcode_line_info = &lineinfo;
V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
jitcode_line_info = NULL;
// We expect that we got some events. Note that if we could get code removal
// notifications, we could compare two collections, one created by listening
// from the time of creation of an isolate, and the other by subscribing
......
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