diff options
author | Chris Dickinson <christopher.s.dickinson@gmail.com> | 2015-05-05 13:48:55 -0700 |
---|---|---|
committer | Rod Vagg <rod@vagg.org> | 2015-08-04 11:56:09 -0700 |
commit | d58e780504bdba6c5897c48428fd984c5b5f96fe (patch) | |
tree | 033f1568ae3f9f077aceb843b42eb1ed1739ce0f /deps/v8/src/gdb-jit.cc | |
parent | 21d31c08e7d0b6865e52452750b20b05e6dca443 (diff) | |
download | android-node-v8-d58e780504bdba6c5897c48428fd984c5b5f96fe.tar.gz android-node-v8-d58e780504bdba6c5897c48428fd984c5b5f96fe.tar.bz2 android-node-v8-d58e780504bdba6c5897c48428fd984c5b5f96fe.zip |
deps: update v8 to 4.3.61.21
* @indutny's SealHandleScope patch (484bebc38319fc7c622478037922ad73b2edcbf9)
has been cherry picked onto the top of V8 to make it compile.
* There's some test breakage in contextify.
* This was merged at the request of the TC.
PR-URL: https://github.com/iojs/io.js/pull/1632
Diffstat (limited to 'deps/v8/src/gdb-jit.cc')
-rw-r--r-- | deps/v8/src/gdb-jit.cc | 350 |
1 files changed, 157 insertions, 193 deletions
diff --git a/deps/v8/src/gdb-jit.cc b/deps/v8/src/gdb-jit.cc index 69b48d6644..044f6fe3f4 100644 --- a/deps/v8/src/gdb-jit.cc +++ b/deps/v8/src/gdb-jit.cc @@ -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" @@ -14,12 +13,15 @@ #include "src/gdb-jit.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" +#include "src/snapshot/natives.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,65 @@ static JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) { } -static bool SameCodeObjects(void* key1, void* key2) { - return key1 == key2; -} - +struct AddressRange { + Address start; + Address end; +}; -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 uintptr_t kGoldenRatio = 2654435761u; + 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 +2024,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 +2113,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 +2157,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 |