Chromium Code Reviews

Unified Diff: src/gdb-jit.cc

Issue 954833004: Revert of Rebase GDBJIT interface solely on JITCodeEvent (Closed) Base URL: https://chromium.googlesource.com/v8/v8@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
« no previous file with comments | « src/gdb-jit.h ('k') | src/heap/mark-compact.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gdb-jit.cc
diff --git a/src/gdb-jit.cc b/src/gdb-jit.cc
index 00c7789828e99a6233d5860591d91b8ef3e41c80..69b48d664486fb1a597bdc1d83efb4bec2468bad 100644
--- a/src/gdb-jit.cc
+++ b/src/gdb-jit.cc
@@ -2,6 +2,7 @@
// 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"
@@ -14,14 +15,11 @@
#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
@@ -935,9 +933,15 @@
};
#endif
- CodeDescription(const char* name, Code* code, SharedFunctionInfo* shared,
- LineInfo* lineinfo)
- : name_(name), code_(code), shared_info_(shared), lineinfo_(lineinfo) {}
+ 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) {}
const char* name() const {
return name_;
@@ -945,16 +949,16 @@
LineInfo* lineinfo() const { return lineinfo_; }
- bool is_function() const {
- Code::Kind kind = code_->kind();
- return kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION;
- }
-
- bool has_scope_info() const { return shared_info_ != NULL; }
-
- ScopeInfo* scope_info() const {
- DCHECK(has_scope_info());
- return shared_info_->scope_info();
+ GDBJITInterface::CodeTag tag() const {
+ return tag_;
+ }
+
+ CompilationInfo* info() const {
+ return info_;
+ }
+
+ bool IsInfoAvailable() const {
+ return info_ != NULL;
}
uintptr_t CodeStart() const {
@@ -969,16 +973,12 @@
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 has_script() && script()->source()->IsString() &&
- script()->HasValidSource() && script()->name()->IsString() &&
- lineinfo_ != NULL;
+ return !script_.is_null() &&
+ script_->source()->IsString() &&
+ script_->HasValidSource() &&
+ script_->name()->IsString() &&
+ lineinfo_ != NULL;
}
#if V8_TARGET_ARCH_X64
@@ -994,17 +994,21 @@
#endif
SmartArrayPointer<char> GetFilename() {
- return String::cast(script()->name())->ToCString();
- }
-
- int GetScriptLineNumber(int pos) { return script()->GetLineNumber(pos) + 1; }
+ return String::cast(script_->name())->ToCString();
+ }
+
+ int GetScriptLineNumber(int pos) {
+ return script_->GetLineNumber(pos) + 1;
+ }
private:
const char* name_;
Code* code_;
- SharedFunctionInfo* shared_info_;
+ Handle<Script> script_;
LineInfo* lineinfo_;
+ GDBJITInterface::CodeTag tag_;
+ CompilationInfo* info_;
#if V8_TARGET_ARCH_X64
uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
#endif
@@ -1091,8 +1095,8 @@
w->Write<uint8_t>(kPointerSize);
w->WriteString("v8value");
- if (desc_->has_scope_info()) {
- ScopeInfo* scope = desc_->scope_info();
+ if (desc_->IsInfoAvailable()) {
+ Scope* scope = desc_->info()->scope();
w->WriteULEB128(2);
w->WriteString(desc_->name());
w->Write<intptr_t>(desc_->CodeStart());
@@ -1114,8 +1118,8 @@
#endif
fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
- int params = scope->ParameterCount();
- int slots = scope->StackLocalCount();
+ int params = scope->num_parameters();
+ int slots = scope->num_stack_slots();
int context_slots = scope->ContextLocalCount();
// The real slot ID is internal_slots + context_slot_id.
int internal_slots = Context::MIN_CONTEXT_SLOTS;
@@ -1125,7 +1129,7 @@
for (int param = 0; param < params; ++param) {
w->WriteULEB128(current_abbreviation++);
w->WriteString(
- scope->ParameterName(param)->ToCString(DISALLOW_NULLS).get());
+ scope->parameter(param)->name()->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();
@@ -1170,10 +1174,13 @@
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(
- scope->StackLocalName(local)->ToCString(DISALLOW_NULLS).get());
+ stack_locals[local]->name()->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();
@@ -1295,7 +1302,7 @@
bool WriteBodyInternal(Writer* w) {
int current_abbreviation = 1;
- bool extra_info = desc_->has_scope_info();
+ bool extra_info = desc_->IsInfoAvailable();
DCHECK(desc_->IsLineInfoAvailable());
w->WriteULEB128(current_abbreviation++);
w->WriteULEB128(DW_TAG_COMPILE_UNIT);
@@ -1312,9 +1319,9 @@
w->WriteULEB128(0);
if (extra_info) {
- ScopeInfo* scope = desc_->scope_info();
- int params = scope->ParameterCount();
- int slots = scope->StackLocalCount();
+ Scope* scope = desc_->info()->scope();
+ int params = scope->num_parameters();
+ int slots = scope->num_stack_slots();
int context_slots = scope->ContextLocalCount();
// The real slot ID is internal_slots + context_slot_id.
int internal_slots = Context::MIN_CONTEXT_SLOTS;
@@ -1861,7 +1868,27 @@
}
-static void RegisterCodeEntry(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
+
entry->next_ = __jit_debug_descriptor.first_entry_;
if (entry->next_ != NULL) entry->next_->prev_ = entry;
__jit_debug_descriptor.first_entry_ =
@@ -1928,67 +1955,69 @@
}
-struct AddressRange {
- Address start;
- Address end;
-};
-
-class JITCodeEntry;
-
-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;
- }
-};
-
-const AddressRange SplayTreeConfig::kNoKey = {0, 0};
-typedef SplayTree<SplayTreeConfig> CodeMap;
-
-static CodeMap* GetCodeMap() {
- static CodeMap* code_map = NULL;
- if (code_map == NULL) code_map = new CodeMap();
- return code_map;
-}
-
-
-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 HashMap* GetLineMap() {
- static HashMap* line_map = NULL;
- if (line_map == NULL) line_map = new HashMap(&HashMap::PointersMatch);
- return line_map;
-}
-
-
-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;
-}
-
-
-static LineInfo* GetLineInfo(Address addr) {
- void* value = GetLineMap()->Remove(addr, HashCodeAddress(addr));
- return static_cast<LineInfo*>(value);
+static bool SameCodeObjects(void* key1, void* key2) {
+ return key1 == key2;
+}
+
+
+static HashMap* GetEntries() {
+ static HashMap* entries = NULL;
+ if (entries == NULL) {
+ entries = new HashMap(&SameCodeObjects);
+ }
+ return entries;
+}
+
+
+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 const intptr_t kLineInfoTag = 0x1;
+
+
+static bool IsLineInfoTagged(void* ptr) {
+ return 0 != (reinterpret_cast<intptr_t>(ptr) & kLineInfoTag);
+}
+
+
+static void* TagLineInfo(LineInfo* ptr) {
+ return reinterpret_cast<void*>(
+ reinterpret_cast<intptr_t>(ptr) | kLineInfoTag);
+}
+
+
+static LineInfo* UntagLineInfo(void* ptr) {
+ return reinterpret_cast<LineInfo*>(reinterpret_cast<intptr_t>(ptr) &
+ ~kLineInfoTag);
+}
+
+
+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 void AddUnwindInfo(CodeDescription* desc) {
#if V8_TARGET_ARCH_X64
- if (desc->is_function()) {
+ if (desc->tag() == GDBJITInterface::FUNCTION) {
// To avoid propagating unwinding information through
// compilation pipeline we use an approximation.
// For most use cases this should not affect usability.
@@ -2026,83 +2055,39 @@
static base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
-// 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) {
+void GDBJITInterface::AddCode(const char* name,
+ Code* code,
+ GDBJITInterface::CodeTag tag,
+ Script* script,
+ CompilationInfo* info) {
+ base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
DisallowHeapAllocation no_gc;
- CodeMap* code_map = GetCodeMap();
- AddressRange range;
- range.start = code->address();
- range.end = code->address() + code->CodeSize();
- RemoveJITCodeEntries(code_map, range);
-
- CodeDescription code_desc(name, code, shared, lineinfo);
+ HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
+ if (e->value != NULL && !IsLineInfoTagged(e->value)) return;
+
+ LineInfo* lineinfo = UntagLineInfo(e->value);
+ CodeDescription code_desc(name,
+ code,
+ script != NULL ? Handle<Script>(script)
+ : Handle<Script>(),
+ lineinfo,
+ tag,
+ info);
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;
@@ -2115,35 +2100,82 @@
should_dump = (name_hint != NULL);
}
}
- AddJITCodeEntry(code_map, range, entry, should_dump, name_hint);
-}
-
-
-void EventHandler(const v8::JitCodeEvent* event) {
+ RegisterCodeEntry(entry, should_dump, name_hint);
+}
+
+
+void GDBJITInterface::RemoveCode(Code* code) {
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: {
- Address addr = reinterpret_cast<Address>(event->code_start);
- Code* code = Code::GetCodeFromTargetAddress(addr);
- LineInfo* lineinfo = GetLineInfo(addr);
+ Code* code = Code::GetCodeFromTargetAddress(
+ reinterpret_cast<Address>(event->code_start));
+ if (code->kind() == Code::OPTIMIZED_FUNCTION ||
+ code->kind() == Code::FUNCTION) {
+ break;
+ }
EmbeddedVector<char, 256> buffer;
StringBuilder builder(buffer.start(), buffer.length());
builder.AddSubstring(event->name.str, static_cast<int>(event->name.len));
- // 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);
+ AddCode(builder.Finalize(), code, NON_FUNCTION, NULL, NULL);
break;
}
case v8::JitCodeEvent::CODE_MOVED:
- // Enabling the GDB JIT interface should disable code compaction.
- UNREACHABLE();
break;
- 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.
+ case v8::JitCodeEvent::CODE_REMOVED: {
+ Code* code = Code::GetCodeFromTargetAddress(
+ reinterpret_cast<Address>(event->code_start));
+ RemoveCode(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),
@@ -2159,12 +2191,14 @@
}
case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
- PutLineInfo(reinterpret_cast<Address>(event->code_start), line_info);
+ Code* code = Code::GetCodeFromTargetAddress(
+ reinterpret_cast<Address>(event->code_start));
+ RegisterDetailedLineInfo(code, line_info);
break;
}
}
}
+
+
+} } // namespace v8::internal
#endif
-} // namespace GDBJITInterface
-} // namespace internal
-} // namespace v8
« no previous file with comments | « src/gdb-jit.h ('k') | src/heap/mark-compact.cc » ('j') | no next file with comments »

Powered by Google App Engine