Rebase GDBJIT interface solely on JITCodeEvent
authorAndy Wingo <wingo@igalia.com>
Wed, 25 Feb 2015 11:49:28 +0000 (12:49 +0100)
committerAndy Wingo <wingo@igalia.com>
Wed, 25 Feb 2015 11:49:47 +0000 (11:49 +0000)
R=mstarzinger@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#26847}

src/compiler.cc
src/flag-definitions.h
src/gdb-jit.cc
src/gdb-jit.h
src/heap/mark-compact.cc

index f3f8dbd086d3288d5e51214f8cdc8a3880367203..4dbe5983e1f9e74f7af70c49ebdbaa05ec988722 100644 (file)
@@ -719,10 +719,6 @@ static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
             CodeCreateEvent(log_tag, *code, *shared, info, script_name,
                             line_num, column_num));
   }
-
-  GDBJIT(AddCode(Handle<String>(shared->DebugName()),
-                 Handle<Script>(info->script()), Handle<Code>(info->code()),
-                 info));
 }
 
 
@@ -1183,7 +1179,6 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
 
     PROFILE(isolate, CodeCreateEvent(
                 log_tag, *info->code(), *result, info, *script_name));
-    GDBJIT(AddCode(script_name, script, info->code(), info));
 
     // Hint to the runtime system used when allocating space for initial
     // property space by setting the expected number of properties for
index f1b9b052e1d53fefd350536cc9bea0848923b4e9..7e6a3a9bd020bc9da79d122b80d916290c7dbd22 100644 (file)
@@ -752,6 +752,14 @@ DEFINE_NEG_IMPLICATION(predictable, concurrent_recompilation)
 DEFINE_NEG_IMPLICATION(predictable, concurrent_osr)
 DEFINE_NEG_IMPLICATION(predictable, concurrent_sweeping)
 
+// mark-compact.cc
+DEFINE_BOOL(force_marking_deque_overflows, false,
+            "force overflows of marking deque by reducing it's size "
+            "to 64 words")
+
+DEFINE_BOOL(stress_compaction, false,
+            "stress the GC compactor to flush out bugs (implies "
+            "--force_marking_deque_overflows)")
 
 //
 // Dev shell flags
