Reland: [embedded] Share a single RelocInfo between all trampolines
This is a reland of https://chromium-review.googlesource.com/c/v8/v8/+/1276468, without the change "Also forces all non-trampoline RelocInfo ByteArrays for builtins to be generated into RO_SPACE." 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. On x64, this results in the OLD_SPACE part of the startup snapshot decreasing in size from 165656 to 130808 (-34848) bytes and RO_SPACE (in the read-only snapshot) increasing from 31248 to 31272 (+24) bytes. Bug: v8:8295 Change-Id: I0dee7dfaccd9b8025d7707b0bb90194173f1ee89 Reviewed-on: https://chromium-review.googlesource.com/c/1296459 Commit-Queue: Dan Elphick <delphick@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#56930}
This commit is contained in:
parent
4c1e1cb561
commit
6b3ef32d57
@ -12,6 +12,7 @@
|
||||
#include "src/isolate.h"
|
||||
#include "src/macro-assembler.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/objects/fixed-array.h"
|
||||
#include "src/visitors.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -364,6 +365,39 @@ bool Builtins::IsWasmRuntimeStub(int index) {
|
||||
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
|
||||
Handle<Code> Builtins::GenerateOffHeapTrampolineFor(Isolate* isolate,
|
||||
Address off_heap_entry) {
|
||||
@ -371,21 +405,26 @@ Handle<Code> Builtins::GenerateOffHeapTrampolineFor(Isolate* isolate,
|
||||
DCHECK_NOT_NULL(isolate->embedded_blob());
|
||||
DCHECK_NE(0, isolate->embedded_blob_size());
|
||||
|
||||
constexpr size_t buffer_size = 256; // Enough to fit the single jmp.
|
||||
byte buffer[buffer_size]; // NOLINT(runtime/arrays)
|
||||
OffHeapTrampolineGenerator generator(isolate);
|
||||
CodeDesc desc = generator.Generate(off_heap_entry);
|
||||
|
||||
// Generate replacement code that simply tail-calls the off-heap code.
|
||||
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes);
|
||||
DCHECK(!masm.has_frame());
|
||||
{
|
||||
FrameScope scope(&masm, StackFrame::NONE);
|
||||
masm.JumpToInstructionStream(off_heap_entry);
|
||||
}
|
||||
return isolate->factory()->NewCode(desc, Code::BUILTIN,
|
||||
generator.CodeObject());
|
||||
}
|
||||
|
||||
CodeDesc desc;
|
||||
masm.GetCode(isolate, &desc);
|
||||
// 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);
|
||||
|
||||
return isolate->factory()->NewCode(desc, Code::BUILTIN, masm.CodeObject());
|
||||
Handle<ByteArray> reloc_info =
|
||||
isolate->factory()->NewByteArray(desc.reloc_size, TENURED_READ_ONLY);
|
||||
Code::CopyRelocInfoToByteArray(*reloc_info, desc);
|
||||
|
||||
return reloc_info;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class ByteArray;
|
||||
class Callable;
|
||||
template <typename T>
|
||||
class Handle;
|
||||
@ -188,6 +189,10 @@ class Builtins {
|
||||
static Handle<Code> GenerateOffHeapTrampolineFor(Isolate* isolate,
|
||||
Address off_heap_entry);
|
||||
|
||||
// Generate the RelocInfo ByteArray that would be generated for an offheap
|
||||
// trampoline.
|
||||
static Handle<ByteArray> GenerateOffHeapTrampolineRelocInfo(Isolate* isolate);
|
||||
|
||||
private:
|
||||
static void Generate_CallFunction(MacroAssembler* masm,
|
||||
ConvertReceiverMode mode);
|
||||
|
@ -2703,6 +2703,21 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -896,6 +896,9 @@ void Heap::CreateInitialObjects() {
|
||||
|
||||
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.
|
||||
isolate()->factory()->zero_string()->Hash();
|
||||
isolate()->factory()->one_string()->Hash();
|
||||
|
@ -14407,9 +14407,7 @@ void Code::CopyFromNoFlush(Heap* heap, const CodeDesc& desc) {
|
||||
}
|
||||
|
||||
// Copy reloc info.
|
||||
CopyBytes(relocation_start(),
|
||||
desc.buffer + desc.buffer_size - desc.reloc_size,
|
||||
static_cast<size_t>(desc.reloc_size));
|
||||
CopyRelocInfoToByteArray(unchecked_relocation_info(), desc);
|
||||
|
||||
// Unbox handles and relocate.
|
||||
Assembler* origin = desc.origin;
|
||||
|
@ -341,6 +341,14 @@ int Code::ExecutableSize() const {
|
||||
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()); }
|
||||
|
||||
Code::Kind Code::kind() const {
|
||||
|
@ -308,6 +308,11 @@ class Code : public HeapObject, public NeverReadOnlySpaceObject {
|
||||
// Migrate code from desc without flushing the instruction cache.
|
||||
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
|
||||
// object.
|
||||
void FlushICache() const;
|
||||
|
@ -212,7 +212,10 @@ class RootVisitor;
|
||||
V(HeapNumber*, minus_zero_value, MinusZeroValue) \
|
||||
V(HeapNumber*, minus_infinity_value, MinusInfinityValue) \
|
||||
/* 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
|
||||
// safely skip write barriers.
|
||||
|
@ -296,41 +296,41 @@ KNOWN_MAPS = {
|
||||
("RO_SPACE", 0x02699): (171, "Tuple2Map"),
|
||||
("RO_SPACE", 0x02739): (173, "ArrayBoilerplateDescriptionMap"),
|
||||
("RO_SPACE", 0x02a79): (161, "InterceptorInfoMap"),
|
||||
("RO_SPACE", 0x050a9): (153, "AccessCheckInfoMap"),
|
||||
("RO_SPACE", 0x050f9): (154, "AccessorInfoMap"),
|
||||
("RO_SPACE", 0x05149): (155, "AccessorPairMap"),
|
||||
("RO_SPACE", 0x05199): (156, "AliasedArgumentsEntryMap"),
|
||||
("RO_SPACE", 0x051e9): (157, "AllocationMementoMap"),
|
||||
("RO_SPACE", 0x05239): (158, "AsyncGeneratorRequestMap"),
|
||||
("RO_SPACE", 0x05289): (159, "DebugInfoMap"),
|
||||
("RO_SPACE", 0x052d9): (160, "FunctionTemplateInfoMap"),
|
||||
("RO_SPACE", 0x05329): (162, "InterpreterDataMap"),
|
||||
("RO_SPACE", 0x05379): (163, "ModuleInfoEntryMap"),
|
||||
("RO_SPACE", 0x053c9): (164, "ModuleMap"),
|
||||
("RO_SPACE", 0x05419): (165, "ObjectTemplateInfoMap"),
|
||||
("RO_SPACE", 0x05469): (166, "PromiseCapabilityMap"),
|
||||
("RO_SPACE", 0x054b9): (167, "PromiseReactionMap"),
|
||||
("RO_SPACE", 0x05509): (168, "PrototypeInfoMap"),
|
||||
("RO_SPACE", 0x05559): (169, "ScriptMap"),
|
||||
("RO_SPACE", 0x055a9): (170, "StackFrameInfoMap"),
|
||||
("RO_SPACE", 0x055f9): (172, "Tuple3Map"),
|
||||
("RO_SPACE", 0x05649): (174, "WasmDebugInfoMap"),
|
||||
("RO_SPACE", 0x05699): (175, "WasmExportedFunctionDataMap"),
|
||||
("RO_SPACE", 0x056e9): (176, "CallableTaskMap"),
|
||||
("RO_SPACE", 0x05739): (177, "CallbackTaskMap"),
|
||||
("RO_SPACE", 0x05789): (178, "PromiseFulfillReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x057d9): (179, "PromiseRejectReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x05829): (180, "PromiseResolveThenableJobTaskMap"),
|
||||
("RO_SPACE", 0x05879): (181, "MicrotaskQueueMap"),
|
||||
("RO_SPACE", 0x058c9): (182, "AllocationSiteWithWeakNextMap"),
|
||||
("RO_SPACE", 0x05919): (182, "AllocationSiteWithoutWeakNextMap"),
|
||||
("RO_SPACE", 0x05969): (214, "LoadHandler1Map"),
|
||||
("RO_SPACE", 0x059b9): (214, "LoadHandler2Map"),
|
||||
("RO_SPACE", 0x05a09): (214, "LoadHandler3Map"),
|
||||
("RO_SPACE", 0x05a59): (221, "StoreHandler0Map"),
|
||||
("RO_SPACE", 0x05aa9): (221, "StoreHandler1Map"),
|
||||
("RO_SPACE", 0x05af9): (221, "StoreHandler2Map"),
|
||||
("RO_SPACE", 0x05b49): (221, "StoreHandler3Map"),
|
||||
("RO_SPACE", 0x050c1): (153, "AccessCheckInfoMap"),
|
||||
("RO_SPACE", 0x05111): (154, "AccessorInfoMap"),
|
||||
("RO_SPACE", 0x05161): (155, "AccessorPairMap"),
|
||||
("RO_SPACE", 0x051b1): (156, "AliasedArgumentsEntryMap"),
|
||||
("RO_SPACE", 0x05201): (157, "AllocationMementoMap"),
|
||||
("RO_SPACE", 0x05251): (158, "AsyncGeneratorRequestMap"),
|
||||
("RO_SPACE", 0x052a1): (159, "DebugInfoMap"),
|
||||
("RO_SPACE", 0x052f1): (160, "FunctionTemplateInfoMap"),
|
||||
("RO_SPACE", 0x05341): (162, "InterpreterDataMap"),
|
||||
("RO_SPACE", 0x05391): (163, "ModuleInfoEntryMap"),
|
||||
("RO_SPACE", 0x053e1): (164, "ModuleMap"),
|
||||
("RO_SPACE", 0x05431): (165, "ObjectTemplateInfoMap"),
|
||||
("RO_SPACE", 0x05481): (166, "PromiseCapabilityMap"),
|
||||
("RO_SPACE", 0x054d1): (167, "PromiseReactionMap"),
|
||||
("RO_SPACE", 0x05521): (168, "PrototypeInfoMap"),
|
||||
("RO_SPACE", 0x05571): (169, "ScriptMap"),
|
||||
("RO_SPACE", 0x055c1): (170, "StackFrameInfoMap"),
|
||||
("RO_SPACE", 0x05611): (172, "Tuple3Map"),
|
||||
("RO_SPACE", 0x05661): (174, "WasmDebugInfoMap"),
|
||||
("RO_SPACE", 0x056b1): (175, "WasmExportedFunctionDataMap"),
|
||||
("RO_SPACE", 0x05701): (176, "CallableTaskMap"),
|
||||
("RO_SPACE", 0x05751): (177, "CallbackTaskMap"),
|
||||
("RO_SPACE", 0x057a1): (178, "PromiseFulfillReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x057f1): (179, "PromiseRejectReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x05841): (180, "PromiseResolveThenableJobTaskMap"),
|
||||
("RO_SPACE", 0x05891): (181, "MicrotaskQueueMap"),
|
||||
("RO_SPACE", 0x058e1): (182, "AllocationSiteWithWeakNextMap"),
|
||||
("RO_SPACE", 0x05931): (182, "AllocationSiteWithoutWeakNextMap"),
|
||||
("RO_SPACE", 0x05981): (214, "LoadHandler1Map"),
|
||||
("RO_SPACE", 0x059d1): (214, "LoadHandler2Map"),
|
||||
("RO_SPACE", 0x05a21): (214, "LoadHandler3Map"),
|
||||
("RO_SPACE", 0x05a71): (221, "StoreHandler0Map"),
|
||||
("RO_SPACE", 0x05ac1): (221, "StoreHandler1Map"),
|
||||
("RO_SPACE", 0x05b11): (221, "StoreHandler2Map"),
|
||||
("RO_SPACE", 0x05b61): (221, "StoreHandler3Map"),
|
||||
("MAP_SPACE", 0x00139): (1057, "ExternalMap"),
|
||||
("MAP_SPACE", 0x00189): (1073, "JSMessageObjectMap"),
|
||||
}
|
||||
@ -384,6 +384,7 @@ KNOWN_OBJECTS = {
|
||||
("RO_SPACE", 0x02af1): "MinusZeroValue",
|
||||
("RO_SPACE", 0x02b01): "MinusInfinityValue",
|
||||
("RO_SPACE", 0x02b11): "SelfReferenceMarker",
|
||||
("RO_SPACE", 0x02b69): "OffHeapTrampolineRelocationInfo",
|
||||
("OLD_SPACE", 0x00139): "ArgumentsIteratorAccessor",
|
||||
("OLD_SPACE", 0x001a9): "ArrayLengthAccessor",
|
||||
("OLD_SPACE", 0x00219): "BoundFunctionLengthAccessor",
|
||||
|
Loading…
Reference in New Issue
Block a user