From b929b52e36c0adbfaf5af3d6a5df13ceb1115a81 Mon Sep 17 00:00:00 2001 From: Igor Sheludko Date: Wed, 10 Oct 2018 17:25:33 +0200 Subject: [PATCH] [ptr-compr] Introduce IsolateData class ... containing RootsTable, ExternalReferenceTable, builtins array and potentially some other data that can be accessed via the RootRegister. This is a preliminary step before adding support for pointer-compression friendly heap layout. Bug: v8:8182 Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: I2899f657aaff1351a5304afa0b1a4c5ae4cfc31d Reviewed-on: https://chromium-review.googlesource.com/c/1245426 Reviewed-by: Jakob Gruber Reviewed-by: Ben Titzer Reviewed-by: Michael Lippautz Reviewed-by: Benedikt Meurer Commit-Queue: Igor Sheludko Cr-Commit-Position: refs/heads/master@{#56551} --- BUILD.gn | 1 + src/builtins/builtins-wasm-gen.cc | 2 +- src/builtins/constants-table-builder.cc | 4 +- src/compiler/code-generator.cc | 3 +- src/compiler/instruction-selector.cc | 2 +- src/compiler/js-heap-broker.cc | 2 +- src/compiler/simplified-lowering.cc | 6 +- src/compiler/wasm-compiler.cc | 2 +- src/compiler/x64/instruction-selector-x64.cc | 6 +- src/disassembler.cc | 22 ++-- src/external-reference.cc | 2 +- src/handles.cc | 3 +- src/heap/factory-inl.h | 8 +- src/heap/factory.cc | 5 +- src/heap/heap-inl.h | 32 ++++- src/heap/heap.cc | 36 +++--- src/heap/heap.h | 109 ++++-------------- src/heap/setup-heap-internal.cc | 20 ++-- src/isolate-data.h | 95 +++++++++++++++ src/isolate-inl.h | 5 +- src/isolate.cc | 14 +-- src/isolate.h | 13 +++ src/roots.h | 1 + src/snapshot/deserializer.cc | 2 +- src/snapshot/serializer-common.cc | 6 +- src/snapshot/startup-serializer.cc | 2 +- src/turbo-assembler.cc | 11 +- src/wasm/wasm-objects.cc | 2 +- src/wasm/wasm-serialization.cc | 9 +- .../instruction-selector-arm64-unittest.cc | 8 +- 30 files changed, 253 insertions(+), 180 deletions(-) create mode 100644 src/isolate-data.h diff --git a/BUILD.gn b/BUILD.gn index 834806811e..4d70482ca8 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -2132,6 +2132,7 @@ v8_source_set("v8_base") { "src/interpreter/interpreter.h", "src/intl.cc", "src/intl.h", + "src/isolate-data.h", "src/isolate-inl.h", "src/isolate.cc", "src/isolate.h", diff --git a/src/builtins/builtins-wasm-gen.cc b/src/builtins/builtins-wasm-gen.cc index 60be33de20..4f7e607c28 100644 --- a/src/builtins/builtins-wasm-gen.cc +++ b/src/builtins/builtins-wasm-gen.cc @@ -29,7 +29,7 @@ class WasmBuiltinsAssembler : public CodeStubAssembler { kHeapObjectTag))); TNode target = UncheckedCast(Load( MachineType::TaggedPointer(), roots, - IntPtrConstant(Heap::roots_to_builtins_offset() + id * kPointerSize))); + IntPtrConstant(IsolateData::kBuiltinsTableOffset + id * kPointerSize))); return target; } diff --git a/src/builtins/constants-table-builder.cc b/src/builtins/constants-table-builder.cc index ccff17a156..5b6d778525 100644 --- a/src/builtins/constants-table-builder.cc +++ b/src/builtins/constants-table-builder.cc @@ -26,7 +26,7 @@ uint32_t BuiltinsConstantsTableBuilder::AddObject(Handle object) { // Roots must not be inserted into the constants table as they are already // accessibly from the root list. RootIndex root_list_index; - DCHECK(!isolate_->heap()->IsRootHandle(object, &root_list_index)); + DCHECK(!isolate_->roots_table().IsRootHandle(object, &root_list_index)); // Not yet finalized. DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(), @@ -56,7 +56,7 @@ void BuiltinsConstantsTableBuilder::PatchSelfReference( // Roots must not be inserted into the constants table as they are already // accessibly from the root list. RootIndex root_list_index; - DCHECK(!isolate_->heap()->IsRootHandle(code_object, &root_list_index)); + DCHECK(!isolate_->roots_table().IsRootHandle(code_object, &root_list_index)); // Not yet finalized. DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(), diff --git a/src/compiler/code-generator.cc b/src/compiler/code-generator.cc index 185d3269ff..143dcb36c6 100644 --- a/src/compiler/code-generator.cc +++ b/src/compiler/code-generator.cc @@ -459,8 +459,7 @@ bool CodeGenerator::IsMaterializableFromRoot(Handle object, const CallDescriptor* incoming_descriptor = linkage()->GetIncomingDescriptor(); if (incoming_descriptor->flags() & CallDescriptor::kCanUseRoots) { - Heap* heap = isolate()->heap(); - return heap->IsRootHandle(object, index_return) && + return isolate()->roots_table().IsRootHandle(object, index_return) && RootsTable::IsImmortalImmovable(*index_return); } return false; diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc index 9a59d3df0a..728bb55105 100644 --- a/src/compiler/instruction-selector.cc +++ b/src/compiler/instruction-selector.cc @@ -472,7 +472,7 @@ InstructionOperand OperandForDeopt(Isolate* isolate, OperandGenerator* g, Handle constant = HeapConstantOf(input->op()); RootIndex root_index; - if (isolate->heap()->IsRootHandle(constant, &root_index) && + if (isolate->roots_table().IsRootHandle(constant, &root_index) && root_index == RootIndex::kOptimizedOut) { // For an optimized-out object we return an invalid instruction // operand, so that we take the fast path for optimized-out values. diff --git a/src/compiler/js-heap-broker.cc b/src/compiler/js-heap-broker.cc index a95bfaad21..8cf05df33c 100644 --- a/src/compiler/js-heap-broker.cc +++ b/src/compiler/js-heap-broker.cc @@ -1393,7 +1393,7 @@ bool IsShareable(Handle object, Isolate* isolate) { RootIndex root_index; return (object->IsHeapObject() && b->IsBuiltinHandle(Handle::cast(object), &index)) || - isolate->heap()->IsRootHandle(object, &root_index); + isolate->roots_table().IsRootHandle(object, &root_index); } void JSHeapBroker::SerializeShareableObjects() { diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index bb22f9baa4..bb2c94fb1d 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -1220,9 +1220,9 @@ class RepresentationSelector { } if (value_type.IsHeapConstant()) { RootIndex root_index; - Heap* heap = jsgraph_->isolate()->heap(); - if (heap->IsRootHandle(value_type.AsHeapConstant()->Value(), - &root_index)) { + const RootsTable& roots_table = jsgraph_->isolate()->roots_table(); + if (roots_table.IsRootHandle(value_type.AsHeapConstant()->Value(), + &root_index)) { if (RootsTable::IsImmortalImmovable(root_index)) { // Write barriers are unnecessary for immortal immovable roots. return kNoWriteBarrier; diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc index 37c600c918..47c25422e9 100644 --- a/src/compiler/wasm-compiler.cc +++ b/src/compiler/wasm-compiler.cc @@ -2996,7 +2996,7 @@ Node* WasmGraphBuilder::BuildLoadBuiltinFromInstance(int builtin_index) { Node* roots = LOAD_INSTANCE_FIELD(RootsArrayAddress, MachineType::TaggedPointer()); return LOAD_TAGGED_POINTER( - roots, Heap::roots_to_builtins_offset() + builtin_index * kPointerSize); + roots, IsolateData::kBuiltinsTableOffset + builtin_index * kPointerSize); } // Only call this function for code which is not reused across instantiations, diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc index 211794ace8..0ec6fd4c60 100644 --- a/src/compiler/x64/instruction-selector-x64.cc +++ b/src/compiler/x64/instruction-selector-x64.cc @@ -1720,11 +1720,11 @@ void VisitWord64Compare(InstructionSelector* selector, Node* node, FlagsContinuation* cont) { X64OperandGenerator g(selector); if (selector->CanUseRootsRegister()) { - Heap* const heap = selector->isolate()->heap(); + const RootsTable& roots_table = selector->isolate()->roots_table(); RootIndex root_index; HeapObjectBinopMatcher m(node); if (m.right().HasValue() && - heap->IsRootHandle(m.right().Value(), &root_index)) { + roots_table.IsRootHandle(m.right().Value(), &root_index)) { if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); InstructionCode opcode = kX64Cmp | AddressingModeField::encode(kMode_Root); @@ -1733,7 +1733,7 @@ void VisitWord64Compare(InstructionSelector* selector, Node* node, g.TempImmediate(TurboAssemblerBase::RootRegisterOffset(root_index)), g.UseRegister(m.left().node()), cont); } else if (m.left().HasValue() && - heap->IsRootHandle(m.left().Value(), &root_index)) { + roots_table.IsRootHandle(m.left().Value(), &root_index)) { InstructionCode opcode = kX64Cmp | AddressingModeField::encode(kMode_Root); return VisitCompare( diff --git a/src/disassembler.cc b/src/disassembler.cc index 0bb59ec0fd..2b60596b7f 100644 --- a/src/disassembler.cc +++ b/src/disassembler.cc @@ -16,6 +16,7 @@ #include "src/disasm.h" #include "src/ic/ic.h" #include "src/instruction-stream.h" +#include "src/isolate-data.h" #include "src/macro-assembler.h" #include "src/objects-inl.h" #include "src/snapshot/serializer-common.h" @@ -55,13 +56,13 @@ class V8NameConverter: public disasm::NameConverter { void V8NameConverter::InitExternalRefsCache() const { ExternalReferenceTable* external_reference_table = - isolate_->heap()->external_reference_table(); + isolate_->external_reference_table(); if (!external_reference_table->is_initialized()) return; base::AddressRegion addressable_region = isolate_->root_register_addressable_region(); Address roots_start = - reinterpret_cast
(isolate_->heap()->roots_array_start()); + reinterpret_cast
(isolate_->roots_array_start()); for (uint32_t i = 0; i < external_reference_table->size(); i++) { Address address = external_reference_table->address(i); @@ -116,13 +117,12 @@ const char* V8NameConverter::NameInCode(byte* addr) const { const char* V8NameConverter::RootRelativeName(int offset) const { if (isolate_ == nullptr) return nullptr; - const int kRootsStart = 0; - const int kRootsEnd = 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; + const int kRootsStart = IsolateData::kRootsTableOffset; + const int kRootsEnd = IsolateData::kRootsTableEndOffset; + const int kExtRefsStart = IsolateData::kExternalReferenceTableOffset; + const int kExtRefsEnd = IsolateData::kExternalReferenceTableEndOffset; + const int kBuiltinsStart = IsolateData::kBuiltinsTableOffset; + const int kBuiltinsEnd = IsolateData::kBuiltinsTableEndOffset; if (kRootsStart <= offset && offset < kRootsEnd) { uint32_t offset_in_roots_table = offset - kRootsStart; @@ -150,12 +150,12 @@ const char* V8NameConverter::RootRelativeName(int offset) const { } // Likewise if the external reference table is uninitialized. - if (!isolate_->heap()->external_reference_table()->is_initialized()) { + if (!isolate_->external_reference_table()->is_initialized()) { return nullptr; } SNPrintF(v8_buffer_, "external reference (%s)", - isolate_->heap()->external_reference_table()->NameFromOffset( + isolate_->external_reference_table()->NameFromOffset( offset_in_extref_table)); return v8_buffer_.start(); diff --git a/src/external-reference.cc b/src/external-reference.cc index 287eef9c18..bd5ca2a0d4 100644 --- a/src/external-reference.cc +++ b/src/external-reference.cc @@ -384,7 +384,7 @@ ExternalReference ExternalReference::log_leave_external_function() { } ExternalReference ExternalReference::roots_array_start(Isolate* isolate) { - return ExternalReference(isolate->heap()->roots_array_start()); + return ExternalReference(isolate->roots_array_start()); } ExternalReference ExternalReference::allocation_sites_list_address( diff --git a/src/handles.cc b/src/handles.cc index f11469d183..0ab8faf20f 100644 --- a/src/handles.cc +++ b/src/handles.cc @@ -29,9 +29,8 @@ bool HandleBase::IsDereferenceAllowed(DereferenceCheckMode mode) const { HeapObject* heap_object = HeapObject::cast(object); Isolate* isolate; if (!Isolate::FromWritableHeapObject(heap_object, &isolate)) return true; - Heap* heap = isolate->heap(); RootIndex root_index; - if (heap->IsRootHandleLocation(location_, &root_index) && + if (isolate->roots_table().IsRootHandleLocation(location_, &root_index) && RootsTable::IsImmortalImmovable(root_index)) { return true; } diff --git a/src/heap/factory-inl.h b/src/heap/factory-inl.h index eb1661aaee..9bcb6a5584 100644 --- a/src/heap/factory-inl.h +++ b/src/heap/factory-inl.h @@ -16,10 +16,10 @@ namespace v8 { namespace internal { -#define ROOT_ACCESSOR(type, name, CamelName) \ - Handle Factory::name() { \ - return Handle(bit_cast( \ - &isolate()->heap()->roots_[RootIndex::k##CamelName])); \ +#define ROOT_ACCESSOR(type, name, CamelName) \ + Handle Factory::name() { \ + return Handle( \ + bit_cast(&isolate()->roots_table()[RootIndex::k##CamelName])); \ } ROOT_LIST(ROOT_ACCESSOR) #undef ROOT_ACCESSOR diff --git a/src/heap/factory.cc b/src/heap/factory.cc index 5bd98c4902..d9d4fa3b67 100644 --- a/src/heap/factory.cc +++ b/src/heap/factory.cc @@ -773,9 +773,8 @@ Handle Factory::AllocateRawOneByteInternalizedString( int length, uint32_t hash_field) { CHECK_GE(String::kMaxLength, length); // The canonical empty_string is the only zero-length string we allow. - DCHECK_IMPLIES( - length == 0, - isolate()->heap()->roots_[RootIndex::kempty_string] == nullptr); + DCHECK_IMPLIES(length == 0, + isolate()->roots_table()[RootIndex::kempty_string] == nullptr); Map* map = *one_byte_internalized_string_map(); int size = SeqOneByteString::SizeFor(length); diff --git a/src/heap/heap-inl.h b/src/heap/heap-inl.h index ddda7322a2..852c96f4d8 100644 --- a/src/heap/heap-inl.h +++ b/src/heap/heap-inl.h @@ -55,8 +55,10 @@ HeapObject* AllocationResult::ToObjectChecked() { return HeapObject::cast(object_); } -#define ROOT_ACCESSOR(type, name, CamelName) \ - type* Heap::name() { return type::cast(roots_[RootIndex::k##CamelName]); } +#define ROOT_ACCESSOR(type, name, CamelName) \ + type* Heap::name() { \ + return type::cast(roots_table()[RootIndex::k##CamelName]); \ + } MUTABLE_ROOT_LIST(ROOT_ACCESSOR) #undef ROOT_ACCESSOR @@ -68,11 +70,35 @@ MUTABLE_ROOT_LIST(ROOT_ACCESSOR) !RootsTable::IsImmortalImmovable(RootIndex::k##CamelName)); \ DCHECK_IMPLIES(RootsTable::IsImmortalImmovable(RootIndex::k##CamelName), \ IsImmovable(HeapObject::cast(value))); \ - roots_[RootIndex::k##CamelName] = value; \ + roots_table()[RootIndex::k##CamelName] = value; \ } ROOT_LIST(ROOT_ACCESSOR) #undef ROOT_ACCESSOR +void Heap::SetRootCodeStubs(SimpleNumberDictionary* value) { + roots_table()[RootIndex::kCodeStubs] = value; +} + +void Heap::SetRootMaterializedObjects(FixedArray* objects) { + roots_table()[RootIndex::kMaterializedObjects] = objects; +} + +void Heap::SetRootScriptList(Object* value) { + roots_table()[RootIndex::kScriptList] = value; +} + +void Heap::SetRootStringTable(StringTable* value) { + roots_table()[RootIndex::kStringTable] = value; +} + +void Heap::SetRootNoScriptSharedFunctionInfos(Object* value) { + roots_table()[RootIndex::kNoScriptSharedFunctionInfos] = value; +} + +void Heap::SetMessageListeners(TemplateList* value) { + roots_table()[RootIndex::kMessageListeners] = value; +} + PagedSpace* Heap::paged_space(int idx) { DCHECK_NE(idx, LO_SPACE); DCHECK_NE(idx, NEW_SPACE); diff --git a/src/heap/heap.cc b/src/heap/heap.cc index 4aea34b66f..11484d0785 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -605,10 +605,6 @@ const char* Heap::GetSpaceName(int idx) { return nullptr; } -void Heap::SetRootCodeStubs(SimpleNumberDictionary* value) { - roots_[RootIndex::kCodeStubs] = value; -} - void Heap::RepairFreeListsAfterDeserialization() { PagedSpaces spaces(this); for (PagedSpace* space = spaces.next(); space != nullptr; @@ -3645,12 +3641,12 @@ Code* Heap::builtin(int index) { DCHECK(Builtins::IsBuiltinId(index)); // Code::cast cannot be used here since we access builtins // during the marking phase of mark sweep. See IC::Clear. - return reinterpret_cast(builtins_[index]); + return reinterpret_cast(builtins_table()[index]); } Address Heap::builtin_address(int index) { DCHECK(Builtins::IsBuiltinId(index) || index == Builtins::builtin_count); - return reinterpret_cast
(&builtins_[index]); + return reinterpret_cast
(&builtins_table()[index]); } void Heap::set_builtin(int index, HeapObject* builtin) { @@ -3658,7 +3654,7 @@ void Heap::set_builtin(int index, HeapObject* builtin) { DCHECK(Internals::HasHeapObjectTag(builtin)); // The given builtin may be completely uninitialized thus we cannot check its // type here. - builtins_[index] = builtin; + builtins_table()[index] = builtin; } void Heap::IterateRoots(RootVisitor* v, VisitMode mode) { @@ -3671,7 +3667,7 @@ void Heap::IterateWeakRoots(RootVisitor* v, VisitMode mode) { mode == VISIT_ALL_IN_MINOR_MC_MARK || mode == VISIT_ALL_IN_MINOR_MC_UPDATE; v->VisitRootPointer(Root::kStringTable, nullptr, - &roots_[RootIndex::kStringTable]); + &roots_table()[RootIndex::kStringTable]); v->Synchronize(VisitorSynchronization::kStringTable); if (!isMinorGC && mode != VISIT_ALL_IN_SWEEP_NEWSPACE && mode != VISIT_FOR_SERIALIZATION) { @@ -3686,8 +3682,9 @@ void Heap::IterateWeakRoots(RootVisitor* v, VisitMode mode) { void Heap::IterateSmiRoots(RootVisitor* v) { // Acquire execution access since we are going to read stack limit values. ExecutionAccess access(isolate()); - v->VisitRootPointers(Root::kSmiRootList, nullptr, roots_.smi_roots_begin(), - roots_.smi_roots_end()); + v->VisitRootPointers(Root::kSmiRootList, nullptr, + roots_table().smi_roots_begin(), + roots_table().smi_roots_end()); v->Synchronize(VisitorSynchronization::kSmiRootList); } @@ -3747,10 +3744,10 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) { // Garbage collection can skip over the read-only roots. const bool isGC = mode != VISIT_ALL && mode != VISIT_FOR_SERIALIZATION && mode != VISIT_ONLY_STRONG_FOR_SERIALIZATION; - Object** start = - isGC ? roots_.read_only_roots_end() : roots_.strong_roots_begin(); + Object** start = isGC ? roots_table().read_only_roots_end() + : roots_table().strong_roots_begin(); v->VisitRootPointers(Root::kStrongRootList, nullptr, start, - roots_.strong_roots_end()); + roots_table().strong_roots_end()); v->Synchronize(VisitorSynchronization::kStrongRootList); isolate_->bootstrapper()->Iterate(v); @@ -3844,7 +3841,8 @@ void Heap::IterateWeakGlobalHandles(RootVisitor* v) { void Heap::IterateBuiltins(RootVisitor* v) { for (int i = 0; i < Builtins::builtin_count; i++) { - v->VisitRootPointer(Root::kBuiltins, Builtins::name(i), &builtins_[i]); + v->VisitRootPointer(Root::kBuiltins, Builtins::name(i), + &builtins_table()[i]); } } @@ -4393,7 +4391,7 @@ void Heap::SetUp() { write_protect_code_memory_ = FLAG_write_protect_code_memory; - external_reference_table_.Init(isolate_); + isolate_data_.external_reference_table()->Init(isolate_); } void Heap::InitializeHashSeed() { @@ -4415,15 +4413,15 @@ void Heap::SetStackLimits() { // Set up the special root array entries containing the stack limits. // These are actually addresses, but the tag makes the GC ignore it. - roots_[RootIndex::kStackLimit] = reinterpret_cast( + roots_table()[RootIndex::kStackLimit] = reinterpret_cast( (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag); - roots_[RootIndex::kRealStackLimit] = reinterpret_cast( + roots_table()[RootIndex::kRealStackLimit] = reinterpret_cast( (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag); } void Heap::ClearStackLimits() { - roots_[RootIndex::kStackLimit] = Smi::kZero; - roots_[RootIndex::kRealStackLimit] = Smi::kZero; + roots_table()[RootIndex::kStackLimit] = Smi::kZero; + roots_table()[RootIndex::kRealStackLimit] = Smi::kZero; } int Heap::NextAllocationTimeout(int current_timeout) { diff --git a/src/heap/heap.h b/src/heap/heap.h index b1410d2ed7..696f7fcd95 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -19,13 +19,12 @@ #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/isolate-data.h" #include "src/objects.h" #include "src/objects/fixed-array.h" #include "src/objects/string-table.h" -#include "src/roots.h" #include "src/visitors.h" namespace v8 { @@ -638,82 +637,39 @@ class Heap { return array_buffer_collector_; } + const IsolateData* isolate_data() const { return &isolate_data_; } + IsolateData* isolate_data() { return &isolate_data_; } + // =========================================================================== // Root set access. ========================================================== // =========================================================================== - friend class ReadOnlyRoots; - public: - RootsTable& roots_table() { return roots_; } + // Shortcut to the roots table stored in |isolate_data_|. + V8_INLINE const RootsTable& roots_table() const { + return isolate_data_.roots(); + } + V8_INLINE RootsTable& roots_table() { return isolate_data_.roots(); } // Heap root getters. #define ROOT_ACCESSOR(type, name, CamelName) inline type* name(); MUTABLE_ROOT_LIST(ROOT_ACCESSOR) #undef ROOT_ACCESSOR - Object* root(RootIndex index) { return roots_[index]; } + // TODO(ishell): move to Isolate + Object* root(RootIndex index) { return roots_table()[index]; } Handle root_handle(RootIndex index) { - return Handle(&roots_[index]); - } - - bool IsRootHandleLocation(Object** handle_location, RootIndex* index) const { - return roots_.IsRootHandleLocation(handle_location, index); - } - - template - bool IsRootHandle(Handle handle, RootIndex* index) const { - return roots_.IsRootHandle(handle, index); - } - - // Generated code can embed this address to get access to the roots. - Object** roots_array_start() { return roots_.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; - } - - static constexpr int roots_to_builtins_offset() { - return kRootsBuiltinsOffset; - } - - static constexpr int root_register_addressable_end_offset() { - return kRootRegisterAddressableEndOffset; - } - - Address root_register_addressable_end() { - return reinterpret_cast
(roots_array_start()) + - kRootRegisterAddressableEndOffset; + return Handle(&roots_table()[index]); } // Sets the stub_cache_ (only used when expanding the dictionary). - void SetRootCodeStubs(SimpleNumberDictionary* value); + V8_INLINE void SetRootCodeStubs(SimpleNumberDictionary* value); + V8_INLINE void SetRootMaterializedObjects(FixedArray* objects); + V8_INLINE void SetRootScriptList(Object* value); + V8_INLINE void SetRootStringTable(StringTable* value); + V8_INLINE void SetRootNoScriptSharedFunctionInfos(Object* value); + V8_INLINE void SetMessageListeners(TemplateList* value); - void SetRootMaterializedObjects(FixedArray* objects) { - roots_[RootIndex::kMaterializedObjects] = objects; - } - - void SetRootScriptList(Object* value) { - roots_[RootIndex::kScriptList] = value; - } - - void SetRootStringTable(StringTable* value) { - roots_[RootIndex::kStringTable] = value; - } - - void SetRootNoScriptSharedFunctionInfos(Object* value) { - roots_[RootIndex::kNoScriptSharedFunctionInfos] = value; - } - - void SetMessageListeners(TemplateList* value) { - roots_[RootIndex::kMessageListeners] = value; - } - - // Set the stack limit in the roots_ array. Some architectures generate + // Set the stack limit in the roots table. Some architectures generate // code that looks here, because it is faster than loading from the static // jslimit_/real_jslimit_ variable in the StackGuard. void SetStackLimits(); @@ -783,6 +739,9 @@ class Heap { // Builtins. ================================================================= // =========================================================================== + // Shortcut to the builtins table stored in |isolate_data_|. + V8_INLINE Object** builtins_table() { return isolate_data_.builtins(); } + Code* builtin(int index); Address builtin_address(int index); void set_builtin(int index, HeapObject* builtin); @@ -1797,28 +1756,7 @@ class Heap { // more expedient to get at the isolate directly from within Heap methods. Isolate* isolate_ = nullptr; - RootsTable roots_; - - // This table is accessed from builtin code compiled into the snapshot, and - // thus its offset from roots_ must remain static. This is verified in - // Isolate::Init() using runtime checks. - static constexpr int kRootsExternalReferenceTableOffset = - static_cast(RootIndex::kRootListLength) * kPointerSize; - ExternalReferenceTable external_reference_table_; - - // As external references above, builtins are accessed through an offset from - // the roots register. Its offset from roots_ must remain static. This is - // verified in Isolate::Init() using runtime checks. - static constexpr int kRootsBuiltinsOffset = - kRootsExternalReferenceTableOffset + - ExternalReferenceTable::SizeInBytes(); - Object* builtins_[Builtins::builtin_count]; - - // kRootRegister may be used to address any location that starts at the - // Isolate and ends at this point. Fields past this point are not guaranteed - // to live at a static offset from kRootRegister. - static constexpr int kRootRegisterAddressableEndOffset = - kRootsBuiltinsOffset + Builtins::builtin_count * kPointerSize; + IsolateData isolate_data_; size_t code_range_size_ = 0; size_t max_semi_space_size_ = 8 * (kPointerSize / 4) * MB; @@ -2094,6 +2032,7 @@ class Heap { friend class ObjectStatsCollector; friend class Page; friend class PagedSpace; + friend class ReadOnlyRoots; friend class Scavenger; friend class ScavengerCollector; friend class Space; diff --git a/src/heap/setup-heap-internal.cc b/src/heap/setup-heap-internal.cc index 37f856579d..c9ef64de8a 100644 --- a/src/heap/setup-heap-internal.cc +++ b/src/heap/setup-heap-internal.cc @@ -292,7 +292,7 @@ bool Heap::CreateInitialMaps() { const StructTable& entry = struct_table[i]; Map* map; if (!AllocatePartialMap(entry.type, entry.size).To(&map)) return false; - roots_[entry.index] = map; + roots_table()[entry.index] = map; } // Allocate the empty enum cache. @@ -334,7 +334,7 @@ bool Heap::CreateInitialMaps() { FinalizePartialMap(roots.the_hole_map()); for (unsigned i = 0; i < arraysize(struct_table); ++i) { const StructTable& entry = struct_table[i]; - FinalizePartialMap(Map::cast(roots_[entry.index])); + FinalizePartialMap(Map::cast(roots_table()[entry.index])); } { // Map allocation @@ -389,7 +389,7 @@ bool Heap::CreateInitialMaps() { // Mark cons string maps as unstable, because their objects can change // maps during GC. if (StringShape(entry.type).IsCons()) map->mark_unstable(); - roots_[entry.index] = map; + roots_table()[entry.index] = map; } { // Create a separate external one byte string map for native sources. @@ -635,7 +635,7 @@ void Heap::CreateInitialObjects() { for (unsigned i = 0; i < arraysize(constant_string_table); i++) { Handle str = factory->InternalizeUtf8String(constant_string_table[i].contents); - roots_[constant_string_table[i].index] = *str; + roots_table()[constant_string_table[i].index] = *str; } // Allocate @@ -705,7 +705,7 @@ void Heap::CreateInitialObjects() { { \ Handle symbol( \ isolate()->factory()->NewPrivateSymbol(TENURED_READ_ONLY)); \ - roots_[RootIndex::k##name] = *symbol; \ + roots_table()[RootIndex::k##name] = *symbol; \ } PRIVATE_SYMBOL_LIST_GENERATOR(SYMBOL_INIT, /* not used */) #undef SYMBOL_INIT @@ -718,7 +718,7 @@ void Heap::CreateInitialObjects() { Handle name##d = \ factory->NewStringFromStaticChars(#description, TENURED_READ_ONLY); \ name->set_name(*name##d); \ - roots_[RootIndex::k##name] = *name; + roots_table()[RootIndex::k##name] = *name; PUBLIC_SYMBOL_LIST_GENERATOR(SYMBOL_INIT, /* not used */) #undef SYMBOL_INIT @@ -728,7 +728,7 @@ void Heap::CreateInitialObjects() { factory->NewStringFromStaticChars(#description, TENURED_READ_ONLY); \ name->set_is_well_known_symbol(true); \ name->set_name(*name##d); \ - roots_[RootIndex::k##name] = *name; + roots_table()[RootIndex::k##name] = *name; WELL_KNOWN_SYMBOL_LIST_GENERATOR(SYMBOL_INIT, /* not used */) #undef SYMBOL_INIT @@ -916,15 +916,15 @@ void Heap::CreateInternalAccessorInfoObjects() { #define INIT_ACCESSOR_INFO(_, accessor_name, AccessorName, ...) \ acessor_info = Accessors::Make##AccessorName##Info(isolate); \ - roots_[RootIndex::k##AccessorName##Accessor] = *acessor_info; + roots_table()[RootIndex::k##AccessorName##Accessor] = *acessor_info; ACCESSOR_INFO_LIST_GENERATOR(INIT_ACCESSOR_INFO, /* not used */) #undef INIT_ACCESSOR_INFO #define INIT_SIDE_EFFECT_FLAG(_, accessor_name, AccessorName, GetterType, \ SetterType) \ - AccessorInfo::cast(roots_[RootIndex::k##AccessorName##Accessor]) \ + AccessorInfo::cast(roots_table()[RootIndex::k##AccessorName##Accessor]) \ ->set_getter_side_effect_type(SideEffectType::GetterType); \ - AccessorInfo::cast(roots_[RootIndex::k##AccessorName##Accessor]) \ + AccessorInfo::cast(roots_table()[RootIndex::k##AccessorName##Accessor]) \ ->set_setter_side_effect_type(SideEffectType::SetterType); ACCESSOR_INFO_LIST_GENERATOR(INIT_SIDE_EFFECT_FLAG, /* not used */) #undef INIT_SIDE_EFFECT_FLAG diff --git a/src/isolate-data.h b/src/isolate-data.h new file mode 100644 index 0000000000..183d929f07 --- /dev/null +++ b/src/isolate-data.h @@ -0,0 +1,95 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_ISOLATE_DATA_H_ +#define V8_ISOLATE_DATA_H_ + +#include "src/builtins/builtins.h" +#include "src/external-reference-table.h" +#include "src/roots.h" +#include "src/utils.h" + +namespace v8 { +namespace internal { + +class Isolate; + +// This class contains a collection of data accessible from both C++ runtime +// and compiled code (including assembly stubs, builtins, interpreter bytecode +// handlers and optimized code). +// In particular, it contains pointer to the V8 heap roots table, external +// reference table and builtins array. +// The compiled code accesses the isolate data fields indirectly via the root +// register. +class IsolateData final { + public: + IsolateData() = default; + +// Layout description. +#define FIELDS(V) \ + /* roots_ */ \ + V(kRootsTableOffset, RootsTable::kEntriesCount* kPointerSize) \ + V(kRootsTableEndOffset, 0) \ + /* external_reference_table_ */ \ + V(kExternalReferenceTableOffset, ExternalReferenceTable::SizeInBytes()) \ + V(kExternalReferenceTableEndOffset, 0) \ + /* builtins_ */ \ + V(kBuiltinsTableOffset, Builtins::builtin_count* kPointerSize) \ + V(kBuiltinsTableEndOffset, 0) \ + /* Total size. */ \ + V(kSize, 0) + + DEFINE_FIELD_OFFSET_CONSTANTS(0, FIELDS) +#undef FIELDS + + // Returns true if this address points to data stored in this instance. + // If it's the case then the value can be accessed indirectly through the + // root register. + bool contains(Address address) const { + STATIC_ASSERT(std::is_unsigned
::value); + Address start = reinterpret_cast
(this); + return (address - start) < sizeof(*this); + } + + RootsTable& roots() { return roots_; } + const RootsTable& roots() const { return roots_; } + + ExternalReferenceTable* external_reference_table() { + return &external_reference_table_; + } + + Object** builtins() { return &builtins_[0]; } + + private: + RootsTable roots_; + + ExternalReferenceTable external_reference_table_; + + Object* builtins_[Builtins::builtin_count]; + + V8_INLINE static void AssertPredictableLayout(); + + friend class Isolate; + + DISALLOW_COPY_AND_ASSIGN(IsolateData); +}; + +// IsolateData object must have "predictable" layout which does not change when +// cross-compiling to another platform. Otherwise there may be compatibility +// issues because of different compilers used for snapshot generator and +// actual V8 code. +void IsolateData::AssertPredictableLayout() { + STATIC_ASSERT(offsetof(IsolateData, roots_) == + IsolateData::kRootsTableOffset); + STATIC_ASSERT(offsetof(IsolateData, external_reference_table_) == + IsolateData::kExternalReferenceTableOffset); + STATIC_ASSERT(offsetof(IsolateData, builtins_) == + IsolateData::kBuiltinsTableOffset); + STATIC_ASSERT(sizeof(IsolateData) == IsolateData::kSize); +} + +} // namespace internal +} // namespace v8 + +#endif // V8_ISOLATE_DATA_H_ diff --git a/src/isolate-inl.h b/src/isolate-inl.h index 3e7378b731..56ff3e65ee 100644 --- a/src/isolate-inl.h +++ b/src/isolate-inl.h @@ -12,8 +12,11 @@ namespace v8 { namespace internal { base::AddressRegion Isolate::root_register_addressable_region() { + // TODO(ishell): limit this region to the IsolateData object once all the + // data is moved there. Address start = reinterpret_cast
(this); - Address end = heap_.root_register_addressable_end(); + Address end = + reinterpret_cast
(heap_.isolate_data()) + sizeof(IsolateData); return base::AddressRegion(start, end - start); } diff --git a/src/isolate.cc b/src/isolate.cc index 3febd5d102..daab7ea762 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -3281,7 +3281,7 @@ bool Isolate::Init(StartupDeserializer* des) { CHECK_EQ(static_cast(OFFSET_OF(Isolate, embedder_data_)), Internals::kIsolateEmbedderDataOffset); - CHECK_EQ(static_cast(OFFSET_OF(Isolate, heap_.roots_)), + CHECK_EQ(static_cast(OFFSET_OF(Isolate, heap_.isolate_data_.roots_)), Internals::kIsolateRootsOffset); CHECK_EQ(static_cast(OFFSET_OF(Isolate, heap_.external_memory_)), Internals::kExternalMemoryOffset); @@ -3290,12 +3290,12 @@ bool Isolate::Init(StartupDeserializer* des) { CHECK_EQ(static_cast( OFFSET_OF(Isolate, heap_.external_memory_at_last_mark_compact_)), Internals::kExternalMemoryAtLastMarkCompactOffset); - CHECK_EQ( - static_cast(OFFSET_OF(Isolate, heap_.external_reference_table_)), - Internals::kIsolateRootsOffset + - Heap::kRootsExternalReferenceTableOffset); - CHECK_EQ(static_cast(OFFSET_OF(Isolate, heap_.builtins_)), - Internals::kIsolateRootsOffset + Heap::kRootsBuiltinsOffset); + CHECK_EQ(static_cast(OFFSET_OF( + Isolate, heap_.isolate_data_.external_reference_table_)), + Internals::kIsolateRootsOffset + + IsolateData::kExternalReferenceTableOffset); + CHECK_EQ(static_cast(OFFSET_OF(Isolate, heap_.isolate_data_.builtins_)), + Internals::kIsolateRootsOffset + IsolateData::kBuiltinsTableOffset); { HandleScope scope(this); diff --git a/src/isolate.h b/src/isolate.h index d0c665466c..d06f5d41cb 100644 --- a/src/isolate.h +++ b/src/isolate.h @@ -999,11 +999,24 @@ class Isolate : private HiddenFactory { StackGuard* stack_guard() { return &stack_guard_; } Heap* heap() { return &heap_; } + const IsolateData* isolate_data() const { return heap_.isolate_data(); } + IsolateData* isolate_data() { return heap_.isolate_data(); } + + RootsTable& roots_table() { return isolate_data()->roots(); } + + // Generated code can embed this address to get access to the roots. + Object** roots_array_start() { return roots_table().roots_; } + // 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(); + ExternalReferenceTable* external_reference_table() { + DCHECK(isolate_data()->external_reference_table()->is_initialized()); + return isolate_data()->external_reference_table(); + } + StubCache* load_stub_cache() { return load_stub_cache_; } StubCache* store_stub_cache() { return store_stub_cache_; } DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; } diff --git a/src/roots.h b/src/roots.h index 5b475999e8..596a45c5a6 100644 --- a/src/roots.h +++ b/src/roots.h @@ -449,6 +449,7 @@ class RootsTable { Object* roots_[kEntriesCount]; + friend class Isolate; friend class Heap; friend class Factory; friend class ReadOnlyRoots; diff --git a/src/snapshot/deserializer.cc b/src/snapshot/deserializer.cc index 53c8983b30..88e04f81e7 100644 --- a/src/snapshot/deserializer.cc +++ b/src/snapshot/deserializer.cc @@ -26,7 +26,7 @@ void Deserializer::Initialize(Isolate* isolate) { DCHECK_NOT_NULL(isolate); isolate_ = isolate; DCHECK_NULL(external_reference_table_); - external_reference_table_ = isolate->heap()->external_reference_table(); + external_reference_table_ = isolate->external_reference_table(); #ifdef DEBUG // Count the number of external references registered through the API. num_api_references_ = 0; diff --git a/src/snapshot/serializer-common.cc b/src/snapshot/serializer-common.cc index d5a8cf1273..0852e8f743 100644 --- a/src/snapshot/serializer-common.cc +++ b/src/snapshot/serializer-common.cc @@ -22,7 +22,7 @@ ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate) { map_ = new AddressToIndexHashMap(); isolate->set_external_reference_map(map_); // Add V8's external references. - ExternalReferenceTable* table = isolate->heap()->external_reference_table(); + ExternalReferenceTable* table = isolate->external_reference_table(); for (uint32_t i = 0; i < table->size(); ++i) { Address addr = table->address(i); // Ignore duplicate references. @@ -89,7 +89,7 @@ const char* ExternalReferenceEncoder::NameOfAddress(Isolate* isolate, if (maybe_index.IsNothing()) return ""; Value value(maybe_index.FromJust()); if (value.is_from_api()) return ""; - return isolate->heap()->external_reference_table()->name(value.index()); + return isolate->external_reference_table()->name(value.index()); } void SerializedData::AllocateData(uint32_t size) { @@ -102,7 +102,7 @@ void SerializedData::AllocateData(uint32_t size) { // static uint32_t SerializedData::ComputeMagicNumber(Isolate* isolate) { - return ComputeMagicNumber(isolate->heap()->external_reference_table()); + return ComputeMagicNumber(isolate->external_reference_table()); } // The partial snapshot cache is terminated by undefined. We visit the diff --git a/src/snapshot/startup-serializer.cc b/src/snapshot/startup-serializer.cc index 4b187a7ca4..ab274fbd42 100644 --- a/src/snapshot/startup-serializer.cc +++ b/src/snapshot/startup-serializer.cc @@ -122,7 +122,7 @@ void StartupSerializer::SerializeStrongReferences() { void StartupSerializer::VisitRootPointers(Root root, const char* description, Object** start, Object** end) { - if (start == isolate()->heap()->roots_array_start()) { + if (start == isolate()->roots_array_start()) { // Serializing the root list needs special handling: // - Only root list elements that have been fully serialized can be // referenced using kRootArray bytecodes. diff --git a/src/turbo-assembler.cc b/src/turbo-assembler.cc index 4bb09047bb..422303e43f 100644 --- a/src/turbo-assembler.cc +++ b/src/turbo-assembler.cc @@ -6,7 +6,8 @@ #include "src/builtins/builtins.h" #include "src/builtins/constants-table-builder.h" -#include "src/heap/heap-inl.h" +#include "src/isolate-data.h" +#include "src/isolate-inl.h" #include "src/lsan.h" #include "src/snapshot/serializer-common.h" @@ -33,7 +34,7 @@ void TurboAssemblerBase::IndirectLoadConstant(Register destination, int builtin_index; RootIndex root_index; - if (isolate()->heap()->IsRootHandle(object, &root_index)) { + if (isolate()->roots_table().IsRootHandle(object, &root_index)) { // Roots are loaded relative to the root register. LoadRoot(destination, root_index); } else if (isolate()->builtins()->IsBuiltinHandle(object, &builtin_index)) { @@ -92,7 +93,7 @@ int32_t TurboAssemblerBase::RootRegisterOffset(RootIndex root_index) { // static int32_t TurboAssemblerBase::RootRegisterOffsetForExternalReferenceIndex( int reference_index) { - return Heap::roots_to_external_reference_table_offset() - kRootRegisterBias + + return IsolateData::kExternalReferenceTableOffset - kRootRegisterBias + ExternalReferenceTable::OffsetOfEntry(reference_index); } @@ -100,7 +101,7 @@ int32_t TurboAssemblerBase::RootRegisterOffsetForExternalReferenceIndex( intptr_t TurboAssemblerBase::RootRegisterOffsetForExternalReference( Isolate* isolate, const ExternalReference& reference) { return static_cast(reference.address()) - kRootRegisterBias - - reinterpret_cast(isolate->heap()->roots_array_start()); + reinterpret_cast(isolate->roots_array_start()); } // static @@ -113,7 +114,7 @@ bool TurboAssemblerBase::IsAddressableThroughRootRegister( // static int32_t TurboAssemblerBase::RootRegisterOffsetForBuiltinIndex( int builtin_index) { - return Heap::roots_to_builtins_offset() - kRootRegisterBias + + return IsolateData::kBuiltinsTableOffset - kRootRegisterBias + builtin_index * kPointerSize; } diff --git a/src/wasm/wasm-objects.cc b/src/wasm/wasm-objects.cc index 8e7f63e853..dac1482dc8 100644 --- a/src/wasm/wasm-objects.cc +++ b/src/wasm/wasm-objects.cc @@ -1288,7 +1288,7 @@ Handle WasmInstanceObject::New( instance->SetRawMemory(nullptr, 0); instance->set_roots_array_address( - reinterpret_cast
(isolate->heap()->roots_array_start())); + reinterpret_cast
(isolate->roots_array_start())); instance->set_stack_limit_address( isolate->stack_guard()->address_of_jslimit()); instance->set_real_stack_limit_address( diff --git a/src/wasm/wasm-serialization.cc b/src/wasm/wasm-serialization.cc index b676a5b61b..a8d6dbdfcb 100644 --- a/src/wasm/wasm-serialization.cc +++ b/src/wasm/wasm-serialization.cc @@ -120,8 +120,8 @@ class Reader { constexpr size_t kVersionSize = 4 * sizeof(uint32_t); void WriteVersion(Isolate* isolate, Writer* writer) { - writer->Write(SerializedData::ComputeMagicNumber( - isolate->heap()->external_reference_table())); + writer->Write( + SerializedData::ComputeMagicNumber(isolate->external_reference_table())); writer->Write(Version::Hash()); writer->Write(static_cast(CpuFeatures::SupportedFeatures())); writer->Write(FlagList::Hash()); @@ -243,7 +243,7 @@ NativeModuleSerializer::NativeModuleSerializer( ->instruction_start(); wasm_stub_targets_lookup_.insert(std::make_pair(addr, i)); } - ExternalReferenceTable* table = isolate_->heap()->external_reference_table(); + ExternalReferenceTable* table = isolate_->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)); @@ -501,8 +501,7 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) { } case RelocInfo::EXTERNAL_REFERENCE: { uint32_t tag = GetWasmCalleeTag(iter.rinfo()); - Address address = - isolate_->heap()->external_reference_table()->address(tag); + Address address = isolate_->external_reference_table()->address(tag); iter.rinfo()->set_target_external_reference(address, SKIP_ICACHE_FLUSH); break; } diff --git a/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc b/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc index aa54abe320..f62b8cc7af 100644 --- a/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc +++ b/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc @@ -4543,8 +4543,8 @@ TEST_F(InstructionSelectorTest, ExternalReferenceLoad1) { TRACED_FOREACH(int64_t, offset, kOffsets) { StreamBuilder m(this, MachineType::Int64()); ExternalReference reference = bit_cast( - reinterpret_cast(isolate()->heap()->roots_array_start()) + - offset + kRootRegisterBias); + reinterpret_cast(isolate()->roots_array_start()) + offset + + kRootRegisterBias); Node* const value = m.Load(MachineType::Int64(), m.ExternalConstant(reference)); m.Return(value); @@ -4565,8 +4565,8 @@ TEST_F(InstructionSelectorTest, ExternalReferenceLoad2) { StreamBuilder m(this, MachineType::Int64()); int64_t offset = 0x100000000; ExternalReference reference = bit_cast( - reinterpret_cast(isolate()->heap()->roots_array_start()) + - offset + kRootRegisterBias); + reinterpret_cast(isolate()->roots_array_start()) + offset + + kRootRegisterBias); Node* const value = m.Load(MachineType::Int64(), m.ExternalConstant(reference)); m.Return(value);