@@ -769,21 +777,24 @@ DEFINE_ARGS(js_arguments,
 //
 // GDB JIT integration flags.
 //
+#undef FLAG
+#ifdef ENABLE_GDB_JIT_INTERFACE
+#define FLAG FLAG_FULL
+#else
+#define FLAG FLAG_READONLY
+#endif
 
-DEFINE_BOOL(gdbjit, false, "enable GDBJIT interface (disables compacting GC)")
+DEFINE_BOOL(gdbjit, false, "enable GDBJIT interface")
 DEFINE_BOOL(gdbjit_full, false, "enable GDBJIT interface for all code objects")
 DEFINE_BOOL(gdbjit_dump, false, "dump elf objects with debug info to disk")
 DEFINE_STRING(gdbjit_dump_filter, "",
               "dump only objects containing this substring")
 
-// mark-compact.cc
-DEFINE_BOOL(force_marking_deque_overflows, false,
-            "force overflows of marking deque by reducing it's size "
-            "to 64 words")
-
-DEFINE_BOOL(stress_compaction, false,
-            "stress the GC compactor to flush out bugs (implies "
-            "--force_marking_deque_overflows)")
+#ifdef ENABLE_GDB_JIT_INTERFACE
+DEFINE_IMPLICATION(gdbjit_full, gdbjit)
+DEFINE_IMPLICATION(gdbjit_dump, gdbjit)
+#endif
+DEFINE_NEG_IMPLICATION(gdbjit, compact_code_space)
 
 //
 // Debug only flags
index 69b48d664486fb1a597bdc1d83efb4bec2468bad..00c7789828e99a6233d5860591d91b8ef3e41c80 100644 (file)
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifdef ENABLE_GDB_JIT_INTERFACE
 #include "src/v8.h"
 
 #include "src/base/bits.h"
 #include "src/global-handles.h"
 #include "src/messages.h"
 #include "src/natives.h"
+#include "src/objects.h"
 #include "src/ostreams.h"
-#include "src/scopes.h"
 
 namespace v8 {
 namespace internal {
+namespace GDBJITInterface {
+
+#ifdef ENABLE_GDB_JIT_INTERFACE
 
 #ifdef __APPLE__
 #define __MACH_O
@@ -933,15 +935,9 @@ class CodeDescription BASE_EMBEDDED {
   };
 #endif
 
-  CodeDescription(const char* name, Code* code, Handle<Script> script,
-                  LineInfo* lineinfo, GDBJITInterface::CodeTag tag,
-                  CompilationInfo* info)
-      : name_(name),
-        code_(code),
-        script_(script),
-        lineinfo_(lineinfo),
-        tag_(tag),
-        info_(info) {}
+  CodeDescription(const char* name, Code* code, SharedFunctionInfo* shared,
+                  LineInfo* lineinfo)
+      : name_(name), code_(code), shared_info_(shared), lineinfo_(lineinfo) {}
 
   const char* name() const {
     return name_;
@@ -949,16 +945,16 @@ class CodeDescription BASE_EMBEDDED {
 
   LineInfo* lineinfo() const { return lineinfo_; }
 
-  GDBJITInterface::CodeTag tag() const {
-    return tag_;
+  bool is_function() const {
+    Code::Kind kind = code_->kind();
+    return kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION;
   }
 
-  CompilationInfo* info() const {
-    return info_;
-  }
+  bool has_scope_info() const { return shared_info_ != NULL; }
 
-  bool IsInfoAvailable() const {
-    return info_ != NULL;
+  ScopeInfo* scope_info() const {
+    DCHECK(has_scope_info());
+    return shared_info_->scope_info();
   }
 
   uintptr_t CodeStart() const {
@@ -973,12 +969,16 @@ class CodeDescription BASE_EMBEDDED {
     return CodeEnd() - CodeStart();
   }
 
+  bool has_script() {
+    return shared_info_ != NULL && shared_info_->script()->IsScript();
+  }
+
+  Script* script() { return Script::cast(shared_info_->script()); }
+
   bool IsLineInfoAvailable() {
-    return !script_.is_null() &&
-        script_->source()->IsString() &&
-        script_->HasValidSource() &&
-        script_->name()->IsString() &&
-        lineinfo_ != NULL;
+    return has_script() && script()->source()->IsString() &&
+           script()->HasValidSource() && script()->name()->IsString() &&
+           lineinfo_ != NULL;
   }
 
 #if V8_TARGET_ARCH_X64
@@ -994,21 +994,17 @@ class CodeDescription BASE_EMBEDDED {
 #endif
 
   SmartArrayPointer<char> GetFilename() {
-    return String::cast(script_->name())->ToCString();
+    return String::cast(script()->name())->ToCString();
   }
 
-  int GetScriptLineNumber(int pos) {
-    return script_->GetLineNumber(pos) + 1;
-  }
+  int GetScriptLineNumber(int pos) { return script()->GetLineNumber(pos) + 1; }
 
 
  private:
   const char* name_;
   Code* code_;
-  Handle<Script> script_;
+  SharedFunctionInfo* shared_info_;
   LineInfo* lineinfo_;
-  GDBJITInterface::CodeTag tag_;
-  CompilationInfo* info_;
 #if V8_TARGET_ARCH_X64
   uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
 #endif
@@ -1095,8 +1091,8 @@ class DebugInfoSection : public DebugSection {
     w->Write<uint8_t>(kPointerSize);
     w->WriteString("v8value");
 
-    if (desc_->IsInfoAvailable()) {
-      Scope* scope = desc_->info()->scope();
+    if (desc_->has_scope_info()) {
+      ScopeInfo* scope = desc_->scope_info();
       w->WriteULEB128(2);
       w->WriteString(desc_->name());
       w->Write<intptr_t>(desc_->CodeStart());
@@ -1118,8 +1114,8 @@ class DebugInfoSection : public DebugSection {
 #endif
       fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
 
-      int params = scope->num_parameters();
-      int slots = scope->num_stack_slots();
+      int params = scope->ParameterCount();
+      int slots = scope->StackLocalCount();
       int context_slots = scope->ContextLocalCount();
       // The real slot ID is internal_slots + context_slot_id.
       int internal_slots = Context::MIN_CONTEXT_SLOTS;
@@ -1129,7 +1125,7 @@ class DebugInfoSection : public DebugSection {
       for (int param = 0; param < params; ++param) {
         w->WriteULEB128(current_abbreviation++);
         w->WriteString(
-            scope->parameter(param)->name()->ToCString(DISALLOW_NULLS).get());
+            scope->ParameterName(param)->ToCString(DISALLOW_NULLS).get());
         w->Write<uint32_t>(ty_offset);
         Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
         uintptr_t block_start = w->position();
@@ -1174,13 +1170,10 @@ class DebugInfoSection : public DebugSection {
         w->WriteString(builder.Finalize());
       }
 
-      ZoneList<Variable*> stack_locals(locals, scope->zone());
-      ZoneList<Variable*> context_locals(context_slots, scope->zone());
-      scope->CollectStackAndContextLocals(&stack_locals, &context_locals);
       for (int local = 0; local < locals; ++local) {
         w->WriteULEB128(current_abbreviation++);
         w->WriteString(
-            stack_locals[local]->name()->ToCString(DISALLOW_NULLS).get());
+            scope->StackLocalName(local)->ToCString(DISALLOW_NULLS).get());
         w->Write<uint32_t>(ty_offset);
         Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
         uintptr_t block_start = w->position();
@@ -1302,7 +1295,7 @@ class DebugAbbrevSection : public DebugSection {
 
   bool WriteBodyInternal(Writer* w) {
     int current_abbreviation = 1;
-    bool extra_info = desc_->IsInfoAvailable();
+    bool extra_info = desc_->has_scope_info();
     DCHECK(desc_->IsLineInfoAvailable());
     w->WriteULEB128(current_abbreviation++);
     w->WriteULEB128(DW_TAG_COMPILE_UNIT);
@@ -1319,9 +1312,9 @@ class DebugAbbrevSection : public DebugSection {
     w->WriteULEB128(0);
 
     if (extra_info) {
-      Scope* scope = desc_->info()->scope();
-      int params = scope->num_parameters();
-      int slots = scope->num_stack_slots();
+      ScopeInfo* scope = desc_->scope_info();
+      int params = scope->ParameterCount();
+      int slots = scope->StackLocalCount();
       int context_slots = scope->ContextLocalCount();
       // The real slot ID is internal_slots + context_slot_id.
       int internal_slots = Context::MIN_CONTEXT_SLOTS;
@@ -1868,27 +1861,7 @@ static void DestroyCodeEntry(JITCodeEntry* entry) {
 }
 
 
-static void RegisterCodeEntry(JITCodeEntry* entry,
-                              bool dump_if_enabled,
-                              const char* name_hint) {
-#if defined(DEBUG) && !V8_OS_WIN
-  static int file_num = 0;
-  if (FLAG_gdbjit_dump && dump_if_enabled) {
-    static const int kMaxFileNameSize = 64;
-    static const char* kElfFilePrefix = "/tmp/elfdump";
-    static const char* kObjFileExt = ".o";
-    char file_name[64];
-
-    SNPrintF(Vector<char>(file_name, kMaxFileNameSize),
-             "%s%s%d%s",
-             kElfFilePrefix,
-             (name_hint != NULL) ? name_hint : "",
-             file_num++,
-             kObjFileExt);
-    WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
-  }
-#endif
-
+static void RegisterCodeEntry(JITCodeEntry* entry) {
   entry->next_ = __jit_debug_descriptor.first_entry_;
   if (entry->next_ != NULL) entry->next_->prev_ = entry;
   __jit_debug_descriptor.first_entry_ =
@@ -1955,69 +1928,67 @@ static JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) {
 }
 
 
-static bool SameCodeObjects(void* key1, void* key2) {
-  return key1 == key2;
-}
+struct AddressRange {
+  Address start;
+  Address end;
+};
 
+class JITCodeEntry;
 
-static HashMap* GetEntries() {
-  static HashMap* entries = NULL;
-  if (entries == NULL) {
-    entries = new HashMap(&SameCodeObjects);
+struct SplayTreeConfig {
+  typedef AddressRange Key;
+  typedef JITCodeEntry* Value;
+  static const AddressRange kNoKey;
+  static Value NoValue() { return NULL; }
+  static int Compare(const AddressRange& a, const AddressRange& b) {
+    // ptrdiff_t probably doesn't fit in an int.
+    if (a.start < b.start) return -1;
+    if (a.start == b.start) return 0;
+    return 1;
   }
-  return entries;
-}
+};
 
+const AddressRange SplayTreeConfig::kNoKey = {0, 0};
+typedef SplayTree<SplayTreeConfig> CodeMap;
 
-static uint32_t HashForCodeObject(Code* code) {
-  static const uintptr_t kGoldenRatio = 2654435761u;
-  uintptr_t hash = reinterpret_cast<uintptr_t>(code->address());
-  return static_cast<uint32_t>((hash >> kCodeAlignmentBits) * kGoldenRatio);
+static CodeMap* GetCodeMap() {
+  static CodeMap* code_map = NULL;
+  if (code_map == NULL) code_map = new CodeMap();
+  return code_map;
 }
 
 
-static const intptr_t kLineInfoTag = 0x1;
-
-
-static bool IsLineInfoTagged(void* ptr) {
-  return 0 != (reinterpret_cast<intptr_t>(ptr) & kLineInfoTag);
+static uint32_t HashCodeAddress(Address addr) {
+  static const intptr_t kGoldenRatio = 2654435761;
+  uintptr_t offset = OffsetFrom(addr);
+  return static_cast<uint32_t>((offset >> kCodeAlignmentBits) * kGoldenRatio);
 }
 
 
-static void* TagLineInfo(LineInfo* ptr) {
-  return reinterpret_cast<void*>(
-      reinterpret_cast<intptr_t>(ptr) | kLineInfoTag);
+static HashMap* GetLineMap() {
+  static HashMap* line_map = NULL;
+  if (line_map == NULL) line_map = new HashMap(&HashMap::PointersMatch);
+  return line_map;
 }
 
 
-static LineInfo* UntagLineInfo(void* ptr) {
-  return reinterpret_cast<LineInfo*>(reinterpret_cast<intptr_t>(ptr) &
-                                     ~kLineInfoTag);
+static void PutLineInfo(Address addr, LineInfo* info) {
+  HashMap* line_map = GetLineMap();
+  HashMap::Entry* e = line_map->Lookup(addr, HashCodeAddress(addr), true);
+  if (e->value != NULL) delete static_cast<LineInfo*>(e->value);
+  e->value = info;
 }
 
 
-void GDBJITInterface::AddCode(Handle<Name> name,
-                              Handle<Script> script,
-                              Handle<Code> code,
-                              CompilationInfo* info) {
-  if (!FLAG_gdbjit) return;
-
-  Script::InitLineEnds(script);
-
-  if (!name.is_null() && name->IsString()) {
-    SmartArrayPointer<char> name_cstring =
-        Handle<String>::cast(name)->ToCString(DISALLOW_NULLS);
-    AddCode(name_cstring.get(), *code, GDBJITInterface::FUNCTION, *script,
-            info);
-  } else {
-    AddCode("", *code, GDBJITInterface::FUNCTION, *script, info);
-  }
+static LineInfo* GetLineInfo(Address addr) {
+  void* value = GetLineMap()->Remove(addr, HashCodeAddress(addr));
+  return static_cast<LineInfo*>(value);
 }
 
 
 static void AddUnwindInfo(CodeDescription* desc) {
 #if V8_TARGET_ARCH_X64
-  if (desc->tag() == GDBJITInterface::FUNCTION) {
+  if (desc->is_function()) {
     // To avoid propagating unwinding information through
     // compilation pipeline we use an approximation.
     // For most use cases this should not affect usability.
@@ -2055,39 +2026,83 @@ static void AddUnwindInfo(CodeDescription* desc) {
 static base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
 
 
-void GDBJITInterface::AddCode(const char* name,
-                              Code* code,
-                              GDBJITInterface::CodeTag tag,
-                              Script* script,
-                              CompilationInfo* info) {
-  base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
+// Remove entries from the splay tree that intersect the given address range,
+// and deregister them from GDB.
+static void RemoveJITCodeEntries(CodeMap* map, const AddressRange& range) {
+  DCHECK(range.start < range.end);
+  CodeMap::Locator cur;
+  if (map->FindGreatestLessThan(range, &cur) || map->FindLeast(&cur)) {
+    // Skip entries that are entirely less than the range of interest.
+    while (cur.key().end <= range.start) {
+      // CodeMap::FindLeastGreaterThan succeeds for entries whose key is greater
+      // than _or equal to_ the given key, so we have to advance our key to get
+      // the next one.
+      AddressRange new_key;
+      new_key.start = cur.key().end;
+      new_key.end = 0;
+      if (!map->FindLeastGreaterThan(new_key, &cur)) return;
+    }
+    // Evict intersecting ranges.
+    while (cur.key().start < range.end) {
+      AddressRange old_range = cur.key();
+      JITCodeEntry* old_entry = cur.value();
+
+      UnregisterCodeEntry(old_entry);
+      DestroyCodeEntry(old_entry);
+
+      CHECK(map->Remove(old_range));
+      if (!map->FindLeastGreaterThan(old_range, &cur)) return;
+    }
+  }
+}
+
+
+// Insert the entry into the splay tree and register it with GDB.
+static void AddJITCodeEntry(CodeMap* map, const AddressRange& range,
+                            JITCodeEntry* entry, bool dump_if_enabled,
+                            const char* name_hint) {
+#if defined(DEBUG) && !V8_OS_WIN
+  static int file_num = 0;
+  if (FLAG_gdbjit_dump && dump_if_enabled) {
+    static const int kMaxFileNameSize = 64;
+    char file_name[64];
+
+    SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "/tmp/elfdump%s%d.o",
+             (name_hint != NULL) ? name_hint : "", file_num++);
+    WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
+  }
+#endif
+
+  CodeMap::Locator cur;
+  CHECK(map->Insert(range, &cur));
+  cur.set_value(entry);
+
+  RegisterCodeEntry(entry);
+}
+
+
+static void AddCode(const char* name, Code* code, SharedFunctionInfo* shared,
+                    LineInfo* lineinfo) {
   DisallowHeapAllocation no_gc;
 
-  HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
-  if (e->value != NULL && !IsLineInfoTagged(e->value)) return;
+  CodeMap* code_map = GetCodeMap();
+  AddressRange range;
+  range.start = code->address();
+  range.end = code->address() + code->CodeSize();
+  RemoveJITCodeEntries(code_map, range);
 
-  LineInfo* lineinfo = UntagLineInfo(e->value);
-  CodeDescription code_desc(name,
-                            code,
-                            script != NULL ? Handle<Script>(script)
-                                           : Handle<Script>(),
-                            lineinfo,
-                            tag,
-                            info);
+  CodeDescription code_desc(name, code, shared, lineinfo);
 
   if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
     delete lineinfo;
-    GetEntries()->Remove(code, HashForCodeObject(code));
     return;
   }
 
   AddUnwindInfo(&code_desc);
   Isolate* isolate = code->GetIsolate();
   JITCodeEntry* entry = CreateELFObject(&code_desc, isolate);
-  DCHECK(!IsLineInfoTagged(entry));
 
   delete lineinfo;
-  e->value = entry;
 
   const char* name_hint = NULL;
   bool should_dump = false;
@@ -2100,82 +2115,35 @@ void GDBJITInterface::AddCode(const char* name,
       should_dump = (name_hint != NULL);
     }
   }
-  RegisterCodeEntry(entry, should_dump, name_hint);
+  AddJITCodeEntry(code_map, range, entry, should_dump, name_hint);
 }
 
 
-void GDBJITInterface::RemoveCode(Code* code) {
+void EventHandler(const v8::JitCodeEvent* event) {
   if (!FLAG_gdbjit) return;
-
-  base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
-  HashMap::Entry* e = GetEntries()->Lookup(code,
-                                           HashForCodeObject(code),
-                                           false);
-  if (e == NULL) return;
-
-  if (IsLineInfoTagged(e->value)) {
-    delete UntagLineInfo(e->value);
-  } else {
-    JITCodeEntry* entry = static_cast<JITCodeEntry*>(e->value);
-    UnregisterCodeEntry(entry);
-    DestroyCodeEntry(entry);
-  }
-  e->value = NULL;
-  GetEntries()->Remove(code, HashForCodeObject(code));
-}
-
-
-void GDBJITInterface::RemoveCodeRange(Address start, Address end) {
-  HashMap* entries = GetEntries();
-  Zone zone;
-  ZoneList<Code*> dead_codes(1, &zone);
-
-  for (HashMap::Entry* e = entries->Start(); e != NULL; e = entries->Next(e)) {
-    Code* code = reinterpret_cast<Code*>(e->key);
-    if (code->address() >= start && code->address() < end) {
-      dead_codes.Add(code, &zone);
-    }
-  }
-
-  for (int i = 0; i < dead_codes.length(); i++) {
-    RemoveCode(dead_codes.at(i));
-  }
-}
-
-
-static void RegisterDetailedLineInfo(Code* code, LineInfo* line_info) {
   base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
-  DCHECK(!IsLineInfoTagged(line_info));
-  HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
-  DCHECK(e->value == NULL);
-  e->value = TagLineInfo(line_info);
-}
-
-
-void GDBJITInterface::EventHandler(const v8::JitCodeEvent* event) {
-  if (!FLAG_gdbjit) return;
   switch (event->type) {
     case v8::JitCodeEvent::CODE_ADDED: {
-      Code* code = Code::GetCodeFromTargetAddress(
-          reinterpret_cast<Address>(event->code_start));
-      if (code->kind() == Code::OPTIMIZED_FUNCTION ||
-          code->kind() == Code::FUNCTION) {
-        break;
-      }
+      Address addr = reinterpret_cast<Address>(event->code_start);
+      Code* code = Code::GetCodeFromTargetAddress(addr);
+      LineInfo* lineinfo = GetLineInfo(addr);
       EmbeddedVector<char, 256> buffer;
       StringBuilder builder(buffer.start(), buffer.length());
       builder.AddSubstring(event->name.str, static_cast<int>(event->name.len));
-      AddCode(builder.Finalize(), code, NON_FUNCTION, NULL, NULL);
+      // It's called UnboundScript in the API but it's a SharedFunctionInfo.
+      SharedFunctionInfo* shared =
+          event->script.IsEmpty() ? NULL : *Utils::OpenHandle(*event->script);
+      AddCode(builder.Finalize(), code, shared, lineinfo);
       break;
     }
     case v8::JitCodeEvent::CODE_MOVED:
+      // Enabling the GDB JIT interface should disable code compaction.
+      UNREACHABLE();
       break;
-    case v8::JitCodeEvent::CODE_REMOVED: {
-      Code* code = Code::GetCodeFromTargetAddress(
-          reinterpret_cast<Address>(event->code_start));
-      RemoveCode(code);
+    case v8::JitCodeEvent::CODE_REMOVED:
+      // Do nothing.  Instead, adding code causes eviction of any entry whose
+      // address range intersects the address range of the added code.
       break;
-    }
     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
       LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
       line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset),
@@ -2191,14 +2159,12 @@ void GDBJITInterface::EventHandler(const v8::JitCodeEvent* event) {
     }
     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
       LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
-      Code* code = Code::GetCodeFromTargetAddress(
-          reinterpret_cast<Address>(event->code_start));
-      RegisterDetailedLineInfo(code, line_info);
+      PutLineInfo(reinterpret_cast<Address>(event->code_start), line_info);
       break;
     }
   }
 }
-
-
-} }  // namespace v8::internal
 #endif
+}  // namespace GDBJITInterface
+}  // namespace internal
+}  // namespace v8
index 14536cf0b38e287937cbad1c7fcef697082bcc0a..45382702da4a9fea2df09632d1437c7618871c95 100644 (file)
@@ -5,50 +5,35 @@
 #ifndef V8_GDB_JIT_H_
 #define V8_GDB_JIT_H_
 
-#include "src/allocation.h"
+#include "src/v8.h"
 
 //
-// Basic implementation of GDB JIT Interface client.
-// GBD JIT Interface is supported in GDB 7.0 and above.
-// Currently on x64 and ia32 architectures and Linux OS are supported.
+// GDB has two ways of interacting with JIT code.  With the "JIT compilation
+// interface", V8 can tell GDB when it emits JIT code.  Unfortunately to do so,
+// it has to create platform-native object files, possibly with platform-native
+// debugging information.  Currently only ELF and Mach-O are supported, which
+// limits this interface to Linux and Mac OS.  This JIT compilation interface
+// was introduced in GDB 7.0.  V8 support can be enabled with the --gdbjit flag.
+//
+// The other way that GDB can know about V8 code is via the "custom JIT reader"
+// interface, in which a GDB extension parses V8's private data to determine the
+// function, file, and line of a JIT frame, and how to unwind those frames.
+// This interface was introduced in GDB 7.6.  This interface still relies on V8
+// to register its code via the JIT compilation interface, but doesn't require
+// that V8 create ELF images.  Support will be added for this interface in the
+// future.
 //
-
-#ifdef ENABLE_GDB_JIT_INTERFACE
-#include "src/v8.h"
-
-#include "src/factory.h"
 
 namespace v8 {
 namespace internal {
-
-class CompilationInfo;
-
-class GDBJITInterface: public AllStatic {
- public:
-  enum CodeTag { NON_FUNCTION, FUNCTION };
-
-  // Main entry point into GDB JIT realized as a JitCodeEventHandler.
-  static void EventHandler(const v8::JitCodeEvent* event);
-
-  static void AddCode(Handle<Name> name,
-                      Handle<Script> script,
-                      Handle<Code> code,
-                      CompilationInfo* info);
-
-  static void RemoveCodeRange(Address start, Address end);
-
- private:
-  static void AddCode(const char* name, Code* code, CodeTag tag, Script* script,
-                      CompilationInfo* info);
-
-  static void RemoveCode(Code* code);
-};
-
-#define GDBJIT(action) GDBJITInterface::action
-
-} }   // namespace v8::internal
-#else
-#define GDBJIT(action) ((void) 0)
+namespace GDBJITInterface {
+#ifdef ENABLE_GDB_JIT_INTERFACE
+// JitCodeEventHandler that creates ELF/Mach-O objects and registers them with
+// GDB.
+void EventHandler(const v8::JitCodeEvent* event);
 #endif
+}  // namespace GDBJITInterface
+}  // namespace internal
+}  // namespace v8
 
 #endif
index 961f5b38329a1266c5b231446f63d04cac6ad0a2..77d084266264fbd78f56bc16115818a92b223ff4 100644 (file)
@@ -262,11 +262,6 @@ bool MarkCompactCollector::StartCompaction(CompactionMode mode) {
   if (!compacting_) {
     DCHECK(evacuation_candidates_.length() == 0);
 
-#ifdef ENABLE_GDB_JIT_INTERFACE
-    // If GDBJIT interface is active disable compaction.
-    if (FLAG_gdbjit) return false;
-#endif
-
     CollectEvacuationCandidates(heap()->old_pointer_space());
     CollectEvacuationCandidates(heap()->old_data_space());
 
@@ -3223,11 +3218,6 @@ static int Sweep(PagedSpace* space, FreeList* free_list, Page* p,
         }
         freed_bytes = Free<parallelism>(space, free_list, free_start, size);
         max_freed_bytes = Max(freed_bytes, max_freed_bytes);
-#ifdef ENABLE_GDB_JIT_INTERFACE
-        if (FLAG_gdbjit && space->identity() == CODE_SPACE) {
-          GDBJITInterface::RemoveCodeRange(free_start, free_end);
-        }
-#endif
       }
       HeapObject* live_object = HeapObject::FromAddress(free_end);
       DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object)));
@@ -3257,11 +3247,6 @@ static int Sweep(PagedSpace* space, FreeList* free_list, Page* p,
     }
     freed_bytes = Free<parallelism>(space, free_list, free_start, size);
     max_freed_bytes = Max(freed_bytes, max_freed_bytes);
-#ifdef ENABLE_GDB_JIT_INTERFACE
-    if (FLAG_gdbjit && space->identity() == CODE_SPACE) {
-      GDBJITInterface::RemoveCodeRange(free_start, p->area_end());
-    }
-#endif
   }
   p->ResetLiveBytes();