[disassembler] Better support for root-relative values
In particular, recognize builtins' values accesses and direct accesses to external reference values. For example: REX.W leaq rax,[r13+0x47a0] REX.W leaq rbx,[r13+0x80b0] turns into REX.W leaq rax,[r13+0x47a0] (builtin (RecordWrite)) REX.W leaq rbx,[r13+0x80b0] (external value (Isolate::context_address)) Bug: v8:8238 Change-Id: I3b049a1e82de7450bf04135c0c8d76b4dca4ee10 Reviewed-on: https://chromium-review.googlesource.com/c/1256830 Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Commit-Queue: Igor Sheludko <ishell@chromium.org> Cr-Commit-Position: refs/heads/master@{#56355}
This commit is contained in:
parent
e06ada18c9
commit
99791dc5ab
@ -5,6 +5,7 @@
|
||||
#include "src/disassembler.h"
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "src/assembler-inl.h"
|
||||
@ -38,12 +39,39 @@ class V8NameConverter: public disasm::NameConverter {
|
||||
const CodeReference& code() const { return code_; }
|
||||
|
||||
private:
|
||||
void InitExternalRefsCache() const;
|
||||
|
||||
Isolate* isolate_;
|
||||
CodeReference code_;
|
||||
|
||||
EmbeddedVector<char, 128> v8_buffer_;
|
||||
|
||||
// Map from root-register relative offset of the external reference value to
|
||||
// the external reference name (stored in the external reference table).
|
||||
// This cache is used to recognize [root_reg + offs] patterns as direct
|
||||
// access to certain external reference's value.
|
||||
mutable std::unordered_map<int, const char*> directly_accessed_external_refs_;
|
||||
};
|
||||
|
||||
void V8NameConverter::InitExternalRefsCache() const {
|
||||
ExternalReferenceTable* external_reference_table =
|
||||
isolate_->heap()->external_reference_table();
|
||||
if (!external_reference_table->is_initialized()) return;
|
||||
|
||||
base::AddressRegion addressable_region =
|
||||
isolate_->root_register_addressable_region();
|
||||
Address roots_start =
|
||||
reinterpret_cast<Address>(isolate_->heap()->roots_array_start());
|
||||
|
||||
for (uint32_t i = 0; i < external_reference_table->size(); i++) {
|
||||
Address address = external_reference_table->address(i);
|
||||
if (addressable_region.contains(address)) {
|
||||
int offset = static_cast<int>(address - roots_start);
|
||||
const char* name = external_reference_table->name(i);
|
||||
directly_accessed_external_refs_.insert({offset, name});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* V8NameConverter::NameOfAddress(byte* pc) const {
|
||||
if (!code_.is_null()) {
|
||||
@ -90,8 +118,11 @@ const char* V8NameConverter::RootRelativeName(int offset) const {
|
||||
|
||||
const int kRootsStart = 0;
|
||||
const int kRootsEnd = Heap::roots_to_external_reference_table_offset();
|
||||
const int kExtRefsStart = Heap::roots_to_external_reference_table_offset();
|
||||
const int kExtRefsStart = kRootsEnd;
|
||||
const int kExtRefsEnd = Heap::roots_to_builtins_offset();
|
||||
const int kBuiltinsStart = kExtRefsEnd;
|
||||
const int kBuiltinsEnd =
|
||||
kBuiltinsStart + Builtins::builtin_count * kPointerSize;
|
||||
|
||||
if (kRootsStart <= offset && offset < kRootsEnd) {
|
||||
uint32_t offset_in_roots_table = offset - kRootsStart;
|
||||
@ -109,6 +140,7 @@ const char* V8NameConverter::RootRelativeName(int offset) const {
|
||||
|
||||
SNPrintF(v8_buffer_, "root (%s)", obj_name.get());
|
||||
return v8_buffer_.start();
|
||||
|
||||
} else if (kExtRefsStart <= offset && offset < kExtRefsEnd) {
|
||||
uint32_t offset_in_extref_table = offset - kExtRefsStart;
|
||||
|
||||
@ -126,8 +158,29 @@ const char* V8NameConverter::RootRelativeName(int offset) const {
|
||||
isolate_->heap()->external_reference_table()->NameFromOffset(
|
||||
offset_in_extref_table));
|
||||
return v8_buffer_.start();
|
||||
|
||||
} else if (kBuiltinsStart <= offset && offset < kBuiltinsEnd) {
|
||||
uint32_t offset_in_builtins_table = (offset - kBuiltinsStart);
|
||||
|
||||
Builtins::Name builtin_id =
|
||||
static_cast<Builtins::Name>(offset_in_builtins_table / kPointerSize);
|
||||
|
||||
const char* name = Builtins::name(builtin_id);
|
||||
SNPrintF(v8_buffer_, "builtin (%s)", name);
|
||||
return v8_buffer_.start();
|
||||
|
||||
} else {
|
||||
return nullptr;
|
||||
// It must be a direct access to one of the external values.
|
||||
if (directly_accessed_external_refs_.empty()) {
|
||||
InitExternalRefsCache();
|
||||
}
|
||||
|
||||
auto iter = directly_accessed_external_refs_.find(offset);
|
||||
if (iter != directly_accessed_external_refs_.end()) {
|
||||
SNPrintF(v8_buffer_, "external value (%s)", iter->second);
|
||||
return v8_buffer_.start();
|
||||
}
|
||||
return "WAAT??? What are we accessing here???";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,12 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
base::AddressRegion Isolate::root_register_addressable_region() {
|
||||
Address start = reinterpret_cast<Address>(this);
|
||||
Address end = heap_.root_register_addressable_end();
|
||||
return base::AddressRegion(start, end - start);
|
||||
}
|
||||
|
||||
bool Isolate::FromWritableHeapObject(HeapObject* obj, Isolate** isolate) {
|
||||
i::MemoryChunk* chunk = i::MemoryChunk::FromHeapObject(obj);
|
||||
if (chunk->owner()->identity() == i::RO_SPACE) {
|
||||
|
@ -998,6 +998,12 @@ class Isolate : private HiddenFactory {
|
||||
}
|
||||
StackGuard* stack_guard() { return &stack_guard_; }
|
||||
Heap* heap() { return &heap_; }
|
||||
|
||||
// kRootRegister may be used to address any location that falls into this
|
||||
// region. Fields outside this region are not guaranteed to live at a static
|
||||
// offset from kRootRegister.
|
||||
inline base::AddressRegion root_register_addressable_region();
|
||||
|
||||
StubCache* load_stub_cache() { return load_stub_cache_; }
|
||||
StubCache* store_stub_cache() { return store_stub_cache_; }
|
||||
DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; }
|
||||
|
@ -106,10 +106,8 @@ intptr_t TurboAssemblerBase::RootRegisterOffsetForExternalReference(
|
||||
// static
|
||||
bool TurboAssemblerBase::IsAddressableThroughRootRegister(
|
||||
Isolate* isolate, const ExternalReference& reference) {
|
||||
Address start = reinterpret_cast<Address>(isolate);
|
||||
Address end = isolate->heap()->root_register_addressable_end();
|
||||
Address address = reference.address();
|
||||
return start <= address && address < end;
|
||||
return isolate->root_register_addressable_region().contains(address);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -64,7 +64,7 @@ class V8_EXPORT_PRIVATE TurboAssemblerBase : public Assembler {
|
||||
Isolate* isolate, const ExternalReference& reference);
|
||||
|
||||
// An address is addressable through kRootRegister if it is located within
|
||||
// [isolate, roots_ + root_register_addressable_end_offset[.
|
||||
// isolate->root_register_addressable_region().
|
||||
static bool IsAddressableThroughRootRegister(
|
||||
Isolate* isolate, const ExternalReference& reference);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user