Commit 64e0921a authored by jgruber's avatar jgruber Committed by Commit Bot

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: 's avatarMichael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52211}
parent 20ab39e7
......@@ -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;
......
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