[heap] Make trampoline CodeDataContainers immutable and deduplicate them
Moves all trampoline CodeDataContainers to read-only space, making them immutable. Containers with no 'kind specific flags' set or 'promise rejection' flag are deduplicated by replacing them with the new canonical CodeDataContainers roots. This saves around 36KB from the snapshot. RO_SPACE NEW_SPACE OLD_SPACE CODE_SPACE MAP_SPACE LO_SPACE old 32048 0 225944 149280 20240 0 new 32120 0 189344 149280 20240 0 Bug: v8:7464 Change-Id: Iedd538a86311ef501cd88c90ec75e1308195762f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1601257 Commit-Queue: Maciej Goszczycki <goszczycki@google.com> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Dan Elphick <delphick@chromium.org> Cr-Commit-Position: refs/heads/master@{#61378}
This commit is contained in:
parent
8090e78ee9
commit
652e32f9f9
@ -291,8 +291,8 @@ constexpr int OffHeapTrampolineGenerator::kBufferSize;
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
Handle<Code> Builtins::GenerateOffHeapTrampolineFor(Isolate* isolate,
|
||||
Address off_heap_entry) {
|
||||
Handle<Code> Builtins::GenerateOffHeapTrampolineFor(
|
||||
Isolate* isolate, Address off_heap_entry, int32_t kind_specfic_flags) {
|
||||
DCHECK_NOT_NULL(isolate->embedded_blob());
|
||||
DCHECK_NE(0, isolate->embedded_blob_size());
|
||||
|
||||
@ -301,6 +301,7 @@ Handle<Code> Builtins::GenerateOffHeapTrampolineFor(Isolate* isolate,
|
||||
|
||||
return Factory::CodeBuilder(isolate, desc, Code::BUILTIN)
|
||||
.set_self_reference(generator.CodeObject())
|
||||
.set_read_only_data_container(kind_specfic_flags)
|
||||
.Build();
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,8 @@ class Builtins {
|
||||
// The result should not be used directly, but only from the related Factory
|
||||
// function.
|
||||
static Handle<Code> GenerateOffHeapTrampolineFor(Isolate* isolate,
|
||||
Address off_heap_entry);
|
||||
Address off_heap_entry,
|
||||
int32_t kind_specific_flags);
|
||||
|
||||
// Generate the RelocInfo ByteArray that would be generated for an offheap
|
||||
// trampoline.
|
||||
|
@ -86,7 +86,29 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal(
|
||||
// Allocate objects needed for code initialization.
|
||||
Handle<ByteArray> reloc_info =
|
||||
factory->NewByteArray(code_desc_.reloc_size, AllocationType::kOld);
|
||||
Handle<CodeDataContainer> data_container = factory->NewCodeDataContainer(0);
|
||||
Handle<CodeDataContainer> data_container;
|
||||
|
||||
// Use a canonical off-heap trampoline CodeDataContainer if possible.
|
||||
const int32_t promise_rejection_flag =
|
||||
Code::IsPromiseRejectionField::encode(true);
|
||||
if (read_only_data_container_ &&
|
||||
(kind_specific_flags_ == 0 ||
|
||||
kind_specific_flags_ == promise_rejection_flag)) {
|
||||
const ReadOnlyRoots roots(isolate_);
|
||||
const auto canonical_code_data_container =
|
||||
kind_specific_flags_ == 0
|
||||
? roots.trampoline_trivial_code_data_container_handle()
|
||||
: roots.trampoline_promise_rejection_code_data_container_handle();
|
||||
DCHECK_EQ(canonical_code_data_container->kind_specific_flags(),
|
||||
kind_specific_flags_);
|
||||
data_container = canonical_code_data_container;
|
||||
} else {
|
||||
data_container = factory->NewCodeDataContainer(
|
||||
0, read_only_data_container_ ? AllocationType::kReadOnly
|
||||
: AllocationType::kOld);
|
||||
data_container->set_kind_specific_flags(kind_specific_flags_);
|
||||
}
|
||||
|
||||
Handle<Code> code;
|
||||
{
|
||||
int object_size = ComputeCodeObjectSize(code_desc_);
|
||||
@ -2684,10 +2706,10 @@ Handle<JSObject> Factory::NewExternal(void* value) {
|
||||
return external;
|
||||
}
|
||||
|
||||
Handle<CodeDataContainer> Factory::NewCodeDataContainer(int flags) {
|
||||
Handle<CodeDataContainer> Factory::NewCodeDataContainer(
|
||||
int flags, AllocationType allocation) {
|
||||
Handle<CodeDataContainer> data_container(
|
||||
CodeDataContainer::cast(
|
||||
New(code_data_container_map(), AllocationType::kOld)),
|
||||
CodeDataContainer::cast(New(code_data_container_map(), allocation)),
|
||||
isolate());
|
||||
data_container->set_next_code_link(*undefined_value(), SKIP_WRITE_BARRIER);
|
||||
data_container->set_kind_specific_flags(flags);
|
||||
@ -2701,12 +2723,14 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
|
||||
CHECK_NE(0, isolate()->embedded_blob_size());
|
||||
CHECK(Builtins::IsIsolateIndependentBuiltin(*code));
|
||||
|
||||
Handle<Code> result =
|
||||
Builtins::GenerateOffHeapTrampolineFor(isolate(), off_heap_entry);
|
||||
Handle<Code> result = Builtins::GenerateOffHeapTrampolineFor(
|
||||
isolate(), off_heap_entry,
|
||||
code->code_data_container()->kind_specific_flags());
|
||||
// The CodeDataContainer should not be modified beyond this point since it's
|
||||
// now possibly canonicalized.
|
||||
|
||||
// The trampoline code object must inherit specific flags from the original
|
||||
// builtin (e.g. the safepoint-table offset). We set them manually here.
|
||||
|
||||
{
|
||||
MemoryChunk* chunk = MemoryChunk::FromHeapObject(*result);
|
||||
CodePageMemoryModificationScope code_allocation(chunk);
|
||||
@ -2714,8 +2738,6 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
|
||||
const bool set_is_off_heap_trampoline = true;
|
||||
const int stack_slots =
|
||||
code->has_safepoint_info() ? code->stack_slots() : 0;
|
||||
result->code_data_container()->set_kind_specific_flags(
|
||||
code->code_data_container()->kind_specific_flags());
|
||||
result->initialize_flags(code->kind(), code->has_unwinding_info(),
|
||||
code->is_turbofanned(), stack_slots,
|
||||
set_is_off_heap_trampoline);
|
||||
@ -2745,8 +2767,8 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
|
||||
}
|
||||
|
||||
Handle<Code> Factory::CopyCode(Handle<Code> code) {
|
||||
Handle<CodeDataContainer> data_container =
|
||||
NewCodeDataContainer(code->code_data_container()->kind_specific_flags());
|
||||
Handle<CodeDataContainer> data_container = NewCodeDataContainer(
|
||||
code->code_data_container()->kind_specific_flags(), AllocationType::kOld);
|
||||
|
||||
Heap* heap = isolate()->heap();
|
||||
Handle<Code> new_code;
|
||||
|
@ -793,7 +793,8 @@ class V8_EXPORT_PRIVATE Factory {
|
||||
Handle<JSObject> NewExternal(void* value);
|
||||
|
||||
// Creates a new CodeDataContainer for a Code object.
|
||||
Handle<CodeDataContainer> NewCodeDataContainer(int flags);
|
||||
Handle<CodeDataContainer> NewCodeDataContainer(int flags,
|
||||
AllocationType allocation);
|
||||
|
||||
// Allocates a new code object and initializes it as the trampoline to the
|
||||
// given off-heap entry point.
|
||||
@ -958,29 +959,44 @@ class V8_EXPORT_PRIVATE Factory {
|
||||
self_reference_ = self_reference;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CodeBuilder& set_builtin_index(int32_t builtin_index) {
|
||||
builtin_index_ = builtin_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CodeBuilder& set_source_position_table(Handle<ByteArray> table) {
|
||||
DCHECK(!table.is_null());
|
||||
source_position_table_ = table;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CodeBuilder& set_deoptimization_data(
|
||||
Handle<DeoptimizationData> deopt_data) {
|
||||
DCHECK(!deopt_data.is_null());
|
||||
deoptimization_data_ = deopt_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CodeBuilder& set_immovable() {
|
||||
is_movable_ = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CodeBuilder& set_is_turbofanned() {
|
||||
is_turbofanned_ = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Indicates the CodeDataContainer should be allocated in read-only space.
|
||||
// As an optimization, if the kind-specific flags match that of a canonical
|
||||
// container, it will be used instead.
|
||||
CodeBuilder& set_read_only_data_container(int32_t flags) {
|
||||
read_only_data_container_ = true;
|
||||
kind_specific_flags_ = flags;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CodeBuilder& set_stack_slots(int stack_slots) {
|
||||
stack_slots_ = stack_slots;
|
||||
return *this;
|
||||
@ -995,9 +1011,11 @@ class V8_EXPORT_PRIVATE Factory {
|
||||
|
||||
MaybeHandle<Object> self_reference_;
|
||||
int32_t builtin_index_ = Builtins::kNoBuiltinId;
|
||||
int32_t kind_specific_flags_ = 0;
|
||||
Handle<ByteArray> source_position_table_;
|
||||
Handle<DeoptimizationData> deoptimization_data_ =
|
||||
DeoptimizationData::Empty(isolate_);
|
||||
bool read_only_data_container_ = false;
|
||||
bool is_movable_ = true;
|
||||
bool is_turbofanned_ = false;
|
||||
int stack_slots_ = 0;
|
||||
|
@ -939,9 +939,19 @@ void Heap::CreateInitialObjects() {
|
||||
|
||||
set_noscript_shared_function_infos(roots.empty_weak_array_list());
|
||||
|
||||
/* Canonical off-heap trampoline data */
|
||||
set_off_heap_trampoline_relocation_info(
|
||||
*Builtins::GenerateOffHeapTrampolineRelocInfo(isolate_));
|
||||
|
||||
set_trampoline_trivial_code_data_container(
|
||||
*isolate()->factory()->NewCodeDataContainer(0,
|
||||
AllocationType::kReadOnly));
|
||||
|
||||
set_trampoline_promise_rejection_code_data_container(
|
||||
*isolate()->factory()->NewCodeDataContainer(
|
||||
Code::IsPromiseRejectionField::encode(true),
|
||||
AllocationType::kReadOnly));
|
||||
|
||||
// Evaluate the hash values which will then be cached in the strings.
|
||||
isolate()->factory()->zero_string()->Hash();
|
||||
isolate()->factory()->one_string()->Hash();
|
||||
|
@ -216,9 +216,13 @@ class Symbol;
|
||||
V(HeapNumber, minus_infinity_value, MinusInfinityValue) \
|
||||
/* Marker for self-references during code-generation */ \
|
||||
V(HeapObject, self_reference_marker, SelfReferenceMarker) \
|
||||
/* Canonical trampoline RelocInfo */ \
|
||||
/* Canonical off-heap trampoline data */ \
|
||||
V(ByteArray, off_heap_trampoline_relocation_info, \
|
||||
OffHeapTrampolineRelocationInfo) \
|
||||
V(CodeDataContainer, trampoline_trivial_code_data_container, \
|
||||
TrampolineTrivialCodeDataContainer) \
|
||||
V(CodeDataContainer, trampoline_promise_rejection_code_data_container, \
|
||||
TrampolinePromiseRejectionCodeDataContainer) \
|
||||
/* Hash seed */ \
|
||||
V(ByteArray, hash_seed, HashSeed)
|
||||
|
||||
|
@ -306,49 +306,49 @@ KNOWN_MAPS = {
|
||||
("read_only_space", 0x026e9): (98, "EnumCacheMap"),
|
||||
("read_only_space", 0x02789): (115, "ArrayBoilerplateDescriptionMap"),
|
||||
("read_only_space", 0x02ad9): (101, "InterceptorInfoMap"),
|
||||
("read_only_space", 0x05111): (89, "AccessCheckInfoMap"),
|
||||
("read_only_space", 0x05161): (90, "AccessorInfoMap"),
|
||||
("read_only_space", 0x051b1): (91, "AccessorPairMap"),
|
||||
("read_only_space", 0x05201): (92, "AliasedArgumentsEntryMap"),
|
||||
("read_only_space", 0x05251): (93, "AllocationMementoMap"),
|
||||
("read_only_space", 0x052a1): (94, "AsmWasmDataMap"),
|
||||
("read_only_space", 0x052f1): (95, "AsyncGeneratorRequestMap"),
|
||||
("read_only_space", 0x05341): (96, "ClassPositionsMap"),
|
||||
("read_only_space", 0x05391): (97, "DebugInfoMap"),
|
||||
("read_only_space", 0x053e1): (99, "FunctionTemplateInfoMap"),
|
||||
("read_only_space", 0x05431): (100, "FunctionTemplateRareDataMap"),
|
||||
("read_only_space", 0x05481): (102, "InterpreterDataMap"),
|
||||
("read_only_space", 0x054d1): (103, "ModuleInfoEntryMap"),
|
||||
("read_only_space", 0x05521): (104, "ModuleMap"),
|
||||
("read_only_space", 0x05571): (105, "ObjectTemplateInfoMap"),
|
||||
("read_only_space", 0x055c1): (106, "PromiseCapabilityMap"),
|
||||
("read_only_space", 0x05611): (107, "PromiseReactionMap"),
|
||||
("read_only_space", 0x05661): (108, "PrototypeInfoMap"),
|
||||
("read_only_space", 0x056b1): (109, "ScriptMap"),
|
||||
("read_only_space", 0x05701): (110, "SourcePositionTableWithFrameCacheMap"),
|
||||
("read_only_space", 0x05751): (111, "StackFrameInfoMap"),
|
||||
("read_only_space", 0x057a1): (112, "StackTraceFrameMap"),
|
||||
("read_only_space", 0x057f1): (113, "Tuple2Map"),
|
||||
("read_only_space", 0x05841): (114, "Tuple3Map"),
|
||||
("read_only_space", 0x05891): (116, "WasmCapiFunctionDataMap"),
|
||||
("read_only_space", 0x058e1): (117, "WasmDebugInfoMap"),
|
||||
("read_only_space", 0x05931): (118, "WasmExceptionTagMap"),
|
||||
("read_only_space", 0x05981): (119, "WasmExportedFunctionDataMap"),
|
||||
("read_only_space", 0x059d1): (120, "CallableTaskMap"),
|
||||
("read_only_space", 0x05a21): (121, "CallbackTaskMap"),
|
||||
("read_only_space", 0x05a71): (122, "PromiseFulfillReactionJobTaskMap"),
|
||||
("read_only_space", 0x05ac1): (123, "PromiseRejectReactionJobTaskMap"),
|
||||
("read_only_space", 0x05b11): (124, "PromiseResolveThenableJobTaskMap"),
|
||||
("read_only_space", 0x05b61): (125, "FinalizationGroupCleanupJobTaskMap"),
|
||||
("read_only_space", 0x05bb1): (126, "AllocationSiteWithWeakNextMap"),
|
||||
("read_only_space", 0x05c01): (126, "AllocationSiteWithoutWeakNextMap"),
|
||||
("read_only_space", 0x05c51): (161, "LoadHandler1Map"),
|
||||
("read_only_space", 0x05ca1): (161, "LoadHandler2Map"),
|
||||
("read_only_space", 0x05cf1): (161, "LoadHandler3Map"),
|
||||
("read_only_space", 0x05d41): (169, "StoreHandler0Map"),
|
||||
("read_only_space", 0x05d91): (169, "StoreHandler1Map"),
|
||||
("read_only_space", 0x05de1): (169, "StoreHandler2Map"),
|
||||
("read_only_space", 0x05e31): (169, "StoreHandler3Map"),
|
||||
("read_only_space", 0x05141): (89, "AccessCheckInfoMap"),
|
||||
("read_only_space", 0x05191): (90, "AccessorInfoMap"),
|
||||
("read_only_space", 0x051e1): (91, "AccessorPairMap"),
|
||||
("read_only_space", 0x05231): (92, "AliasedArgumentsEntryMap"),
|
||||
("read_only_space", 0x05281): (93, "AllocationMementoMap"),
|
||||
("read_only_space", 0x052d1): (94, "AsmWasmDataMap"),
|
||||
("read_only_space", 0x05321): (95, "AsyncGeneratorRequestMap"),
|
||||
("read_only_space", 0x05371): (96, "ClassPositionsMap"),
|
||||
("read_only_space", 0x053c1): (97, "DebugInfoMap"),
|
||||
("read_only_space", 0x05411): (99, "FunctionTemplateInfoMap"),
|
||||
("read_only_space", 0x05461): (100, "FunctionTemplateRareDataMap"),
|
||||
("read_only_space", 0x054b1): (102, "InterpreterDataMap"),
|
||||
("read_only_space", 0x05501): (103, "ModuleInfoEntryMap"),
|
||||
("read_only_space", 0x05551): (104, "ModuleMap"),
|
||||
("read_only_space", 0x055a1): (105, "ObjectTemplateInfoMap"),
|
||||
("read_only_space", 0x055f1): (106, "PromiseCapabilityMap"),
|
||||
("read_only_space", 0x05641): (107, "PromiseReactionMap"),
|
||||
("read_only_space", 0x05691): (108, "PrototypeInfoMap"),
|
||||
("read_only_space", 0x056e1): (109, "ScriptMap"),
|
||||
("read_only_space", 0x05731): (110, "SourcePositionTableWithFrameCacheMap"),
|
||||
("read_only_space", 0x05781): (111, "StackFrameInfoMap"),
|
||||
("read_only_space", 0x057d1): (112, "StackTraceFrameMap"),
|
||||
("read_only_space", 0x05821): (113, "Tuple2Map"),
|
||||
("read_only_space", 0x05871): (114, "Tuple3Map"),
|
||||
("read_only_space", 0x058c1): (116, "WasmCapiFunctionDataMap"),
|
||||
("read_only_space", 0x05911): (117, "WasmDebugInfoMap"),
|
||||
("read_only_space", 0x05961): (118, "WasmExceptionTagMap"),
|
||||
("read_only_space", 0x059b1): (119, "WasmExportedFunctionDataMap"),
|
||||
("read_only_space", 0x05a01): (120, "CallableTaskMap"),
|
||||
("read_only_space", 0x05a51): (121, "CallbackTaskMap"),
|
||||
("read_only_space", 0x05aa1): (122, "PromiseFulfillReactionJobTaskMap"),
|
||||
("read_only_space", 0x05af1): (123, "PromiseRejectReactionJobTaskMap"),
|
||||
("read_only_space", 0x05b41): (124, "PromiseResolveThenableJobTaskMap"),
|
||||
("read_only_space", 0x05b91): (125, "FinalizationGroupCleanupJobTaskMap"),
|
||||
("read_only_space", 0x05be1): (126, "AllocationSiteWithWeakNextMap"),
|
||||
("read_only_space", 0x05c31): (126, "AllocationSiteWithoutWeakNextMap"),
|
||||
("read_only_space", 0x05c81): (161, "LoadHandler1Map"),
|
||||
("read_only_space", 0x05cd1): (161, "LoadHandler2Map"),
|
||||
("read_only_space", 0x05d21): (161, "LoadHandler3Map"),
|
||||
("read_only_space", 0x05d71): (169, "StoreHandler0Map"),
|
||||
("read_only_space", 0x05dc1): (169, "StoreHandler1Map"),
|
||||
("read_only_space", 0x05e11): (169, "StoreHandler2Map"),
|
||||
("read_only_space", 0x05e61): (169, "StoreHandler3Map"),
|
||||
("map_space", 0x00141): (1057, "ExternalMap"),
|
||||
("map_space", 0x00191): (1073, "JSMessageObjectMap"),
|
||||
}
|
||||
@ -404,7 +404,9 @@ KNOWN_OBJECTS = {
|
||||
("read_only_space", 0x02b61): "MinusInfinityValue",
|
||||
("read_only_space", 0x02b71): "SelfReferenceMarker",
|
||||
("read_only_space", 0x02bc9): "OffHeapTrampolineRelocationInfo",
|
||||
("read_only_space", 0x02be1): "HashSeed",
|
||||
("read_only_space", 0x02be1): "TrampolineTrivialCodeDataContainer",
|
||||
("read_only_space", 0x02bf9): "TrampolinePromiseRejectionCodeDataContainer",
|
||||
("read_only_space", 0x02c11): "HashSeed",
|
||||
("old_space", 0x00141): "ArgumentsIteratorAccessor",
|
||||
("old_space", 0x001b1): "ArrayLengthAccessor",
|
||||
("old_space", 0x00221): "BoundFunctionLengthAccessor",
|
||||
|
Loading…
Reference in New Issue
Block a user