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 @@
#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);
......
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