Embed external reference table in heap
This removes one level of indirection from loading external references, which can now be accesses through the root pointer with a single load: [kRootPointer + <offset from root list to desired offset in table>] Bug: v8:6666 Change-Id: I927634993920828ff48621a0e17e5f3099782917 Reviewed-on: https://chromium-review.googlesource.com/971041 Commit-Queue: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#52211}
This commit is contained in:
parent
20ab39e7c9
commit
64e0921ad7
@ -275,23 +275,17 @@ TNode<ExternalReference> CodeAssembler::LookupExternalReference(
|
||||
uint32_t index = v.index();
|
||||
|
||||
// Generate code to load from the external reference table.
|
||||
// TODO(jgruber,v8:6666): If the external reference points within the isolate,
|
||||
// we could return kRootPointer + offset without loading through the table.
|
||||
|
||||
TNode<IntPtrT> roots_ptr = LoadRootsPointer();
|
||||
|
||||
static const int roots_to_isolate_offset =
|
||||
const intptr_t roots_to_external_reference_offset =
|
||||
Heap::roots_to_external_reference_table_offset()
|
||||
#ifdef V8_TARGET_ARCH_X64
|
||||
Heap::roots_to_external_reference_table_offset() - kRootRegisterBias;
|
||||
#else
|
||||
Heap::roots_to_external_reference_table_offset();
|
||||
- kRootRegisterBias
|
||||
#endif
|
||||
+ ExternalReferenceTable::OffsetOfEntry(index);
|
||||
|
||||
Node* external_refs_ptr = Load(MachineType::Pointer(), roots_ptr,
|
||||
IntPtrConstant(roots_to_isolate_offset));
|
||||
return UncheckedCast<ExternalReference>(
|
||||
Load(MachineType::Pointer(), external_refs_ptr,
|
||||
IntPtrConstant(ExternalReferenceTable::OffsetOfEntry(index))));
|
||||
Load(MachineType::Pointer(), LoadRootsPointer(),
|
||||
IntPtrConstant(roots_to_external_reference_offset)));
|
||||
}
|
||||
#endif // V8_EMBEDDED_BUILTINS
|
||||
|
||||
|
@ -24,17 +24,7 @@ namespace internal {
|
||||
BUILTIN_LIST_C(FORWARD_DECLARE)
|
||||
#undef FORWARD_DECLARE
|
||||
|
||||
ExternalReferenceTable* ExternalReferenceTable::instance(Isolate* isolate) {
|
||||
ExternalReferenceTable* external_reference_table =
|
||||
isolate->external_reference_table();
|
||||
if (external_reference_table == nullptr) {
|
||||
external_reference_table = new ExternalReferenceTable(isolate);
|
||||
isolate->set_external_reference_table(external_reference_table);
|
||||
}
|
||||
return external_reference_table;
|
||||
}
|
||||
|
||||
ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
|
||||
void ExternalReferenceTable::Init(Isolate* isolate) {
|
||||
int index = 0;
|
||||
|
||||
// nullptr is preserved through serialization/deserialization.
|
||||
@ -45,6 +35,7 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
|
||||
AddIsolateAddresses(isolate, &index);
|
||||
AddAccessors(isolate, &index);
|
||||
AddStubCache(isolate, &index);
|
||||
is_initialized_ = true;
|
||||
|
||||
CHECK_EQ(kSize, index);
|
||||
}
|
||||
|
@ -22,8 +22,6 @@ class Isolate;
|
||||
// hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
|
||||
class ExternalReferenceTable {
|
||||
public:
|
||||
static ExternalReferenceTable* instance(Isolate* isolate);
|
||||
|
||||
// For the nullptr ref, see the constructor.
|
||||
static constexpr int kSpecialReferenceCount = 1;
|
||||
static constexpr int kExternalReferenceCount =
|
||||
@ -49,6 +47,8 @@ class ExternalReferenceTable {
|
||||
Address address(uint32_t i) { return refs_[i].address; }
|
||||
const char* name(uint32_t i) { return refs_[i].name; }
|
||||
|
||||
bool is_initialized() const { return is_initialized_; }
|
||||
|
||||
static const char* ResolveSymbol(void* address);
|
||||
|
||||
static uint32_t OffsetOfEntry(uint32_t i) {
|
||||
@ -57,6 +57,9 @@ class ExternalReferenceTable {
|
||||
return i * sizeof(ExternalReferenceEntry);
|
||||
}
|
||||
|
||||
ExternalReferenceTable() {}
|
||||
void Init(Isolate* isolate);
|
||||
|
||||
private:
|
||||
struct ExternalReferenceEntry {
|
||||
Address address;
|
||||
@ -67,8 +70,6 @@ class ExternalReferenceTable {
|
||||
: address(address), name(name) {}
|
||||
};
|
||||
|
||||
explicit ExternalReferenceTable(Isolate* isolate);
|
||||
|
||||
void Add(Address address, const char* name, int* index);
|
||||
|
||||
void AddReferences(Isolate* isolate, int* index);
|
||||
@ -79,6 +80,8 @@ class ExternalReferenceTable {
|
||||
void AddStubCache(Isolate* isolate, int* index);
|
||||
|
||||
ExternalReferenceEntry refs_[kSize];
|
||||
bool is_initialized_ = false;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ExternalReferenceTable);
|
||||
};
|
||||
|
||||
|
@ -5846,6 +5846,8 @@ bool Heap::SetUp() {
|
||||
|
||||
write_protect_code_memory_ = FLAG_write_protect_code_memory;
|
||||
|
||||
external_reference_table_.Init(isolate_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5980,9 +5982,6 @@ void Heap::TearDown() {
|
||||
}
|
||||
}
|
||||
|
||||
delete external_reference_table_;
|
||||
external_reference_table_ = nullptr;
|
||||
|
||||
new_space()->RemoveAllocationObserver(idle_scavenge_observer_);
|
||||
delete idle_scavenge_observer_;
|
||||
idle_scavenge_observer_ = nullptr;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "src/allocation.h"
|
||||
#include "src/assert-scope.h"
|
||||
#include "src/base/atomic-utils.h"
|
||||
#include "src/external-reference-table.h"
|
||||
#include "src/globals.h"
|
||||
#include "src/heap-symbols.h"
|
||||
#include "src/objects.h"
|
||||
@ -43,7 +44,6 @@ class BoilerplateDescription;
|
||||
class BytecodeArray;
|
||||
class CodeDataContainer;
|
||||
class DeoptimizationData;
|
||||
class ExternalReferenceTable;
|
||||
class HandlerTable;
|
||||
class IncrementalMarking;
|
||||
class JSArrayBuffer;
|
||||
@ -1094,6 +1094,11 @@ class Heap {
|
||||
// Generated code can embed this address to get access to the roots.
|
||||
Object** roots_array_start() { return roots_; }
|
||||
|
||||
ExternalReferenceTable* external_reference_table() {
|
||||
DCHECK(external_reference_table_.is_initialized());
|
||||
return &external_reference_table_;
|
||||
}
|
||||
|
||||
static constexpr int roots_to_external_reference_table_offset() {
|
||||
return kRootsExternalReferenceTableOffset;
|
||||
}
|
||||
@ -2404,7 +2409,7 @@ class Heap {
|
||||
// Isolate::Init() using runtime checks.
|
||||
static constexpr int kRootsExternalReferenceTableOffset =
|
||||
kRootListLength * kPointerSize;
|
||||
ExternalReferenceTable* external_reference_table_ = nullptr;
|
||||
ExternalReferenceTable external_reference_table_;
|
||||
|
||||
size_t code_range_size_;
|
||||
size_t max_semi_space_size_;
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/deoptimizer.h"
|
||||
#include "src/elements.h"
|
||||
#include "src/external-reference-table.h"
|
||||
#include "src/frames-inl.h"
|
||||
#include "src/ic/stub-cache.h"
|
||||
#include "src/instruction-stream.h"
|
||||
|
@ -71,7 +71,6 @@ class DescriptorLookupCache;
|
||||
class EmptyStatement;
|
||||
class EternalHandles;
|
||||
class ExternalCallbackScope;
|
||||
class ExternalReferenceTable;
|
||||
class Factory;
|
||||
class HandleScopeImplementer;
|
||||
class HeapObjectToIndexHashMap;
|
||||
@ -862,14 +861,6 @@ class Isolate {
|
||||
ISOLATE_INIT_LIST(GLOBAL_ACCESSOR)
|
||||
#undef GLOBAL_ACCESSOR
|
||||
|
||||
ExternalReferenceTable* external_reference_table() const {
|
||||
return heap_.external_reference_table_;
|
||||
}
|
||||
|
||||
void set_external_reference_table(ExternalReferenceTable* v) {
|
||||
heap_.external_reference_table_ = v;
|
||||
}
|
||||
|
||||
#define GLOBAL_ARRAY_ACCESSOR(type, name, length) \
|
||||
inline type* name() { \
|
||||
DCHECK(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
|
||||
|
@ -22,7 +22,7 @@ void Deserializer<AllocatorT>::Initialize(Isolate* isolate) {
|
||||
DCHECK_NOT_NULL(isolate);
|
||||
isolate_ = isolate;
|
||||
DCHECK_NULL(external_reference_table_);
|
||||
external_reference_table_ = ExternalReferenceTable::instance(isolate);
|
||||
external_reference_table_ = isolate->heap()->external_reference_table();
|
||||
#ifdef DEBUG
|
||||
// Count the number of external references registered through the API.
|
||||
num_api_references_ = 0;
|
||||
|
@ -22,7 +22,7 @@ ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate) {
|
||||
map_ = new AddressToIndexHashMap();
|
||||
isolate->set_external_reference_map(map_);
|
||||
// Add V8's external references.
|
||||
ExternalReferenceTable* table = ExternalReferenceTable::instance(isolate);
|
||||
ExternalReferenceTable* table = isolate->heap()->external_reference_table();
|
||||
for (uint32_t i = 0; i < table->size(); ++i) {
|
||||
Address addr = table->address(i);
|
||||
// Ignore duplicate references.
|
||||
@ -86,7 +86,7 @@ const char* ExternalReferenceEncoder::NameOfAddress(Isolate* isolate,
|
||||
Address address) const {
|
||||
Maybe<uint32_t> maybe_index = map_->Get(address);
|
||||
if (maybe_index.IsNothing()) return "<unknown>";
|
||||
return ExternalReferenceTable::instance(isolate)->name(
|
||||
return isolate->heap()->external_reference_table()->name(
|
||||
maybe_index.FromJust());
|
||||
}
|
||||
|
||||
@ -98,6 +98,11 @@ void SerializedData::AllocateData(uint32_t size) {
|
||||
DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment));
|
||||
}
|
||||
|
||||
// static
|
||||
uint32_t SerializedData::ComputeMagicNumber(Isolate* isolate) {
|
||||
return ComputeMagicNumber(isolate->heap()->external_reference_table());
|
||||
}
|
||||
|
||||
// The partial snapshot cache is terminated by undefined. We visit the
|
||||
// partial snapshot...
|
||||
// - during deserialization to populate it.
|
||||
|
@ -328,9 +328,7 @@ class SerializedData {
|
||||
|
||||
void AllocateData(uint32_t size);
|
||||
|
||||
static uint32_t ComputeMagicNumber(Isolate* isolate) {
|
||||
return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
|
||||
}
|
||||
static uint32_t ComputeMagicNumber(Isolate* isolate);
|
||||
|
||||
void SetMagicNumber(Isolate* isolate) {
|
||||
SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
|
||||
|
@ -104,7 +104,7 @@ void WriteVersion(Isolate* isolate, Vector<byte> buffer) {
|
||||
DCHECK_GE(buffer.size(), kVersionSize);
|
||||
Writer writer(buffer);
|
||||
writer.Write(SerializedData::ComputeMagicNumber(
|
||||
ExternalReferenceTable::instance(isolate)));
|
||||
isolate->heap()->external_reference_table()));
|
||||
writer.Write(Version::Hash());
|
||||
writer.Write(static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
|
||||
writer.Write(FlagList::Hash());
|
||||
@ -211,7 +211,7 @@ NativeModuleSerializer::NativeModuleSerializer(Isolate* isolate,
|
||||
DCHECK_NOT_NULL(native_module_);
|
||||
// TODO(mtrofin): persist the export wrappers. Ideally, we'd only persist
|
||||
// the unique ones, i.e. the cache.
|
||||
ExternalReferenceTable* table = ExternalReferenceTable::instance(isolate_);
|
||||
ExternalReferenceTable* table = isolate_->heap()->external_reference_table();
|
||||
for (uint32_t i = 0; i < table->size(); ++i) {
|
||||
Address addr = table->address(i);
|
||||
reference_table_lookup_.insert(std::make_pair(addr, i));
|
||||
@ -584,7 +584,7 @@ bool NativeModuleDeserializer::ReadCode() {
|
||||
case RelocInfo::RUNTIME_ENTRY: {
|
||||
uint32_t tag = GetWasmCalleeTag(iter.rinfo());
|
||||
Address address =
|
||||
ExternalReferenceTable::instance(isolate_)->address(tag);
|
||||
isolate_->heap()->external_reference_table()->address(tag);
|
||||
iter.rinfo()->set_target_runtime_entry(address, SKIP_WRITE_BARRIER,
|
||||
SKIP_ICACHE_FLUSH);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user