Improve the JitCodeEventHandler API to add support for line position information.
authordanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 18 Feb 2013 18:06:12 +0000 (18:06 +0000)
committerdanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 18 Feb 2013 18:06:12 +0000 (18:06 +0000)
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

include/v8.h
src/assembler.cc
src/assembler.h
src/full-codegen.cc
src/lithium.cc
src/log.cc
src/log.h
test/cctest/test-api.cc

index abd055a..dd9c548 100644 (file)
@@ -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;
   };
index e284974..b4958f5 100644 (file)
@@ -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));
 }
 
 
index be88a3c..890ef69 100644 (file)
@@ -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);
index b49337a..a43f674 100644 (file)
@@ -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();
 }
 
index 45ba0e0..e216542 100644 (file)
@@ -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;
   }
index 99425a6..2ed0141 100644 (file)
@@ -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;
index 2183160..9532e8b 100644 (file)
--- a/src/log.h
+++ b/src/log.h
@@ -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();
 
index 12d44af..7dd9fc7 100644 (file)
@@ -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