Commit 779b0edd authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[code] Move embedded metadata to the .rodata section

The embedded metadata section is the off-heap equivalent to an on-heap
Code object's metadata section. It contains no executable data, thus
.rodata is the natural home for it. Another motivation is that some
platforms do not grant read permissions on the .text section.

Embedded blob stats before:

  EmbeddedData:
    Total size: 1322944
    Data size:  25952
    Code size:  1296992

And after:

  EmbeddedData:
    Total size: 1323372
    Data size:  121452
    Code size:  1201920

(Slight size increase due to additional padding.)

Bug: v8:11036,v8:10707
Change-Id: Ib6b54a7e947966c7bd2fcc1e7e44c85e352f0063
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2502334Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Auto-Submit: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70822}
parent 3640583f
...@@ -199,7 +199,10 @@ void CodeStatistics::CollectCodeCommentStatistics(HeapObject obj, ...@@ -199,7 +199,10 @@ void CodeStatistics::CollectCodeCommentStatistics(HeapObject obj,
Isolate* isolate) { Isolate* isolate) {
// Bytecode objects do not contain RelocInfo. Only process code objects // Bytecode objects do not contain RelocInfo. Only process code objects
// for code comment statistics. // for code comment statistics.
if (!obj.IsCode()) return; if (!obj.IsCode()) {
DCHECK(obj.IsBytecodeArray());
return;
}
Code code = Code::cast(obj); Code code = Code::cast(obj);
CodeCommentsIterator cit(code.code_comments(), code.code_comments_size()); CodeCommentsIterator cit(code.code_comments(), code.code_comments_size());
...@@ -212,9 +215,8 @@ void CodeStatistics::CollectCodeCommentStatistics(HeapObject obj, ...@@ -212,9 +215,8 @@ void CodeStatistics::CollectCodeCommentStatistics(HeapObject obj,
cit.Next(); cit.Next();
} }
STATIC_ASSERT(Code::kBodyIsContiguous); DCHECK(0 <= prev_pc_offset && prev_pc_offset <= code.InstructionSize());
DCHECK(0 <= prev_pc_offset && prev_pc_offset <= code.raw_body_size()); delta += static_cast<int>(code.InstructionSize() - prev_pc_offset);
delta += static_cast<int>(code.raw_body_size() - prev_pc_offset);
EnterComment(isolate, "NoComment", delta); EnterComment(isolate, "NoComment", delta);
} }
#endif #endif
......
...@@ -119,7 +119,6 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal( ...@@ -119,7 +119,6 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal(
isolate_->heap()->SetBasicBlockProfilingData(new_list); isolate_->heap()->SetBasicBlockProfilingData(new_list);
} }
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas.
STATIC_ASSERT(Code::kOnHeapBodyIsContiguous); STATIC_ASSERT(Code::kOnHeapBodyIsContiguous);
const int object_size = Code::SizeFor(code_desc_.body_size()); const int object_size = Code::SizeFor(code_desc_.body_size());
......
...@@ -222,11 +222,6 @@ void Code::set_next_code_link(Object value) { ...@@ -222,11 +222,6 @@ void Code::set_next_code_link(Object value) {
Address Code::raw_body_start() const { return raw_instruction_start(); } Address Code::raw_body_start() const { return raw_instruction_start(); }
Address Code::BodyStart() const {
STATIC_ASSERT(kBodyIsContiguous);
return InstructionStart();
}
Address Code::raw_body_end() const { Address Code::raw_body_end() const {
return raw_body_start() + raw_body_size(); return raw_body_start() + raw_body_size();
} }
...@@ -235,19 +230,6 @@ int Code::raw_body_size() const { ...@@ -235,19 +230,6 @@ int Code::raw_body_size() const {
return raw_instruction_size() + raw_metadata_size(); return raw_instruction_size() + raw_metadata_size();
} }
Address Code::BodyEnd() const {
STATIC_ASSERT(kBodyIsContiguous);
return MetadataEnd();
}
int Code::BodySize() const {
// TODO(jgruber,v8:11036): Update once embedded instructions and metadata are
// separate.
return V8_UNLIKELY(is_off_heap_trampoline())
? OffHeapInstructionSize() + OffHeapMetadataSize()
: raw_body_size();
}
int Code::InstructionSize() const { int Code::InstructionSize() const {
return V8_UNLIKELY(is_off_heap_trampoline()) ? OffHeapInstructionSize() return V8_UNLIKELY(is_off_heap_trampoline()) ? OffHeapInstructionSize()
: raw_instruction_size(); : raw_instruction_size();
...@@ -276,7 +258,7 @@ Address Code::raw_metadata_start() const { ...@@ -276,7 +258,7 @@ Address Code::raw_metadata_start() const {
} }
Address Code::MetadataStart() const { Address Code::MetadataStart() const {
STATIC_ASSERT(kBodyIsContiguous); STATIC_ASSERT(kOnHeapBodyIsContiguous);
return V8_UNLIKELY(is_off_heap_trampoline()) ? OffHeapMetadataStart() return V8_UNLIKELY(is_off_heap_trampoline()) ? OffHeapMetadataStart()
: raw_metadata_start(); : raw_metadata_start();
} }
...@@ -286,13 +268,11 @@ Address Code::raw_metadata_end() const { ...@@ -286,13 +268,11 @@ Address Code::raw_metadata_end() const {
} }
Address Code::MetadataEnd() const { Address Code::MetadataEnd() const {
STATIC_ASSERT(kBodyIsContiguous);
return V8_UNLIKELY(is_off_heap_trampoline()) ? OffHeapMetadataEnd() return V8_UNLIKELY(is_off_heap_trampoline()) ? OffHeapMetadataEnd()
: raw_metadata_end(); : raw_metadata_end();
} }
int Code::MetadataSize() const { int Code::MetadataSize() const {
STATIC_ASSERT(kBodyIsContiguous);
return V8_UNLIKELY(is_off_heap_trampoline()) ? OffHeapMetadataSize() return V8_UNLIKELY(is_off_heap_trampoline()) ? OffHeapMetadataSize()
: raw_metadata_size(); : raw_metadata_size();
} }
...@@ -547,12 +527,10 @@ bool Code::is_optimized_code() const { ...@@ -547,12 +527,10 @@ bool Code::is_optimized_code() const {
bool Code::is_wasm_code() const { return kind() == CodeKind::WASM_FUNCTION; } bool Code::is_wasm_code() const { return kind() == CodeKind::WASM_FUNCTION; }
int Code::constant_pool_offset() const { int Code::constant_pool_offset() const {
if (!FLAG_enable_embedded_constant_pool) return code_comments_offset();
return ReadField<int>(kConstantPoolOffsetOffset); return ReadField<int>(kConstantPoolOffsetOffset);
} }
void Code::set_constant_pool_offset(int value) { void Code::set_constant_pool_offset(int value) {
if (!FLAG_enable_embedded_constant_pool) return;
DCHECK_LE(value, MetadataSize()); DCHECK_LE(value, MetadataSize());
WriteField<int>(kConstantPoolOffsetOffset, value); WriteField<int>(kConstantPoolOffsetOffset, value);
} }
......
...@@ -91,7 +91,6 @@ void Code::FlushICache() const { ...@@ -91,7 +91,6 @@ void Code::FlushICache() const {
void Code::CopyFromNoFlush(Heap* heap, const CodeDesc& desc) { void Code::CopyFromNoFlush(Heap* heap, const CodeDesc& desc) {
// Copy code. // Copy code.
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas.
STATIC_ASSERT(kOnHeapBodyIsContiguous); STATIC_ASSERT(kOnHeapBodyIsContiguous);
CopyBytes(reinterpret_cast<byte*>(raw_instruction_start()), desc.buffer, CopyBytes(reinterpret_cast<byte*>(raw_instruction_start()), desc.buffer,
static_cast<size_t>(desc.instr_size)); static_cast<size_t>(desc.instr_size));
......
...@@ -129,20 +129,16 @@ class Code : public HeapObject { ...@@ -129,20 +129,16 @@ class Code : public HeapObject {
// | | <-- MS + unwinding_info_offset() // | | <-- MS + unwinding_info_offset()
// +--------------------------+ <-- MetadataEnd() // +--------------------------+ <-- MetadataEnd()
// TODO(jgruber,v8:11036): Update once no longer true for embedded builtins. // Constants for use in static asserts, stating whether the body is adjacent,
// i.e. instructions and metadata areas are adjacent.
static constexpr bool kOnHeapBodyIsContiguous = true; static constexpr bool kOnHeapBodyIsContiguous = true;
static constexpr bool kOffHeapBodyIsContiguous = true; static constexpr bool kOffHeapBodyIsContiguous = false;
static constexpr bool kBodyIsContiguous = static constexpr bool kBodyIsContiguous =
kOnHeapBodyIsContiguous && kOffHeapBodyIsContiguous; kOnHeapBodyIsContiguous && kOffHeapBodyIsContiguous;
inline Address raw_body_start() const; inline Address raw_body_start() const;
inline Address BodyStart() const;
inline Address raw_body_end() const; inline Address raw_body_end() const;
inline Address BodyEnd() const;
inline int raw_body_size() const; inline int raw_body_size() const;
// TODO(jgruber,v8:11036): Replace this once the off-heap instruction and
// metadata areas are separate.
inline int BodySize() const;
inline Address raw_instruction_start() const; inline Address raw_instruction_start() const;
inline Address InstructionStart() const; inline Address InstructionStart() const;
...@@ -171,8 +167,7 @@ class Code : public HeapObject { ...@@ -171,8 +167,7 @@ class Code : public HeapObject {
// The metadata section is aligned to this value. // The metadata section is aligned to this value.
static constexpr int kMetadataAlignment = kIntSize; static constexpr int kMetadataAlignment = kIntSize;
// [safepoint_table_offset]: If {has_safepoint_info()}, the offset where the // [safepoint_table_offset]: The offset where the safepoint table starts.
// safepoint table starts.
inline int safepoint_table_offset() const { return 0; } inline int safepoint_table_offset() const { return 0; }
Address SafepointTableAddress() const; Address SafepointTableAddress() const;
int safepoint_table_size() const; int safepoint_table_size() const;
...@@ -187,9 +182,9 @@ class Code : public HeapObject { ...@@ -187,9 +182,9 @@ class Code : public HeapObject {
bool has_handler_table() const; bool has_handler_table() const;
// [constant_pool offset]: Offset of the constant pool. // [constant_pool offset]: Offset of the constant pool.
// Valid for FLAG_enable_embedded_constant_pool only
inline int constant_pool_offset() const; inline int constant_pool_offset() const;
inline void set_constant_pool_offset(int offset); inline void set_constant_pool_offset(int offset);
inline Address constant_pool() const;
int constant_pool_size() const; int constant_pool_size() const;
bool has_constant_pool() const; bool has_constant_pool() const;
...@@ -325,9 +320,6 @@ class Code : public HeapObject { ...@@ -325,9 +320,6 @@ class Code : public HeapObject {
// this is a trampoline to an off-heap builtin. // this is a trampoline to an off-heap builtin.
inline bool is_off_heap_trampoline() const; inline bool is_off_heap_trampoline() const;
// [constant_pool]: The constant pool for this function.
inline Address constant_pool() const;
// Get the safepoint entry for the given pc. // Get the safepoint entry for the given pc.
SafepointEntry GetSafepointEntry(Address pc); SafepointEntry GetSafepointEntry(Address pc);
......
...@@ -663,6 +663,7 @@ void Deserializer::RelocInfoVisitor::VisitInternalReference(Code host, ...@@ -663,6 +663,7 @@ void Deserializer::RelocInfoVisitor::VisitInternalReference(Code host,
// TODO(jgruber,v8:11036): We are being permissive for this DCHECK, but // TODO(jgruber,v8:11036): We are being permissive for this DCHECK, but
// consider using raw_instruction_size() instead of raw_body_size() in the // consider using raw_instruction_size() instead of raw_body_size() in the
// future. // future.
STATIC_ASSERT(Code::kOnHeapBodyIsContiguous);
DCHECK_LT(static_cast<unsigned>(target_offset), DCHECK_LT(static_cast<unsigned>(target_offset),
static_cast<unsigned>(host.raw_body_size())); static_cast<unsigned>(host.raw_body_size()));
Address target = host.entry() + target_offset; Address target = host.entry() + target_offset;
......
...@@ -209,6 +209,7 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) { ...@@ -209,6 +209,7 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
bool saw_unsafe_builtin = false; bool saw_unsafe_builtin = false;
uint32_t raw_code_size = 0; uint32_t raw_code_size = 0;
uint32_t raw_data_size = 0;
STATIC_ASSERT(Builtins::kAllBuiltinsAreIsolateIndependent); STATIC_ASSERT(Builtins::kAllBuiltinsAreIsolateIndependent);
for (int i = 0; i < Builtins::builtin_count; i++) { for (int i = 0; i < Builtins::builtin_count; i++) {
Code code = builtins->builtin(i); Code code = builtins->builtin(i);
...@@ -228,16 +229,16 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) { ...@@ -228,16 +229,16 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
uint32_t instruction_size = uint32_t instruction_size =
static_cast<uint32_t>(code.raw_instruction_size()); static_cast<uint32_t>(code.raw_instruction_size());
uint32_t metadata_size = static_cast<uint32_t>(code.raw_metadata_size()); uint32_t metadata_size = static_cast<uint32_t>(code.raw_metadata_size());
uint32_t length = instruction_size + metadata_size;
DCHECK_EQ(0, raw_code_size % kCodeAlignment); DCHECK_EQ(0, raw_code_size % kCodeAlignment);
layout_descriptions[i].instruction_offset = raw_code_size; layout_descriptions[i].instruction_offset = raw_code_size;
layout_descriptions[i].instruction_length = instruction_size; layout_descriptions[i].instruction_length = instruction_size;
layout_descriptions[i].metadata_offset = raw_code_size + instruction_size; layout_descriptions[i].metadata_offset = raw_data_size;
layout_descriptions[i].metadata_length = metadata_size; layout_descriptions[i].metadata_length = metadata_size;
// Align the start of each instruction stream. // Align the start of each section.
raw_code_size += PadAndAlign(length); raw_code_size += PadAndAlignCode(instruction_size);
raw_data_size += PadAndAlignData(metadata_size);
} }
CHECK_WITH_MSG( CHECK_WITH_MSG(
!saw_unsafe_builtin, !saw_unsafe_builtin,
...@@ -245,12 +246,15 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) { ...@@ -245,12 +246,15 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
"isolate-dependent code or aliases the off-heap trampoline register. " "isolate-dependent code or aliases the off-heap trampoline register. "
"If in doubt, ask jgruber@"); "If in doubt, ask jgruber@");
// Allocate space for the code section, value-initialized to 0.
STATIC_ASSERT(RawCodeOffset() == 0);
const uint32_t blob_code_size = RawCodeOffset() + raw_code_size; const uint32_t blob_code_size = RawCodeOffset() + raw_code_size;
uint8_t* const blob_code = new uint8_t[blob_code_size]; uint8_t* const blob_code = new uint8_t[blob_code_size]();
uint8_t* const raw_code_start = blob_code + RawCodeOffset();
const uint32_t blob_data_size = // Allocate space for the data section, value-initialized to 0.
LayoutDescriptionTableOffset() + LayoutDescriptionTableSize(); STATIC_ASSERT(IsAligned(FixedDataSize(), Code::kMetadataAlignment));
uint8_t* const blob_data = new uint8_t[blob_data_size]; const uint32_t blob_data_size = FixedDataSize() + raw_data_size;
uint8_t* const blob_data = new uint8_t[blob_data_size]();
// Initially zap the entire blob, effectively padding the alignment area // Initially zap the entire blob, effectively padding the alignment area
// between two builtins with int3's (on x64/ia32). // between two builtins with int3's (on x64/ia32).
...@@ -269,16 +273,30 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) { ...@@ -269,16 +273,30 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
std::memcpy(blob_data + LayoutDescriptionTableOffset(), std::memcpy(blob_data + LayoutDescriptionTableOffset(),
layout_descriptions.data(), LayoutDescriptionTableSize()); layout_descriptions.data(), LayoutDescriptionTableSize());
// Write the raw data section. // .. and the variable-size data section.
uint8_t* const raw_metadata_start = blob_data + RawMetadataOffset();
STATIC_ASSERT(Builtins::kAllBuiltinsAreIsolateIndependent);
for (int i = 0; i < Builtins::builtin_count; i++) {
Code code = builtins->builtin(i);
uint32_t offset = layout_descriptions[i].metadata_offset;
uint8_t* dst = raw_metadata_start + offset;
DCHECK_LE(RawMetadataOffset() + offset + code.raw_metadata_size(),
blob_data_size);
std::memcpy(dst, reinterpret_cast<uint8_t*>(code.raw_metadata_start()),
code.raw_metadata_size());
}
// .. and the variable-size code section.
uint8_t* const raw_code_start = blob_code + RawCodeOffset();
STATIC_ASSERT(Builtins::kAllBuiltinsAreIsolateIndependent); STATIC_ASSERT(Builtins::kAllBuiltinsAreIsolateIndependent);
for (int i = 0; i < Builtins::builtin_count; i++) { for (int i = 0; i < Builtins::builtin_count; i++) {
STATIC_ASSERT(Code::kBodyIsContiguous);
Code code = builtins->builtin(i); Code code = builtins->builtin(i);
uint32_t offset = layout_descriptions[i].instruction_offset; uint32_t offset = layout_descriptions[i].instruction_offset;
uint8_t* dst = raw_code_start + offset; uint8_t* dst = raw_code_start + offset;
DCHECK_LE(RawCodeOffset() + offset + code.raw_body_size(), blob_code_size); DCHECK_LE(RawCodeOffset() + offset + code.raw_instruction_size(),
std::memcpy(dst, reinterpret_cast<uint8_t*>(code.raw_body_start()), blob_code_size);
code.raw_body_size()); std::memcpy(dst, reinterpret_cast<uint8_t*>(code.raw_instruction_start()),
code.raw_instruction_size());
} }
EmbeddedData d(blob_code, blob_code_size, blob_data, blob_data_size); EmbeddedData d(blob_code, blob_code_size, blob_data, blob_data_size);
...@@ -318,10 +336,9 @@ uint32_t EmbeddedData::InstructionSizeOfBuiltin(int i) const { ...@@ -318,10 +336,9 @@ uint32_t EmbeddedData::InstructionSizeOfBuiltin(int i) const {
Address EmbeddedData::MetadataStartOfBuiltin(int i) const { Address EmbeddedData::MetadataStartOfBuiltin(int i) const {
DCHECK(Builtins::IsBuiltinId(i)); DCHECK(Builtins::IsBuiltinId(i));
STATIC_ASSERT(Code::kOffHeapBodyIsContiguous);
const struct LayoutDescription* descs = LayoutDescription(); const struct LayoutDescription* descs = LayoutDescription();
const uint8_t* result = RawCode() + descs[i].metadata_offset; const uint8_t* result = RawMetadata() + descs[i].metadata_offset;
DCHECK_LT(result, code_ + code_size_); DCHECK_LE(descs[i].metadata_offset, data_size_);
return reinterpret_cast<Address>(result); return reinterpret_cast<Address>(result);
} }
......
...@@ -85,10 +85,9 @@ class EmbeddedData final { ...@@ -85,10 +85,9 @@ class EmbeddedData final {
// Padded with kCodeAlignment. // Padded with kCodeAlignment.
// TODO(v8:11045): Consider removing code alignment. // TODO(v8:11045): Consider removing code alignment.
uint32_t PaddedInstructionSizeOfBuiltin(int i) const { uint32_t PaddedInstructionSizeOfBuiltin(int i) const {
STATIC_ASSERT(Code::kOffHeapBodyIsContiguous); uint32_t size = InstructionSizeOfBuiltin(i);
uint32_t size = InstructionSizeOfBuiltin(i) + MetadataSizeOfBuiltin(i);
CHECK_NE(size, 0); CHECK_NE(size, 0);
return PadAndAlign(size); return PadAndAlignCode(size);
} }
size_t CreateEmbeddedBlobHash() const; size_t CreateEmbeddedBlobHash() const;
...@@ -129,10 +128,12 @@ class EmbeddedData final { ...@@ -129,10 +128,12 @@ class EmbeddedData final {
// [1] hash of embedded-blob-relevant heap objects // [1] hash of embedded-blob-relevant heap objects
// [2] layout description of instruction stream 0 // [2] layout description of instruction stream 0
// ... layout descriptions // ... layout descriptions
// [x] metadata section of builtin 0
// ... metadata sections
// //
// code: // code:
// [0] instruction stream 0 // [0] instruction section of builtin 0
// ... instruction streams // ... instruction sections
static constexpr uint32_t kTableSize = Builtins::builtin_count; static constexpr uint32_t kTableSize = Builtins::builtin_count;
static constexpr uint32_t EmbeddedBlobHashOffset() { return 0; } static constexpr uint32_t EmbeddedBlobHashOffset() { return 0; }
...@@ -147,6 +148,13 @@ class EmbeddedData final { ...@@ -147,6 +148,13 @@ class EmbeddedData final {
static constexpr uint32_t LayoutDescriptionTableSize() { static constexpr uint32_t LayoutDescriptionTableSize() {
return sizeof(struct LayoutDescription) * kTableSize; return sizeof(struct LayoutDescription) * kTableSize;
} }
static constexpr uint32_t FixedDataSize() {
return LayoutDescriptionTableOffset() + LayoutDescriptionTableSize();
}
// The variable-size data section starts here.
static constexpr uint32_t RawMetadataOffset() { return FixedDataSize(); }
// Code is in its own dedicated section.
static constexpr uint32_t RawCodeOffset() { return 0; } static constexpr uint32_t RawCodeOffset() { return 0; }
private: private:
...@@ -159,28 +167,35 @@ class EmbeddedData final { ...@@ -159,28 +167,35 @@ class EmbeddedData final {
DCHECK_LT(0, data_size); DCHECK_LT(0, data_size);
} }
const uint8_t* RawCode() const { return code_ + RawCodeOffset(); }
const LayoutDescription* LayoutDescription() const { const LayoutDescription* LayoutDescription() const {
return reinterpret_cast<const struct LayoutDescription*>( return reinterpret_cast<const struct LayoutDescription*>(
data_ + LayoutDescriptionTableOffset()); data_ + LayoutDescriptionTableOffset());
} }
const uint8_t* RawCode() const { return code_ + RawCodeOffset(); } const uint8_t* RawMetadata() const { return data_ + RawMetadataOffset(); }
static constexpr int PadAndAlign(int size) { static constexpr int PadAndAlignCode(int size) {
// Ensure we have at least one byte trailing the actual builtin // Ensure we have at least one byte trailing the actual builtin
// instructions which we can later fill with int3. // instructions which we can later fill with int3.
return RoundUp<kCodeAlignment>(size + 1); return RoundUp<kCodeAlignment>(size + 1);
} }
static constexpr int PadAndAlignData(int size) {
// Ensure we have at least one byte trailing the actual builtin
// instructions which we can later fill with int3.
return RoundUp<Code::kMetadataAlignment>(size);
}
void PrintStatistics() const; void PrintStatistics() const;
// This points to code for builtins. The contents are potentially unreadable // The code section contains instruction streams. It is guaranteed to have
// on platforms that disallow reads from the .text section. // execute permissions, and may have read permissions.
const uint8_t* code_; const uint8_t* code_;
uint32_t code_size_; uint32_t code_size_;
// The data section contains both descriptions of the code section (hashes, // The data section contains both descriptions of the code section (hashes,
// offsets, sizes) and metadata describing Code objects (see // offsets, sizes) and metadata describing Code objects (see
// Code::MetadataStart()). // Code::MetadataStart()). It is guaranteed to have read permissions.
const uint8_t* data_; const uint8_t* data_;
uint32_t data_size_; uint32_t data_size_;
}; };
......
...@@ -130,9 +130,10 @@ void EmbeddedFileWriter::WriteBuiltinLabels(PlatformEmbeddedFileWriterBase* w, ...@@ -130,9 +130,10 @@ void EmbeddedFileWriter::WriteBuiltinLabels(PlatformEmbeddedFileWriterBase* w,
w->DeclareLabel(name.c_str()); w->DeclareLabel(name.c_str());
} }
void EmbeddedFileWriter::WriteInstructionStreams( void EmbeddedFileWriter::WriteCodeSection(PlatformEmbeddedFileWriterBase* w,
PlatformEmbeddedFileWriterBase* w, const i::EmbeddedData* blob) const { const i::EmbeddedData* blob) const {
w->Comment("The embedded blob data starts here. It contains the builtin"); w->Comment(
"The embedded blob code section starts here. It contains the builtin");
w->Comment("instruction streams."); w->Comment("instruction streams.");
w->SectionText(); w->SectionText();
......
...@@ -110,7 +110,7 @@ class EmbeddedFileWriter : public EmbeddedFileWriterInterface { ...@@ -110,7 +110,7 @@ class EmbeddedFileWriter : public EmbeddedFileWriterInterface {
WriteFilePrologue(writer.get()); WriteFilePrologue(writer.get());
WriteExternalFilenames(writer.get()); WriteExternalFilenames(writer.get());
WriteDataSection(writer.get(), blob); WriteDataSection(writer.get(), blob);
WriteInstructionStreams(writer.get(), blob); WriteCodeSection(writer.get(), blob);
WriteFileEpilogue(writer.get(), blob); WriteFileEpilogue(writer.get(), blob);
fclose(fp); fclose(fp);
...@@ -185,7 +185,7 @@ class EmbeddedFileWriter : public EmbeddedFileWriterInterface { ...@@ -185,7 +185,7 @@ class EmbeddedFileWriter : public EmbeddedFileWriterInterface {
void WriteBuiltinLabels(PlatformEmbeddedFileWriterBase* w, void WriteBuiltinLabels(PlatformEmbeddedFileWriterBase* w,
std::string name) const; std::string name) const;
void WriteInstructionStreams(PlatformEmbeddedFileWriterBase* w, void WriteCodeSection(PlatformEmbeddedFileWriterBase* w,
const i::EmbeddedData* blob) const; const i::EmbeddedData* blob) const;
void WriteFileEpilogue(PlatformEmbeddedFileWriterBase* w, void WriteFileEpilogue(PlatformEmbeddedFileWriterBase* w,
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "src/snapshot/embedded/platform-embedded-file-writer-aix.h" #include "src/snapshot/embedded/platform-embedded-file-writer-aix.h"
#include "src/objects/code.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -63,10 +65,12 @@ void PlatformEmbeddedFileWriterAIX::DeclareSymbolGlobal(const char* name) { ...@@ -63,10 +65,12 @@ void PlatformEmbeddedFileWriterAIX::DeclareSymbolGlobal(const char* name) {
} }
void PlatformEmbeddedFileWriterAIX::AlignToCodeAlignment() { void PlatformEmbeddedFileWriterAIX::AlignToCodeAlignment() {
STATIC_ASSERT((1 << 5) >= kCodeAlignment);
fprintf(fp_, ".align 5\n"); fprintf(fp_, ".align 5\n");
} }
void PlatformEmbeddedFileWriterAIX::AlignToDataAlignment() { void PlatformEmbeddedFileWriterAIX::AlignToDataAlignment() {
STATIC_ASSERT((1 << 3) >= Code::kMetadataAlignment);
fprintf(fp_, ".align 3\n"); fprintf(fp_, ".align 3\n");
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <cinttypes> #include <cinttypes>
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/objects/code.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -73,6 +74,7 @@ void PlatformEmbeddedFileWriterGeneric::DeclareSymbolGlobal(const char* name) { ...@@ -73,6 +74,7 @@ void PlatformEmbeddedFileWriterGeneric::DeclareSymbolGlobal(const char* name) {
} }
void PlatformEmbeddedFileWriterGeneric::AlignToCodeAlignment() { void PlatformEmbeddedFileWriterGeneric::AlignToCodeAlignment() {
STATIC_ASSERT(32 >= kCodeAlignment);
fprintf(fp_, ".balign 32\n"); fprintf(fp_, ".balign 32\n");
} }
...@@ -81,6 +83,7 @@ void PlatformEmbeddedFileWriterGeneric::AlignToDataAlignment() { ...@@ -81,6 +83,7 @@ void PlatformEmbeddedFileWriterGeneric::AlignToDataAlignment() {
// instructions are used to retrieve v8_Default_embedded_blob_ and/or // instructions are used to retrieve v8_Default_embedded_blob_ and/or
// v8_Default_embedded_blob_size_. The generated instructions require the // v8_Default_embedded_blob_size_. The generated instructions require the
// load target to be aligned at 8 bytes (2^3). // load target to be aligned at 8 bytes (2^3).
STATIC_ASSERT(8 >= Code::kMetadataAlignment);
fprintf(fp_, ".balign 8\n"); fprintf(fp_, ".balign 8\n");
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "src/snapshot/embedded/platform-embedded-file-writer-mac.h" #include "src/snapshot/embedded/platform-embedded-file-writer-mac.h"
#include "src/objects/code.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -54,6 +56,7 @@ void PlatformEmbeddedFileWriterMac::DeclareSymbolGlobal(const char* name) { ...@@ -54,6 +56,7 @@ void PlatformEmbeddedFileWriterMac::DeclareSymbolGlobal(const char* name) {
// prevents something along the compilation chain from messing with the // prevents something along the compilation chain from messing with the
// embedded blob. Using .global here causes embedded blob hash verification // embedded blob. Using .global here causes embedded blob hash verification
// failures at runtime. // failures at runtime.
STATIC_ASSERT(32 >= kCodeAlignment);
fprintf(fp_, ".private_extern _%s\n", name); fprintf(fp_, ".private_extern _%s\n", name);
} }
...@@ -62,6 +65,7 @@ void PlatformEmbeddedFileWriterMac::AlignToCodeAlignment() { ...@@ -62,6 +65,7 @@ void PlatformEmbeddedFileWriterMac::AlignToCodeAlignment() {
} }
void PlatformEmbeddedFileWriterMac::AlignToDataAlignment() { void PlatformEmbeddedFileWriterMac::AlignToDataAlignment() {
STATIC_ASSERT(8 >= Code::kMetadataAlignment);
fprintf(fp_, ".balign 8\n"); fprintf(fp_, ".balign 8\n");
} }
......
...@@ -978,6 +978,7 @@ void Serializer::ObjectSerializer::VisitInternalReference(Code host, ...@@ -978,6 +978,7 @@ void Serializer::ObjectSerializer::VisitInternalReference(Code host,
// TODO(jgruber,v8:11036): We are being permissive for this DCHECK, but // TODO(jgruber,v8:11036): We are being permissive for this DCHECK, but
// consider using raw_instruction_size() instead of raw_body_size() in the // consider using raw_instruction_size() instead of raw_body_size() in the
// future. // future.
STATIC_ASSERT(Code::kOnHeapBodyIsContiguous);
DCHECK_LE(target_offset, Handle<Code>::cast(object_)->raw_body_size()); DCHECK_LE(target_offset, Handle<Code>::cast(object_)->raw_body_size());
sink_->Put(kInternalReference, "InternalRef"); sink_->Put(kInternalReference, "InternalRef");
sink_->PutInt(target_offset, "internal ref value"); sink_->PutInt(target_offset, "internal ref value");
......
...@@ -878,11 +878,7 @@ CompilationEnv NativeModule::CreateCompilationEnv() const { ...@@ -878,11 +878,7 @@ CompilationEnv NativeModule::CreateCompilationEnv() const {
WasmCode* NativeModule::AddCodeForTesting(Handle<Code> code) { WasmCode* NativeModule::AddCodeForTesting(Handle<Code> code) {
CODE_SPACE_WRITE_SCOPE CODE_SPACE_WRITE_SCOPE
// For off-heap builtins, we create a copy of the off-heap instruction stream const size_t relocation_size = code->relocation_size();
// instead of the on-heap code object containing the trampoline. Ensure that
// we do not apply the on-heap reloc info to the off-heap instructions.
const size_t relocation_size =
code->is_off_heap_trampoline() ? 0 : code->relocation_size();
OwnedVector<byte> reloc_info; OwnedVector<byte> reloc_info;
if (relocation_size > 0) { if (relocation_size > 0) {
reloc_info = OwnedVector<byte>::Of( reloc_info = OwnedVector<byte>::Of(
...@@ -896,14 +892,16 @@ WasmCode* NativeModule::AddCodeForTesting(Handle<Code> code) { ...@@ -896,14 +892,16 @@ WasmCode* NativeModule::AddCodeForTesting(Handle<Code> code) {
source_pos_table->copy_out(0, source_pos.start(), source_pos_table->copy_out(0, source_pos.start(),
source_pos_table->length()); source_pos_table->length());
} }
STATIC_ASSERT(Code::kBodyIsContiguous); CHECK(!code->is_off_heap_trampoline());
Vector<const byte> instructions(reinterpret_cast<byte*>(code->BodyStart()), STATIC_ASSERT(Code::kOnHeapBodyIsContiguous);
static_cast<size_t>(code->BodySize())); Vector<const byte> instructions(
reinterpret_cast<byte*>(code->raw_body_start()),
static_cast<size_t>(code->raw_body_size()));
const int stack_slots = code->has_safepoint_info() ? code->stack_slots() : 0; const int stack_slots = code->has_safepoint_info() ? code->stack_slots() : 0;
// Metadata offsets in Code objects are relative to the start of the metadata // Metadata offsets in Code objects are relative to the start of the metadata
// section, whereas WasmCode expects offsets relative to InstructionStart. // section, whereas WasmCode expects offsets relative to InstructionStart.
const int base_offset = code->InstructionSize(); const int base_offset = code->raw_instruction_size();
// TODO(jgruber,v8:8758): Remove this translation. It exists only because // TODO(jgruber,v8:8758): Remove this translation. It exists only because
// Code objects contains real offsets but WasmCode expects an offset of 0 to // Code objects contains real offsets but WasmCode expects an offset of 0 to
// mean 'empty'. // mean 'empty'.
...@@ -920,7 +918,7 @@ WasmCode* NativeModule::AddCodeForTesting(Handle<Code> code) { ...@@ -920,7 +918,7 @@ WasmCode* NativeModule::AddCodeForTesting(Handle<Code> code) {
// Apply the relocation delta by iterating over the RelocInfo. // Apply the relocation delta by iterating over the RelocInfo.
intptr_t delta = reinterpret_cast<Address>(dst_code_bytes.begin()) - intptr_t delta = reinterpret_cast<Address>(dst_code_bytes.begin()) -
code->InstructionStart(); code->raw_instruction_start();
int mode_mask = int mode_mask =
RelocInfo::kApplyMask | RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL); RelocInfo::kApplyMask | RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL);
auto jump_tables_ref = auto jump_tables_ref =
......
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