diff --git a/BUILD.gn b/BUILD.gn index 9a1124e7d1..871aae846c 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -65,6 +65,7 @@ declare_args() { v8_enable_fast_mksnapshot = false # Enable embedded builtins. + # TODO(jgruber,v8:6666): Support ia32. v8_enable_embedded_builtins = false # Enable code-generation-time checking of types in the CodeStubAssembler. @@ -1326,6 +1327,8 @@ v8_source_set("v8_base") { "src/builtins/builtins-utils.h", "src/builtins/builtins.cc", "src/builtins/builtins.h", + "src/builtins/constants-table-builder.cc", + "src/builtins/constants-table-builder.h", "src/cached-powers.cc", "src/cached-powers.h", "src/callable.h", diff --git a/src/builtins/builtins.cc b/src/builtins/builtins.cc index 807b2ec5f5..a6a17c182e 100644 --- a/src/builtins/builtins.cc +++ b/src/builtins/builtins.cc @@ -283,14 +283,28 @@ bool Builtins::IsIsolateIndependent(int index) { case kContinueToJavaScriptBuiltin: case kContinueToJavaScriptBuiltinWithResult: #ifndef DEBUG -#if !V8_TARGET_ARCH_IA32 + case kAsyncFunctionAwaitFulfill: + case kAsyncFunctionAwaitReject: + case kAsyncGeneratorAwaitFulfill: + case kAsyncGeneratorAwaitReject: + case kAsyncGeneratorReturnClosedFulfill: + case kAsyncGeneratorReturnClosedReject: + case kAsyncGeneratorReturnFulfill: + case kAsyncGeneratorYieldFulfill: case kConstructFunction: - case kTypeof: - case kWeakMapLookupHashIndex: -#endif + case kKeyedLoadICTrampoline: + case kKeyedStoreICTrampoline: + case kLoadGlobalICInsideTypeofTrampoline: + case kLoadGlobalICTrampoline: case kLoadIC_StringLength: case kLoadIC_StringWrapperLength: + case kLoadICTrampoline: case kOrderedHashTableHealIndex: + case kStoreGlobalICTrampoline: + case kStoreICTrampoline: + case kStringRepeat: + case kTypeof: + case kWeakMapLookupHashIndex: #endif return true; default: diff --git a/src/builtins/constants-table-builder.cc b/src/builtins/constants-table-builder.cc new file mode 100644 index 0000000000..6c6d8a9c0b --- /dev/null +++ b/src/builtins/constants-table-builder.cc @@ -0,0 +1,74 @@ +// 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. + +#include "src/builtins/constants-table-builder.h" + +#include "src/heap/heap-inl.h" + +namespace v8 { +namespace internal { + +BuiltinsConstantsTableBuilder::BuiltinsConstantsTableBuilder(Isolate* isolate) + : isolate_(isolate), map_(isolate->heap()) { + // Ensure this is only called once per Isolate. + DCHECK_EQ(isolate_->heap()->empty_fixed_array(), + isolate_->heap()->builtins_constants_table()); + + // And that the initial value of the builtins constants table can be treated + // as a constant, which means that codegen will load it using the root + // register. + DCHECK(isolate_->heap()->RootCanBeTreatedAsConstant( + Heap::kEmptyFixedArrayRootIndex)); +} + +uint32_t BuiltinsConstantsTableBuilder::AddObject(Handle object) { +#ifdef DEBUG + // Roots must not be inserted into the constants table as they are already + // accessibly from the root list. + Heap::RootListIndex root_list_index; + DCHECK(!isolate_->heap()->IsRootHandle(object, &root_list_index)); + + // Not yet finalized. + DCHECK_EQ(isolate_->heap()->empty_fixed_array(), + isolate_->heap()->builtins_constants_table()); +#endif + + uint32_t* maybe_key = map_.Find(object); + if (maybe_key == nullptr) { + uint32_t index = map_.size(); + map_.Set(object, index); + return index; + } else { + return *maybe_key; + } +} + +void BuiltinsConstantsTableBuilder::Finalize() { + HandleScope handle_scope(isolate_); + + DCHECK_EQ(isolate_->heap()->empty_fixed_array(), + isolate_->heap()->builtins_constants_table()); + + DCHECK_LT(0, map_.size()); + Handle table = + isolate_->factory()->NewFixedArray(map_.size(), TENURED); + + ConstantsMap::IteratableScope it_scope(&map_); + for (auto it = it_scope.begin(); it != it_scope.end(); ++it) { + uint32_t index = *it.entry(); + table->set(index, it.key()); + } + +#ifdef DEBUG + for (int i = 0; i < map_.size(); i++) { + DCHECK(table->get(i)->IsHeapObject()); + DCHECK_NE(isolate_->heap()->undefined_value(), table->get(i)); + } +#endif + + isolate_->heap()->SetBuiltinsConstantsTable(*table); +} + +} // namespace internal +} // namespace v8 diff --git a/src/builtins/constants-table-builder.h b/src/builtins/constants-table-builder.h new file mode 100644 index 0000000000..d251d5849b --- /dev/null +++ b/src/builtins/constants-table-builder.h @@ -0,0 +1,48 @@ +// 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_BUILTINS_CONSTANTS_TABLE_BUILDER_H_ +#define V8_BUILTINS_CONSTANTS_TABLE_BUILDER_H_ + +#include "src/allocation.h" +#include "src/base/macros.h" +#include "src/handles.h" +#include "src/identity-map.h" + +namespace v8 { +namespace internal { + +class Isolate; +class Object; + +// Utility class to build the builtins constants table and store it on the root +// list. The constants table contains constants used by builtins, and is there +// to avoid directly embedding them into code objects, which would not be +// possible for off-heap (and thus immutable) code objects. +class BuiltinsConstantsTableBuilder final { + public: + explicit BuiltinsConstantsTableBuilder(Isolate* isolate); + + // Returns the index within the builtins constants list for the given object, + // possibly adding the object to the cache. Objects are deduplicated. + uint32_t AddObject(Handle object); + + // Should be called after all affected code (e.g. builtins and bytecode + // handlers) has been generated. + void Finalize(); + + private: + Isolate* isolate_; + + // Maps objects to corresponding indices within the constants list. + typedef IdentityMap ConstantsMap; + ConstantsMap map_; + + DISALLOW_COPY_AND_ASSIGN(BuiltinsConstantsTableBuilder) +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_BUILTINS_CONSTANTS_TABLE_BUILDER_H_ diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc index 279355d338..19a50d761d 100644 --- a/src/code-stub-assembler.cc +++ b/src/code-stub-assembler.cc @@ -1,7 +1,10 @@ // Copyright 2016 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. + #include "src/code-stub-assembler.h" + +#include "src/builtins/constants-table-builder.h" #include "src/code-factory.h" #include "src/frames-inl.h" #include "src/frames.h" @@ -7302,6 +7305,23 @@ void CodeStubAssembler::TryGetOwnProperty( } } +#ifdef V8_EMBEDDED_BUILTINS +TNode CodeStubAssembler::LookupConstantCodeTarget(Handle code) { + DCHECK(isolate()->serializer_enabled()); + // The builtins constants table is loaded through the root register on all + // supported platforms. This is checked by the + // VerifyBuiltinsIsolateIndependence cctest, which disallows embedded objects + // in isolate-independent builtins. + BuiltinsConstantsTableBuilder* builder = + isolate()->builtins_constants_table_builder(); + uint32_t index = builder->AddObject(code); + DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant( + Heap::kBuiltinsConstantsTableRootIndex)); + TNode cache = BuiltinsConstantsTableConstant(); + return CAST(LoadFixedArrayElement(cache, index)); +} +#endif // V8_EMBEDDED_BUILTINS + void CodeStubAssembler::TryLookupElement(Node* object, Node* map, Node* instance_type, Node* intptr_index, Label* if_found, diff --git a/src/code-stub-assembler.h b/src/code-stub-assembler.h index d0d0e2efa7..e338d82b29 100644 --- a/src/code-stub-assembler.h +++ b/src/code-stub-assembler.h @@ -22,48 +22,49 @@ class StubCache; enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol }; -#define HEAP_CONSTANT_LIST(V) \ - V(AccessorInfoMap, accessor_info_map, AccessorInfoMap) \ - V(AccessorPairMap, accessor_pair_map, AccessorPairMap) \ - V(AllocationSiteMap, allocation_site_map, AllocationSiteMap) \ - V(BooleanMap, boolean_map, BooleanMap) \ - V(CodeMap, code_map, CodeMap) \ - V(EmptyPropertyDictionary, empty_property_dictionary, \ - EmptyPropertyDictionary) \ - V(EmptyFixedArray, empty_fixed_array, EmptyFixedArray) \ - V(EmptySlowElementDictionary, empty_slow_element_dictionary, \ - EmptySlowElementDictionary) \ - V(empty_string, empty_string, EmptyString) \ - V(EmptyWeakCell, empty_weak_cell, EmptyWeakCell) \ - V(FalseValue, false_value, False) \ - V(FeedbackVectorMap, feedback_vector_map, FeedbackVectorMap) \ - V(FixedArrayMap, fixed_array_map, FixedArrayMap) \ - V(FixedCOWArrayMap, fixed_cow_array_map, FixedCOWArrayMap) \ - V(FixedDoubleArrayMap, fixed_double_array_map, FixedDoubleArrayMap) \ - V(FunctionTemplateInfoMap, function_template_info_map, \ - FunctionTemplateInfoMap) \ - V(GlobalPropertyCellMap, global_property_cell_map, PropertyCellMap) \ - V(has_instance_symbol, has_instance_symbol, HasInstanceSymbol) \ - V(HeapNumberMap, heap_number_map, HeapNumberMap) \ - V(length_string, length_string, LengthString) \ - V(ManyClosuresCellMap, many_closures_cell_map, ManyClosuresCellMap) \ - V(MetaMap, meta_map, MetaMap) \ - V(MinusZeroValue, minus_zero_value, MinusZero) \ - V(MutableHeapNumberMap, mutable_heap_number_map, MutableHeapNumberMap) \ - V(NanValue, nan_value, Nan) \ - V(NoClosuresCellMap, no_closures_cell_map, NoClosuresCellMap) \ - V(NullValue, null_value, Null) \ - V(OneClosureCellMap, one_closure_cell_map, OneClosureCellMap) \ - V(prototype_string, prototype_string, PrototypeString) \ - V(SpeciesProtector, species_protector, SpeciesProtector) \ - V(StoreHandler0Map, store_handler0_map, StoreHandler0Map) \ - V(SymbolMap, symbol_map, SymbolMap) \ - V(TheHoleValue, the_hole_value, TheHole) \ - V(TrueValue, true_value, True) \ - V(Tuple2Map, tuple2_map, Tuple2Map) \ - V(Tuple3Map, tuple3_map, Tuple3Map) \ - V(UndefinedValue, undefined_value, Undefined) \ - V(WeakCellMap, weak_cell_map, WeakCellMap) \ +#define HEAP_CONSTANT_LIST(V) \ + V(AccessorInfoMap, accessor_info_map, AccessorInfoMap) \ + V(AccessorPairMap, accessor_pair_map, AccessorPairMap) \ + V(AllocationSiteMap, allocation_site_map, AllocationSiteMap) \ + V(BooleanMap, boolean_map, BooleanMap) \ + V(BuiltinsConstantsTable, builtins_constants_table, BuiltinsConstantsTable) \ + V(CodeMap, code_map, CodeMap) \ + V(EmptyPropertyDictionary, empty_property_dictionary, \ + EmptyPropertyDictionary) \ + V(EmptyFixedArray, empty_fixed_array, EmptyFixedArray) \ + V(EmptySlowElementDictionary, empty_slow_element_dictionary, \ + EmptySlowElementDictionary) \ + V(empty_string, empty_string, EmptyString) \ + V(EmptyWeakCell, empty_weak_cell, EmptyWeakCell) \ + V(FalseValue, false_value, False) \ + V(FeedbackVectorMap, feedback_vector_map, FeedbackVectorMap) \ + V(FixedArrayMap, fixed_array_map, FixedArrayMap) \ + V(FixedCOWArrayMap, fixed_cow_array_map, FixedCOWArrayMap) \ + V(FixedDoubleArrayMap, fixed_double_array_map, FixedDoubleArrayMap) \ + V(FunctionTemplateInfoMap, function_template_info_map, \ + FunctionTemplateInfoMap) \ + V(GlobalPropertyCellMap, global_property_cell_map, PropertyCellMap) \ + V(has_instance_symbol, has_instance_symbol, HasInstanceSymbol) \ + V(HeapNumberMap, heap_number_map, HeapNumberMap) \ + V(length_string, length_string, LengthString) \ + V(ManyClosuresCellMap, many_closures_cell_map, ManyClosuresCellMap) \ + V(MetaMap, meta_map, MetaMap) \ + V(MinusZeroValue, minus_zero_value, MinusZero) \ + V(MutableHeapNumberMap, mutable_heap_number_map, MutableHeapNumberMap) \ + V(NanValue, nan_value, Nan) \ + V(NoClosuresCellMap, no_closures_cell_map, NoClosuresCellMap) \ + V(NullValue, null_value, Null) \ + V(OneClosureCellMap, one_closure_cell_map, OneClosureCellMap) \ + V(prototype_string, prototype_string, PrototypeString) \ + V(SpeciesProtector, species_protector, SpeciesProtector) \ + V(StoreHandler0Map, store_handler0_map, StoreHandler0Map) \ + V(SymbolMap, symbol_map, SymbolMap) \ + V(TheHoleValue, the_hole_value, TheHole) \ + V(TrueValue, true_value, True) \ + V(Tuple2Map, tuple2_map, Tuple2Map) \ + V(Tuple3Map, tuple3_map, Tuple3Map) \ + V(UndefinedValue, undefined_value, Undefined) \ + V(WeakCellMap, weak_cell_map, WeakCellMap) \ V(SharedFunctionInfoMap, shared_function_info_map, SharedFunctionInfoMap) // Returned from IteratorBuiltinsAssembler::GetIterator(). Struct is declared @@ -1597,6 +1598,90 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { Label* if_not_found, Label* if_bailout, GetOwnPropertyMode mode); +#ifdef V8_EMBEDDED_BUILTINS +#if V8_TARGET_ARCH_IA32 +#error "ia32 does not yet support embedded builtins" +#endif + + // Off-heap builtins cannot embed constants within the code object itself, + // and thus need to load them from the root list. + bool ShouldLoadConstantsFromRootList() const { + return (isolate()->serializer_enabled() && + isolate()->builtins_constants_table_builder() != nullptr); + } + + TNode LookupConstantCodeTarget(Handle code); + + template + Node* CallStub(Callable const& callable, Node* context, TArgs... args) { + if (ShouldLoadConstantsFromRootList()) { + TNode target = LookupConstantCodeTarget(callable.code()); + return compiler::CodeAssembler::CallStub(callable.descriptor(), target, + context, args...); + } else { + return compiler::CodeAssembler::CallStub(callable, context, args...); + } + } + + template + Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target, + Node* context, TArgs... args) { + // Just a forwarding definition, required due to the other overload above. + return compiler::CodeAssembler::CallStub(descriptor, target, context, + args...); + } + + template + Node* TailCallStub(Callable const& callable, Node* context, TArgs... args) { + if (ShouldLoadConstantsFromRootList()) { + TNode target = LookupConstantCodeTarget(callable.code()); + return compiler::CodeAssembler::TailCallStub(callable.descriptor(), + target, context, args...); + } else { + return compiler::CodeAssembler::TailCallStub(callable, context, args...); + } + } + + template + Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target, + Node* context, TArgs... args) { + // Just a forwarding definition, required due to the other overload above. + return compiler::CodeAssembler::TailCallStub(descriptor, target, context, + args...); + } + + template + TNode CallRuntime(Runtime::FunctionId function, + SloppyTNode context, TArgs... args) { + if (ShouldLoadConstantsFromRootList()) { + auto function_info = Runtime::FunctionForId(function); + Handle code = + CodeFactory::RuntimeCEntry(isolate(), function_info->result_size); + TNode target = LookupConstantCodeTarget(code); + return compiler::CodeAssembler::CallRuntime(function, target, context, + args...); + } else { + return compiler::CodeAssembler::CallRuntime(function, context, args...); + } + } + + template + TNode TailCallRuntime(Runtime::FunctionId function, + SloppyTNode context, TArgs... args) { + if (ShouldLoadConstantsFromRootList()) { + auto function_info = Runtime::FunctionForId(function); + Handle code = + CodeFactory::RuntimeCEntry(isolate(), function_info->result_size); + TNode target = LookupConstantCodeTarget(code); + return compiler::CodeAssembler::TailCallRuntime(function, target, context, + args...); + } else { + return compiler::CodeAssembler::TailCallRuntime(function, context, + args...); + } + } +#endif // V8_EMBEDDED_BUILTINS + Node* GetProperty(Node* context, Node* receiver, Handle name) { return GetProperty(context, receiver, HeapConstant(name)); } diff --git a/src/compiler/code-assembler.cc b/src/compiler/code-assembler.cc index 499c603471..e5da049911 100644 --- a/src/compiler/code-assembler.cc +++ b/src/compiler/code-assembler.cc @@ -1011,6 +1011,37 @@ TNode CodeAssembler::CallRuntimeImpl(Runtime::FunctionId function, REPEAT_1_TO_7(INSTANTIATE, SloppyTNode) #undef INSTANTIATE +#ifdef V8_EMBEDDED_BUILTINS +template +TNode CodeAssembler::CallRuntimeImpl(Runtime::FunctionId function, + TNode target, + SloppyTNode context, + TArgs... args) { + int argc = static_cast(sizeof...(args)); + auto call_descriptor = Linkage::GetRuntimeCallDescriptor( + zone(), function, argc, Operator::kNoProperties, + CallDescriptor::kNoFlags); + + Node* ref = ExternalConstant(ExternalReference(function, isolate())); + Node* arity = Int32Constant(argc); + + Node* nodes[] = {target, args..., ref, arity, context}; + + CallPrologue(); + Node* return_value = + raw_assembler()->CallN(call_descriptor, arraysize(nodes), nodes); + CallEpilogue(); + return UncheckedCast(return_value); +} + +// Instantiate CallRuntime() for argument counts used by CSA-generated code +#define INSTANTIATE(...) \ + template V8_EXPORT_PRIVATE TNode CodeAssembler::CallRuntimeImpl( \ + Runtime::FunctionId, TNode, __VA_ARGS__); +REPEAT_1_TO_7(INSTANTIATE, SloppyTNode) +#undef INSTANTIATE +#endif // V8_EMBEDDED_BUILTINS + template TNode CodeAssembler::TailCallRuntimeImpl(Runtime::FunctionId function, SloppyTNode context, @@ -1039,6 +1070,34 @@ TNode CodeAssembler::TailCallRuntimeImpl(Runtime::FunctionId function, REPEAT_1_TO_7(INSTANTIATE, SloppyTNode) #undef INSTANTIATE +#ifdef V8_EMBEDDED_BUILTINS +template +TNode CodeAssembler::TailCallRuntimeImpl(Runtime::FunctionId function, + TNode target, + SloppyTNode context, + TArgs... args) { + int argc = static_cast(sizeof...(args)); + auto call_descriptor = Linkage::GetRuntimeCallDescriptor( + zone(), function, argc, Operator::kNoProperties, + CallDescriptor::kNoFlags); + + Node* ref = ExternalConstant(ExternalReference(function, isolate())); + Node* arity = Int32Constant(argc); + + Node* nodes[] = {target, args..., ref, arity, context}; + + return UncheckedCast( + raw_assembler()->TailCallN(call_descriptor, arraysize(nodes), nodes)); +} + +// Instantiate TailCallRuntime() for argument counts used by CSA-generated code +#define INSTANTIATE(...) \ + template V8_EXPORT_PRIVATE TNode CodeAssembler::TailCallRuntimeImpl( \ + Runtime::FunctionId, TNode, __VA_ARGS__); +REPEAT_1_TO_7(INSTANTIATE, SloppyTNode) +#undef INSTANTIATE +#endif // V8_EMBEDDED_BUILTINS + template Node* CodeAssembler::CallStubR(const CallInterfaceDescriptor& descriptor, size_t result_size, Node* target, Node* context, diff --git a/src/compiler/code-assembler.h b/src/compiler/code-assembler.h index 9812798d48..3abeec03e3 100644 --- a/src/compiler/code-assembler.h +++ b/src/compiler/code-assembler.h @@ -913,6 +913,18 @@ class V8_EXPORT_PRIVATE CodeAssembler { return CallRuntimeImpl(function, context, base::implicit_cast>(args)...); } +#ifdef V8_EMBEDDED_BUILTINS + template + TNode CallRuntimeImpl(Runtime::FunctionId function, + TNode target, SloppyTNode context, + TArgs... args); + template + TNode CallRuntime(Runtime::FunctionId function, TNode target, + SloppyTNode context, TArgs... args) { + return CallRuntimeImpl(function, target, context, + base::implicit_cast>(args)...); + } +#endif template TNode TailCallRuntimeImpl(Runtime::FunctionId function, @@ -923,6 +935,20 @@ class V8_EXPORT_PRIVATE CodeAssembler { return TailCallRuntimeImpl( function, context, base::implicit_cast>(args)...); } +#ifdef V8_EMBEDDED_BUILTINS + template + TNode TailCallRuntimeImpl(Runtime::FunctionId function, + TNode target, + SloppyTNode context, TArgs... args); + template + TNode TailCallRuntime(Runtime::FunctionId function, + TNode target, SloppyTNode context, + TArgs... args) { + return TailCallRuntimeImpl( + function, target, context, + base::implicit_cast>(args)...); + } +#endif // // If context passed to CallStub is nullptr, it won't be passed to the stub. diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc index 02bf849b16..f3e947dd1c 100644 --- a/src/compiler/instruction-selector.cc +++ b/src/compiler/instruction-selector.cc @@ -766,12 +766,22 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, bool call_use_fixed_target_reg = (flags & kCallFixedTargetRegister) != 0; switch (buffer->descriptor->kind()) { case CallDescriptor::kCallCodeObject: + // TODO(jgruber, v8:7449): The below is a hack to support tail-calls from + // JS-linkage callers with a register code target. The problem is that the + // code target register may be clobbered before the final jmp by + // AssemblePopArgumentsAdaptorFrame. As a more permanent fix we could + // entirely remove support for tail-calls from JS-linkage callers. buffer->instruction_args.push_back( (call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant) ? g.UseImmediate(callee) : call_use_fixed_target_reg ? g.UseFixed(callee, kJavaScriptCallCodeStartRegister) +#ifdef V8_EMBEDDED_BUILTINS + : is_tail_call ? g.UseUniqueRegister(callee) + : g.UseRegister(callee)); +#else : g.UseRegister(callee)); +#endif break; case CallDescriptor::kCallAddress: buffer->instruction_args.push_back( diff --git a/src/heap/heap.cc b/src/heap/heap.cc index 02170a8677..4ce6df5564 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -6518,6 +6518,10 @@ void Heap::SetDeserializeLazyHandlerExtraWide(Code* code) { set_deserialize_lazy_handler_extra_wide(code); } +void Heap::SetBuiltinsConstantsTable(FixedArray* cache) { + set_builtins_constants_table(cache); +} + size_t Heap::NumberOfTrackedHeapObjectTypes() { return ObjectStats::OBJECT_STATS_COUNT; } diff --git a/src/heap/heap.h b/src/heap/heap.h index 18172d6f4f..533fc12bfa 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -250,6 +250,8 @@ using v8::MemoryPressureLevel; /* slots refer to the code with the reference to the weak object. */ \ V(ArrayList, weak_new_space_object_to_code_list, \ WeakNewSpaceObjectToCodeList) \ + /* Indirection lists for isolate-independent builtins */ \ + V(FixedArray, builtins_constants_table, BuiltinsConstantsTable) \ /* Feedback vectors that we need for code coverage or type profile */ \ V(Object, feedback_vectors_for_profiling_tools, \ FeedbackVectorsForProfilingTools) \ @@ -1121,6 +1123,8 @@ class Heap { void SetDeserializeLazyHandlerWide(Code* code); void SetDeserializeLazyHandlerExtraWide(Code* code); + void SetBuiltinsConstantsTable(FixedArray* cache); + // =========================================================================== // Inline allocation. ======================================================== // =========================================================================== diff --git a/src/heap/setup-heap-internal.cc b/src/heap/setup-heap-internal.cc index 906ff90a21..a3e50e8b24 100644 --- a/src/heap/setup-heap-internal.cc +++ b/src/heap/setup-heap-internal.cc @@ -659,6 +659,9 @@ void Heap::CreateInitialObjects() { set_deserialize_lazy_handler_wide(Smi::kZero); set_deserialize_lazy_handler_extra_wide(Smi::kZero); + // Initialize builtins constants table. + set_builtins_constants_table(empty_fixed_array()); + // Initialize context slot cache. isolate_->context_slot_cache()->Clear(); diff --git a/src/identity-map.cc b/src/identity-map.cc index b652d6a6db..8c176298ed 100644 --- a/src/identity-map.cc +++ b/src/identity-map.cc @@ -194,6 +194,14 @@ void* IdentityMapBase::DeleteEntry(Object* key) { return DeleteIndex(index); } +Object* IdentityMapBase::KeyAtIndex(int index) const { + DCHECK_LE(0, index); + DCHECK_LT(index, capacity_); + DCHECK_NE(keys_[index], heap_->not_mapped_symbol()); + CHECK(is_iterable()); // Must be iterable to access by index; + return keys_[index]; +} + IdentityMapBase::RawEntry IdentityMapBase::EntryAtIndex(int index) const { DCHECK_LE(0, index); DCHECK_LT(index, capacity_); diff --git a/src/identity-map.h b/src/identity-map.h index cd198e1cb5..4e69d3198a 100644 --- a/src/identity-map.h +++ b/src/identity-map.h @@ -46,6 +46,8 @@ class IdentityMapBase { void* DeleteEntry(Object* key); void Clear(); + Object* KeyAtIndex(int index) const; + V8_EXPORT_PRIVATE RawEntry EntryAtIndex(int index) const; V8_EXPORT_PRIVATE int NextIndex(int index) const; @@ -126,8 +128,13 @@ class IdentityMap : public IdentityMapBase { return *this; } - V* operator*() { return reinterpret_cast(map_->EntryAtIndex(index_)); } - V* operator->() { return reinterpret_cast(map_->EntryAtIndex(index_)); } + Object* key() const { return map_->KeyAtIndex(index_); } + V* entry() const { + return reinterpret_cast(map_->EntryAtIndex(index_)); + } + + V* operator*() { return entry(); } + V* operator->() { return entry(); } bool operator!=(const Iterator& other) { return index_ != other.index_; } private: diff --git a/src/isolate.cc b/src/isolate.cc index 1f23770321..34124c99d1 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -20,6 +20,7 @@ #include "src/base/utils/random-number-generator.h" #include "src/basic-block-profiler.h" #include "src/bootstrapper.h" +#include "src/builtins/constants-table-builder.h" #include "src/callable.h" #include "src/cancelable-task.h" #include "src/code-stubs.h" @@ -3041,6 +3042,9 @@ bool Isolate::Init(StartupDeserializer* des) { if (create_heap_objects) { // Terminate the partial snapshot cache so we can iterate. partial_snapshot_cache_.push_back(heap_.undefined_value()); +#ifdef V8_EMBEDDED_BUILTINS + builtins_constants_table_builder_ = new BuiltinsConstantsTableBuilder(this); +#endif } InitializeThreadLocal(); @@ -3073,6 +3077,14 @@ bool Isolate::Init(StartupDeserializer* des) { store_stub_cache_->Initialize(); setup_delegate_->SetupInterpreter(interpreter_); +#ifdef V8_EMBEDDED_BUILTINS + if (create_heap_objects) { + builtins_constants_table_builder_->Finalize(); + delete builtins_constants_table_builder_; + builtins_constants_table_builder_ = nullptr; + } +#endif // V8_EMBEDDED_BUILTINS + heap_.NotifyDeserializationComplete(); } delete setup_delegate_; diff --git a/src/isolate.h b/src/isolate.h index 72e3ea9e4a..3fd3e567ac 100644 --- a/src/isolate.h +++ b/src/isolate.h @@ -48,6 +48,7 @@ class AddressToIndexHashMap; class AstStringConstants; class BasicBlockProfiler; class Bootstrapper; +class BuiltinsConstantsTableBuilder; class CallInterfaceDescriptorData; class CancelableTaskManager; class CodeEventDispatcher; @@ -1244,6 +1245,12 @@ class Isolate { off_heap_code_.emplace_back(stream); } +#ifdef V8_EMBEDDED_BUILTINS + BuiltinsConstantsTableBuilder* builtins_constants_table_builder() const { + return builtins_constants_table_builder_; + } +#endif + void set_array_buffer_allocator(v8::ArrayBuffer::Allocator* allocator) { array_buffer_allocator_ = allocator; } @@ -1617,6 +1624,12 @@ class Isolate { // implemented. std::vector off_heap_code_; +#ifdef V8_EMBEDDED_BUILTINS + // Used during builtins compilation to build the builtins constants table, + // which is stored on the root list prior to serialization. + BuiltinsConstantsTableBuilder* builtins_constants_table_builder_ = nullptr; +#endif + v8::ArrayBuffer::Allocator* array_buffer_allocator_; FutexWaitListNode futex_wait_list_node_; diff --git a/test/cctest/test-isolate-independent-builtins.cc b/test/cctest/test-isolate-independent-builtins.cc index 37dd95d53d..fd2ca2d46b 100644 --- a/test/cctest/test-isolate-independent-builtins.cc +++ b/test/cctest/test-isolate-independent-builtins.cc @@ -19,6 +19,7 @@ namespace v8 { namespace internal { namespace test_isolate_independent_builtins { +#ifdef V8_EMBEDDED_BUILTINS TEST(VerifyBuiltinsIsolateIndependence) { Isolate* isolate = CcTest::i_isolate(); HandleScope handle_scope(isolate); @@ -81,6 +82,7 @@ TEST(VerifyBuiltinsIsolateIndependence) { CHECK(!found_mismatch); } +#endif // V8_EMBEDDED_BUILTINS // V8_CC_MSVC is true for both MSVC and clang on windows. clang can handle // __asm__-style inline assembly but MSVC cannot, and thus we need a more