Commit 99791dc5 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[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/1256830Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56355}
parent e06ada18
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "src/disassembler.h" #include "src/disassembler.h"
#include <memory> #include <memory>
#include <unordered_map>
#include <vector> #include <vector>
#include "src/assembler-inl.h" #include "src/assembler-inl.h"
...@@ -38,12 +39,39 @@ class V8NameConverter: public disasm::NameConverter { ...@@ -38,12 +39,39 @@ class V8NameConverter: public disasm::NameConverter {
const CodeReference& code() const { return code_; } const CodeReference& code() const { return code_; }
private: private:
void InitExternalRefsCache() const;
Isolate* isolate_; Isolate* isolate_;
CodeReference code_; CodeReference code_;
EmbeddedVector<char, 128> v8_buffer_; 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 { const char* V8NameConverter::NameOfAddress(byte* pc) const {
if (!code_.is_null()) { if (!code_.is_null()) {
...@@ -90,8 +118,11 @@ const char* V8NameConverter::RootRelativeName(int offset) const { ...@@ -90,8 +118,11 @@ const char* V8NameConverter::RootRelativeName(int offset) const {
const int kRootsStart = 0; const int kRootsStart = 0;
const int kRootsEnd = Heap::roots_to_external_reference_table_offset(); 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 kExtRefsEnd = Heap::roots_to_builtins_offset();
const int kBuiltinsStart = kExtRefsEnd;
const int kBuiltinsEnd =
kBuiltinsStart + Builtins::builtin_count * kPointerSize;
if (kRootsStart <= offset && offset < kRootsEnd) { if (kRootsStart <= offset && offset < kRootsEnd) {
uint32_t offset_in_roots_table = offset - kRootsStart; uint32_t offset_in_roots_table = offset - kRootsStart;
...@@ -109,6 +140,7 @@ const char* V8NameConverter::RootRelativeName(int offset) const { ...@@ -109,6 +140,7 @@ const char* V8NameConverter::RootRelativeName(int offset) const {
SNPrintF(v8_buffer_, "root (%s)", obj_name.get()); SNPrintF(v8_buffer_, "root (%s)", obj_name.get());
return v8_buffer_.start(); return v8_buffer_.start();
} else if (kExtRefsStart <= offset && offset < kExtRefsEnd) { } else if (kExtRefsStart <= offset && offset < kExtRefsEnd) {
uint32_t offset_in_extref_table = offset - kExtRefsStart; uint32_t offset_in_extref_table = offset - kExtRefsStart;
...@@ -126,8 +158,29 @@ const char* V8NameConverter::RootRelativeName(int offset) const { ...@@ -126,8 +158,29 @@ const char* V8NameConverter::RootRelativeName(int offset) const {
isolate_->heap()->external_reference_table()->NameFromOffset( isolate_->heap()->external_reference_table()->NameFromOffset(
offset_in_extref_table)); offset_in_extref_table));
return v8_buffer_.start(); 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 { } 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 @@ ...@@ -11,6 +11,12 @@
namespace v8 { namespace v8 {
namespace internal { 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) { bool Isolate::FromWritableHeapObject(HeapObject* obj, Isolate** isolate) {
i::MemoryChunk* chunk = i::MemoryChunk::FromHeapObject(obj); i::MemoryChunk* chunk = i::MemoryChunk::FromHeapObject(obj);
if (chunk->owner()->identity() == i::RO_SPACE) { if (chunk->owner()->identity() == i::RO_SPACE) {
......
...@@ -998,6 +998,12 @@ class Isolate : private HiddenFactory { ...@@ -998,6 +998,12 @@ class Isolate : private HiddenFactory {
} }
StackGuard* stack_guard() { return &stack_guard_; } StackGuard* stack_guard() { return &stack_guard_; }
Heap* heap() { return &heap_; } 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* load_stub_cache() { return load_stub_cache_; }
StubCache* store_stub_cache() { return store_stub_cache_; } StubCache* store_stub_cache() { return store_stub_cache_; }
DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; } DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; }
......
...@@ -106,10 +106,8 @@ intptr_t TurboAssemblerBase::RootRegisterOffsetForExternalReference( ...@@ -106,10 +106,8 @@ intptr_t TurboAssemblerBase::RootRegisterOffsetForExternalReference(
// static // static
bool TurboAssemblerBase::IsAddressableThroughRootRegister( bool TurboAssemblerBase::IsAddressableThroughRootRegister(
Isolate* isolate, const ExternalReference& reference) { Isolate* isolate, const ExternalReference& reference) {
Address start = reinterpret_cast<Address>(isolate);
Address end = isolate->heap()->root_register_addressable_end();
Address address = reference.address(); Address address = reference.address();
return start <= address && address < end; return isolate->root_register_addressable_region().contains(address);
} }
// static // static
......
...@@ -64,7 +64,7 @@ class V8_EXPORT_PRIVATE TurboAssemblerBase : public Assembler { ...@@ -64,7 +64,7 @@ class V8_EXPORT_PRIVATE TurboAssemblerBase : public Assembler {
Isolate* isolate, const ExternalReference& reference); Isolate* isolate, const ExternalReference& reference);
// An address is addressable through kRootRegister if it is located within // 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( static bool IsAddressableThroughRootRegister(
Isolate* isolate, const ExternalReference& reference); Isolate* isolate, const ExternalReference& reference);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment