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:
jgruber 2018-03-26 11:24:15 +02:00 committed by Commit Bot
parent 20ab39e7c9
commit 64e0921ad7
11 changed files with 36 additions and 51 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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;

View File

@ -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_;

View File

@ -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"

View File

@ -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_); \

View File

@ -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;

View File

@ -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.

View File

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

View File

@ -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;