Commit 1bf6e735 authored by Dan Elphick's avatar Dan Elphick Committed by Commit Bot

[embedded] Share a single RelocInfo between all trampolines

Creates a single RelocInfo to be used by all builtin trampolines and
stores it as a root. All trampolines then substitute this for their
trampoline at generation time with DCHECKs to make sure it is
identical.

Also forces all non-trampoline RelocInfo ByteArrays for builtins to be
generated into RO_SPACE.

On x64, this results in the OLD_SPACE part of the startup snapshot
decreasing in size from 166096 to 131248 (-34848) bytes and RO_SPACE
(in the read-only snapshot) increasing from 31176 to 31248 (+72) bytes.

Bug: v8:8295
Change-Id: I69f4a899b738f2023ed42501c2b9797d34305b06
Reviewed-on: https://chromium-review.googlesource.com/c/1276468
Commit-Queue: Dan Elphick <delphick@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56811}
parent c7a17431
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "src/isolate.h" #include "src/isolate.h"
#include "src/macro-assembler.h" #include "src/macro-assembler.h"
#include "src/objects-inl.h" #include "src/objects-inl.h"
#include "src/objects/fixed-array.h"
#include "src/visitors.h" #include "src/visitors.h"
namespace v8 { namespace v8 {
...@@ -364,6 +365,39 @@ bool Builtins::IsWasmRuntimeStub(int index) { ...@@ -364,6 +365,39 @@ bool Builtins::IsWasmRuntimeStub(int index) {
UNREACHABLE(); UNREACHABLE();
} }
namespace {
class OffHeapTrampolineGenerator {
public:
explicit OffHeapTrampolineGenerator(Isolate* isolate)
: isolate_(isolate),
masm_(isolate, buffer, kBufferSize, CodeObjectRequired::kYes) {}
CodeDesc Generate(Address off_heap_entry) {
// Generate replacement code that simply tail-calls the off-heap code.
DCHECK(!masm_.has_frame());
{
FrameScope scope(&masm_, StackFrame::NONE);
masm_.JumpToInstructionStream(off_heap_entry);
}
CodeDesc desc;
masm_.GetCode(isolate_, &desc);
return desc;
}
Handle<HeapObject> CodeObject() { return masm_.CodeObject(); }
private:
Isolate* isolate_;
// Enough to fit the single jmp.
static constexpr size_t kBufferSize = 256;
byte buffer[kBufferSize];
MacroAssembler masm_;
};
} // namespace
// static // static
Handle<Code> Builtins::GenerateOffHeapTrampolineFor(Isolate* isolate, Handle<Code> Builtins::GenerateOffHeapTrampolineFor(Isolate* isolate,
Address off_heap_entry) { Address off_heap_entry) {
...@@ -371,21 +405,26 @@ Handle<Code> Builtins::GenerateOffHeapTrampolineFor(Isolate* isolate, ...@@ -371,21 +405,26 @@ Handle<Code> Builtins::GenerateOffHeapTrampolineFor(Isolate* isolate,
DCHECK_NOT_NULL(isolate->embedded_blob()); DCHECK_NOT_NULL(isolate->embedded_blob());
DCHECK_NE(0, isolate->embedded_blob_size()); DCHECK_NE(0, isolate->embedded_blob_size());
constexpr size_t buffer_size = 256; // Enough to fit the single jmp. OffHeapTrampolineGenerator generator(isolate);
byte buffer[buffer_size]; // NOLINT(runtime/arrays) CodeDesc desc = generator.Generate(off_heap_entry);
// Generate replacement code that simply tail-calls the off-heap code. return isolate->factory()->NewCode(desc, Code::BUILTIN,
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes); generator.CodeObject());
DCHECK(!masm.has_frame()); }
{
FrameScope scope(&masm, StackFrame::NONE);
masm.JumpToInstructionStream(off_heap_entry);
}
CodeDesc desc;
masm.GetCode(isolate, &desc);
return isolate->factory()->NewCode(desc, Code::BUILTIN, masm.CodeObject()); // static
Handle<ByteArray> Builtins::GenerateOffHeapTrampolineRelocInfo(
Isolate* isolate) {
OffHeapTrampolineGenerator generator(isolate);
// Generate a jump to a dummy address as we're not actually interested in the
// generated instruction stream.
CodeDesc desc = generator.Generate(kNullAddress);
Handle<ByteArray> reloc_info =
isolate->factory()->NewByteArray(desc.reloc_size, TENURED_READ_ONLY);
Code::CopyRelocInfoToByteArray(*reloc_info, desc);
return reloc_info;
} }
// static // static
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class ByteArray;
class Callable; class Callable;
template <typename T> template <typename T>
class Handle; class Handle;
...@@ -188,6 +189,10 @@ class Builtins { ...@@ -188,6 +189,10 @@ class Builtins {
static Handle<Code> GenerateOffHeapTrampolineFor(Isolate* isolate, static Handle<Code> GenerateOffHeapTrampolineFor(Isolate* isolate,
Address off_heap_entry); Address off_heap_entry);
// Generate the RelocInfo ByteArray that would be generated for an offheap
// trampoline.
static Handle<ByteArray> GenerateOffHeapTrampolineRelocInfo(Isolate* isolate);
private: private:
static void Generate_CallFunction(MacroAssembler* masm, static void Generate_CallFunction(MacroAssembler* masm,
ConvertReceiverMode mode); ConvertReceiverMode mode);
......
...@@ -2575,7 +2575,9 @@ MaybeHandle<Code> Factory::TryNewCode( ...@@ -2575,7 +2575,9 @@ MaybeHandle<Code> Factory::TryNewCode(
uint32_t stub_key, bool is_turbofanned, int stack_slots, uint32_t stub_key, bool is_turbofanned, int stack_slots,
int safepoint_table_offset, int handler_table_offset) { int safepoint_table_offset, int handler_table_offset) {
// Allocate objects needed for code initialization. // Allocate objects needed for code initialization.
Handle<ByteArray> reloc_info = NewByteArray(desc.reloc_size, TENURED); Handle<ByteArray> reloc_info = NewByteArray(
desc.reloc_size,
Builtins::IsBuiltinId(builtin_index) ? TENURED_READ_ONLY : TENURED);
Handle<CodeDataContainer> data_container = NewCodeDataContainer(0); Handle<CodeDataContainer> data_container = NewCodeDataContainer(0);
Handle<ByteArray> source_position_table = Handle<ByteArray> source_position_table =
maybe_source_position_table.is_null() maybe_source_position_table.is_null()
...@@ -2625,7 +2627,9 @@ Handle<Code> Factory::NewCode( ...@@ -2625,7 +2627,9 @@ Handle<Code> Factory::NewCode(
uint32_t stub_key, bool is_turbofanned, int stack_slots, uint32_t stub_key, bool is_turbofanned, int stack_slots,
int safepoint_table_offset, int handler_table_offset) { int safepoint_table_offset, int handler_table_offset) {
// Allocate objects needed for code initialization. // Allocate objects needed for code initialization.
Handle<ByteArray> reloc_info = NewByteArray(desc.reloc_size, TENURED); Handle<ByteArray> reloc_info = NewByteArray(
desc.reloc_size,
Builtins::IsBuiltinId(builtin_index) ? TENURED_READ_ONLY : TENURED);
Handle<CodeDataContainer> data_container = NewCodeDataContainer(0); Handle<CodeDataContainer> data_container = NewCodeDataContainer(0);
Handle<ByteArray> source_position_table = Handle<ByteArray> source_position_table =
maybe_source_position_table.is_null() maybe_source_position_table.is_null()
...@@ -2709,6 +2713,21 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code, ...@@ -2709,6 +2713,21 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
result->set_safepoint_table_offset(code->safepoint_table_offset()); result->set_safepoint_table_offset(code->safepoint_table_offset());
} }
// Replace the newly generated trampoline's RelocInfo ByteArray with the
// canonical one stored in the roots to avoid duplicating it for every single
// builtin.
ByteArray* canonical_reloc_info =
ReadOnlyRoots(isolate()).off_heap_trampoline_relocation_info();
#ifdef DEBUG
// Verify that the contents are the same.
ByteArray* reloc_info = result->relocation_info();
DCHECK_EQ(reloc_info->length(), canonical_reloc_info->length());
for (int i = 0; i < reloc_info->length(); ++i) {
DCHECK_EQ(reloc_info->get(i), canonical_reloc_info->get(i));
}
#endif
result->set_relocation_info(canonical_reloc_info);
return result; return result;
} }
......
...@@ -896,6 +896,9 @@ void Heap::CreateInitialObjects() { ...@@ -896,6 +896,9 @@ void Heap::CreateInitialObjects() {
set_noscript_shared_function_infos(roots.empty_weak_array_list()); set_noscript_shared_function_infos(roots.empty_weak_array_list());
set_off_heap_trampoline_relocation_info(
*Builtins::GenerateOffHeapTrampolineRelocInfo(isolate_));
// Evaluate the hash values which will then be cached in the strings. // Evaluate the hash values which will then be cached in the strings.
isolate()->factory()->zero_string()->Hash(); isolate()->factory()->zero_string()->Hash();
isolate()->factory()->one_string()->Hash(); isolate()->factory()->one_string()->Hash();
......
...@@ -14397,9 +14397,7 @@ void Code::CopyFromNoFlush(Heap* heap, const CodeDesc& desc) { ...@@ -14397,9 +14397,7 @@ void Code::CopyFromNoFlush(Heap* heap, const CodeDesc& desc) {
} }
// Copy reloc info. // Copy reloc info.
CopyBytes(relocation_start(), CopyRelocInfoToByteArray(unchecked_relocation_info(), desc);
desc.buffer + desc.buffer_size - desc.reloc_size,
static_cast<size_t>(desc.reloc_size));
// Unbox handles and relocate. // Unbox handles and relocate.
Assembler* origin = desc.origin; Assembler* origin = desc.origin;
......
...@@ -341,6 +341,14 @@ int Code::ExecutableSize() const { ...@@ -341,6 +341,14 @@ int Code::ExecutableSize() const {
return raw_instruction_size() + Code::kHeaderSize; return raw_instruction_size() + Code::kHeaderSize;
} }
// static
void Code::CopyRelocInfoToByteArray(ByteArray* dest, const CodeDesc& desc) {
DCHECK_EQ(dest->length(), desc.reloc_size);
CopyBytes(dest->GetDataStartAddress(),
desc.buffer + desc.buffer_size - desc.reloc_size,
static_cast<size_t>(desc.reloc_size));
}
int Code::CodeSize() const { return SizeFor(body_size()); } int Code::CodeSize() const { return SizeFor(body_size()); }
Code::Kind Code::kind() const { Code::Kind Code::kind() const {
......
...@@ -308,6 +308,11 @@ class Code : public HeapObject, public NeverReadOnlySpaceObject { ...@@ -308,6 +308,11 @@ class Code : public HeapObject, public NeverReadOnlySpaceObject {
// Migrate code from desc without flushing the instruction cache. // Migrate code from desc without flushing the instruction cache.
void CopyFromNoFlush(Heap* heap, const CodeDesc& desc); void CopyFromNoFlush(Heap* heap, const CodeDesc& desc);
// Copy the RelocInfo portion of |desc| to |dest|. The ByteArray must be
// exactly the same size as the RelocInfo in |desc|.
static inline void CopyRelocInfoToByteArray(ByteArray* dest,
const CodeDesc& desc);
// Flushes the instruction cache for the executable instructions of this code // Flushes the instruction cache for the executable instructions of this code
// object. // object.
void FlushICache() const; void FlushICache() const;
......
...@@ -211,7 +211,10 @@ class RootVisitor; ...@@ -211,7 +211,10 @@ class RootVisitor;
V(HeapNumber*, minus_zero_value, MinusZeroValue) \ V(HeapNumber*, minus_zero_value, MinusZeroValue) \
V(HeapNumber*, minus_infinity_value, MinusInfinityValue) \ V(HeapNumber*, minus_infinity_value, MinusInfinityValue) \
/* Marker for self-references during code-generation */ \ /* Marker for self-references during code-generation */ \
V(HeapObject*, self_reference_marker, SelfReferenceMarker) V(HeapObject*, self_reference_marker, SelfReferenceMarker) \
/* Canonical trampoline RelocInfo */ \
V(ByteArray*, off_heap_trampoline_relocation_info, \
OffHeapTrampolineRelocationInfo)
// Mutable roots that are known to be immortal immovable, for which we can // Mutable roots that are known to be immortal immovable, for which we can
// safely skip write barriers. // safely skip write barriers.
......
...@@ -296,41 +296,41 @@ KNOWN_MAPS = { ...@@ -296,41 +296,41 @@ KNOWN_MAPS = {
("RO_SPACE", 0x02699): (171, "Tuple2Map"), ("RO_SPACE", 0x02699): (171, "Tuple2Map"),
("RO_SPACE", 0x02739): (173, "ArrayBoilerplateDescriptionMap"), ("RO_SPACE", 0x02739): (173, "ArrayBoilerplateDescriptionMap"),
("RO_SPACE", 0x02a79): (161, "InterceptorInfoMap"), ("RO_SPACE", 0x02a79): (161, "InterceptorInfoMap"),
("RO_SPACE", 0x05031): (153, "AccessCheckInfoMap"), ("RO_SPACE", 0x05049): (153, "AccessCheckInfoMap"),
("RO_SPACE", 0x05081): (154, "AccessorInfoMap"), ("RO_SPACE", 0x05099): (154, "AccessorInfoMap"),
("RO_SPACE", 0x050d1): (155, "AccessorPairMap"), ("RO_SPACE", 0x050e9): (155, "AccessorPairMap"),
("RO_SPACE", 0x05121): (156, "AliasedArgumentsEntryMap"), ("RO_SPACE", 0x05139): (156, "AliasedArgumentsEntryMap"),
("RO_SPACE", 0x05171): (157, "AllocationMementoMap"), ("RO_SPACE", 0x05189): (157, "AllocationMementoMap"),
("RO_SPACE", 0x051c1): (158, "AsyncGeneratorRequestMap"), ("RO_SPACE", 0x051d9): (158, "AsyncGeneratorRequestMap"),
("RO_SPACE", 0x05211): (159, "DebugInfoMap"), ("RO_SPACE", 0x05229): (159, "DebugInfoMap"),
("RO_SPACE", 0x05261): (160, "FunctionTemplateInfoMap"), ("RO_SPACE", 0x05279): (160, "FunctionTemplateInfoMap"),
("RO_SPACE", 0x052b1): (162, "InterpreterDataMap"), ("RO_SPACE", 0x052c9): (162, "InterpreterDataMap"),
("RO_SPACE", 0x05301): (163, "ModuleInfoEntryMap"), ("RO_SPACE", 0x05319): (163, "ModuleInfoEntryMap"),
("RO_SPACE", 0x05351): (164, "ModuleMap"), ("RO_SPACE", 0x05369): (164, "ModuleMap"),
("RO_SPACE", 0x053a1): (165, "ObjectTemplateInfoMap"), ("RO_SPACE", 0x053b9): (165, "ObjectTemplateInfoMap"),
("RO_SPACE", 0x053f1): (166, "PromiseCapabilityMap"), ("RO_SPACE", 0x05409): (166, "PromiseCapabilityMap"),
("RO_SPACE", 0x05441): (167, "PromiseReactionMap"), ("RO_SPACE", 0x05459): (167, "PromiseReactionMap"),
("RO_SPACE", 0x05491): (168, "PrototypeInfoMap"), ("RO_SPACE", 0x054a9): (168, "PrototypeInfoMap"),
("RO_SPACE", 0x054e1): (169, "ScriptMap"), ("RO_SPACE", 0x054f9): (169, "ScriptMap"),
("RO_SPACE", 0x05531): (170, "StackFrameInfoMap"), ("RO_SPACE", 0x05549): (170, "StackFrameInfoMap"),
("RO_SPACE", 0x05581): (172, "Tuple3Map"), ("RO_SPACE", 0x05599): (172, "Tuple3Map"),
("RO_SPACE", 0x055d1): (174, "WasmDebugInfoMap"), ("RO_SPACE", 0x055e9): (174, "WasmDebugInfoMap"),
("RO_SPACE", 0x05621): (175, "WasmExportedFunctionDataMap"), ("RO_SPACE", 0x05639): (175, "WasmExportedFunctionDataMap"),
("RO_SPACE", 0x05671): (176, "CallableTaskMap"), ("RO_SPACE", 0x05689): (176, "CallableTaskMap"),
("RO_SPACE", 0x056c1): (177, "CallbackTaskMap"), ("RO_SPACE", 0x056d9): (177, "CallbackTaskMap"),
("RO_SPACE", 0x05711): (178, "PromiseFulfillReactionJobTaskMap"), ("RO_SPACE", 0x05729): (178, "PromiseFulfillReactionJobTaskMap"),
("RO_SPACE", 0x05761): (179, "PromiseRejectReactionJobTaskMap"), ("RO_SPACE", 0x05779): (179, "PromiseRejectReactionJobTaskMap"),
("RO_SPACE", 0x057b1): (180, "PromiseResolveThenableJobTaskMap"), ("RO_SPACE", 0x057c9): (180, "PromiseResolveThenableJobTaskMap"),
("RO_SPACE", 0x05801): (181, "MicrotaskQueueMap"), ("RO_SPACE", 0x05819): (181, "MicrotaskQueueMap"),
("RO_SPACE", 0x05851): (182, "AllocationSiteWithWeakNextMap"), ("RO_SPACE", 0x05869): (182, "AllocationSiteWithWeakNextMap"),
("RO_SPACE", 0x058a1): (182, "AllocationSiteWithoutWeakNextMap"), ("RO_SPACE", 0x058b9): (182, "AllocationSiteWithoutWeakNextMap"),
("RO_SPACE", 0x058f1): (214, "LoadHandler1Map"), ("RO_SPACE", 0x05909): (214, "LoadHandler1Map"),
("RO_SPACE", 0x05941): (214, "LoadHandler2Map"), ("RO_SPACE", 0x05959): (214, "LoadHandler2Map"),
("RO_SPACE", 0x05991): (214, "LoadHandler3Map"), ("RO_SPACE", 0x059a9): (214, "LoadHandler3Map"),
("RO_SPACE", 0x059e1): (221, "StoreHandler0Map"), ("RO_SPACE", 0x059f9): (221, "StoreHandler0Map"),
("RO_SPACE", 0x05a31): (221, "StoreHandler1Map"), ("RO_SPACE", 0x05a49): (221, "StoreHandler1Map"),
("RO_SPACE", 0x05a81): (221, "StoreHandler2Map"), ("RO_SPACE", 0x05a99): (221, "StoreHandler2Map"),
("RO_SPACE", 0x05ad1): (221, "StoreHandler3Map"), ("RO_SPACE", 0x05ae9): (221, "StoreHandler3Map"),
("MAP_SPACE", 0x00139): (1057, "ExternalMap"), ("MAP_SPACE", 0x00139): (1057, "ExternalMap"),
("MAP_SPACE", 0x00189): (1073, "JSMessageObjectMap"), ("MAP_SPACE", 0x00189): (1073, "JSMessageObjectMap"),
} }
...@@ -384,6 +384,7 @@ KNOWN_OBJECTS = { ...@@ -384,6 +384,7 @@ KNOWN_OBJECTS = {
("RO_SPACE", 0x02af1): "MinusZeroValue", ("RO_SPACE", 0x02af1): "MinusZeroValue",
("RO_SPACE", 0x02b01): "MinusInfinityValue", ("RO_SPACE", 0x02b01): "MinusInfinityValue",
("RO_SPACE", 0x02b11): "SelfReferenceMarker", ("RO_SPACE", 0x02b11): "SelfReferenceMarker",
("RO_SPACE", 0x02b69): "OffHeapTrampolineRelocationInfo",
("OLD_SPACE", 0x00139): "ArgumentsIteratorAccessor", ("OLD_SPACE", 0x00139): "ArgumentsIteratorAccessor",
("OLD_SPACE", 0x001a9): "ArrayLengthAccessor", ("OLD_SPACE", 0x001a9): "ArrayLengthAccessor",
("OLD_SPACE", 0x00219): "BoundFunctionLengthAccessor", ("OLD_SPACE", 0x00219): "BoundFunctionLengthAccessor",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment