[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:
Maciej Goszczycki 2019-05-09 11:43:40 +01:00 committed by Commit Bot
parent 8090e78ee9
commit 652e32f9f9
7 changed files with 118 additions and 60 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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