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.
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.
// 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;
};
gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, false);
}
#endif
+ LOG_CODE_EVENT(assembler_->isolate(),
+ CodeLinePosInfoAddPositionEvent(jit_handler_data_,
+ assembler_->pc_offset(),
+ pos));
}
gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, true);
}
#endif
+ LOG_CODE_EVENT(assembler_->isolate(),
+ CodeLinePosInfoAddStatementPositionEvent(
+ jit_handler_data_,
+ assembler_->pc_offset(),
+ pos));
}
#ifdef ENABLE_GDB_JIT_INTERFACE
gdbjit_lineinfo_ = NULL;
#endif
+ jit_handler_data_ = NULL;
}
#ifdef ENABLE_GDB_JIT_INTERFACE
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);
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);
#ifdef ENABLE_GDB_JIT_INTERFACE
masm.positions_recorder()->StartGDBJITLineInfoRecording();
#endif
+ LOG_CODE_EVENT(isolate,
+ CodeStartLinePosInfoRecordEvent(masm.positions_recorder()));
FullCodeGenerator cgen(&masm, info);
cgen.Generate();
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();
}
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();
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;
}
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;
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] = {
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) {
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) {
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) {
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) {
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) {
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) {
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;
class Semaphore;
class Ticker;
class Isolate;
+class PositionsRecorder;
#undef LOG
#define LOG(isolate, Call) \
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);
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;
}
~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();
static i::HashMap* code_map = NULL;
+static i::HashMap* jitcode_line_info = NULL;
static int saw_bar = 0;
static int move_events = 0;
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: {
// 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);
i::HashMap code(MatchPointers);
code_map = &code;
+ i::HashMap lineinfo(MatchPointers);
+ jitcode_line_info = &lineinfo;
+
saw_bar = 0;
move_events = 0;
CHECK_LT(0, move_events);
code_map = NULL;
+ jitcode_line_info = NULL;
}
isolate->Exit();
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