Commit a4449f26 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

Reland "[code] Separate instruction and metadata areas"

This is a reland of b66993bc

Nothing changed in the reland, the original CL was not the
culprit for win32 failures. They started earlier, at
https://ci.chromium.org/p/v8/builders/ci/V8%20Win32/29444

Original change's description:
> [code] Separate instruction and metadata areas
>
> In this CL, Code object layout changes s.t. the instruction
> area is distinct / non-overlapping from the metadata area.
>
> On-heap Code objects now have a variable-size `body` area,
> containing distinct-but-adjacent `instruction` and `metadata`
> areas.
>
> Off-heap code (= embedded builtins) currently have the same,
> but in the future the metadata area will move elsewhere and
> no longer be adjacent to instructions.
>
> To implement this, the main changes are:
>
>  - The Code object header now contains instruction and metadata
>    sizes, and no longer contains the safepoint table offset
>    (it's implicitly the first table of the metadata section).
>  - The embedded metadata table contains information about both
>    instruction and metadata areas.
>
> I've also added assertions in spots that currently rely on a
> contiguous body area.
>
> Bug: v8:11036
> Change-Id: I940f0c70c07ad511dafd2d2c3e337de8c92cd4b9
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2491025
> Reviewed-by: Leszek Swirski <leszeks@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Dominik Inführ <dinfuehr@chromium.org>
> Commit-Queue: Jakob Gruber <jgruber@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#70743}

No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Tbr: leszeks@chromium.org, clemensb@chromium.org, dinfuehr@chromium.org
Bug: v8:11036
Change-Id: I238562d7e25cf28cc689856ee8b17f25627aaee7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2497162
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Auto-Submit: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70747}
parent bc0d7e6c
...@@ -257,8 +257,8 @@ void SetupIsolateDelegate::ReplacePlaceholders(Isolate* isolate) { ...@@ -257,8 +257,8 @@ void SetupIsolateDelegate::ReplacePlaceholders(Isolate* isolate) {
flush_icache = true; flush_icache = true;
} }
if (flush_icache) { if (flush_icache) {
FlushInstructionCache(code.raw_instruction_start_future(), FlushInstructionCache(code.raw_instruction_start(),
code.raw_instruction_size_future()); code.raw_instruction_size());
} }
} }
} }
......
...@@ -62,6 +62,12 @@ class CodeDesc { ...@@ -62,6 +62,12 @@ class CodeDesc {
int code_comments_offset = 0; int code_comments_offset = 0;
int code_comments_size = 0; int code_comments_size = 0;
// TODO(jgruber,v8:11036): Remove these functions once CodeDesc fields have
// been made consistent with Code layout.
int body_size() const { return instr_size + unwinding_info_size; }
int instruction_size() const { return safepoint_table_offset; }
int metadata_size() const { return body_size() - instruction_size(); }
// Relocation info is located at the end of the buffer and not part of the // Relocation info is located at the end of the buffer and not part of the
// instructions area. // instructions area.
......
...@@ -386,10 +386,12 @@ size_t Isolate::HashIsolateForEmbeddedBlob() { ...@@ -386,10 +386,12 @@ size_t Isolate::HashIsolateForEmbeddedBlob() {
reinterpret_cast<uint8_t*>(code.ptr() - kHeapObjectTag); reinterpret_cast<uint8_t*>(code.ptr() - kHeapObjectTag);
// These static asserts ensure we don't miss relevant fields. We don't hash // These static asserts ensure we don't miss relevant fields. We don't hash
// instruction size and flags since they change when creating the off-heap // instruction/metadata size and flags since they change when creating the
// trampolines. Other data fields must remain the same. // off-heap trampolines. Other data fields must remain the same.
STATIC_ASSERT(Code::kInstructionSizeOffset == Code::kDataStart); STATIC_ASSERT(Code::kInstructionSizeOffset == Code::kDataStart);
STATIC_ASSERT(Code::kFlagsOffset == Code::kInstructionSizeOffsetEnd + 1); STATIC_ASSERT(Code::kMetadataSizeOffset ==
Code::kInstructionSizeOffsetEnd + 1);
STATIC_ASSERT(Code::kFlagsOffset == Code::kMetadataSizeOffsetEnd + 1);
STATIC_ASSERT(Code::kBuiltinIndexOffset == Code::kFlagsOffsetEnd + 1); STATIC_ASSERT(Code::kBuiltinIndexOffset == Code::kFlagsOffsetEnd + 1);
static constexpr int kStartOffset = Code::kBuiltinIndexOffset; static constexpr int kStartOffset = Code::kBuiltinIndexOffset;
......
...@@ -212,9 +212,7 @@ void CodeStatistics::CollectCodeCommentStatistics(HeapObject obj, ...@@ -212,9 +212,7 @@ void CodeStatistics::CollectCodeCommentStatistics(HeapObject obj,
cit.Next(); cit.Next();
} }
// TODO(jgruber,v8:11036): Revisit this when separating instruction- and STATIC_ASSERT(Code::kBodyIsContiguous);
// metadata areas. The logic will become a bit more complex since these areas
// will no longer be adjacent in some cases.
DCHECK(0 <= prev_pc_offset && prev_pc_offset <= code.raw_body_size()); DCHECK(0 <= prev_pc_offset && prev_pc_offset <= code.raw_body_size());
delta += static_cast<int>(code.raw_body_size() - prev_pc_offset); delta += static_cast<int>(code.raw_body_size() - prev_pc_offset);
EnterComment(isolate, "NoComment", delta); EnterComment(isolate, "NoComment", delta);
......
...@@ -120,8 +120,8 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal( ...@@ -120,8 +120,8 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal(
} }
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas. // TODO(jgruber,v8:11036): Distinguish instruction and metadata areas.
const int body_size = code_desc_.instr_size + code_desc_.unwinding_info_size; STATIC_ASSERT(Code::kOnHeapBodyIsContiguous);
const int object_size = Code::SizeFor(body_size); const int object_size = Code::SizeFor(code_desc_.body_size());
Handle<Code> code; Handle<Code> code;
{ {
...@@ -157,8 +157,8 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal( ...@@ -157,8 +157,8 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal(
constexpr bool kIsNotOffHeapTrampoline = false; constexpr bool kIsNotOffHeapTrampoline = false;
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas. code->set_raw_instruction_size(code_desc_.instruction_size());
code->set_raw_instruction_size(body_size); code->set_raw_metadata_size(code_desc_.metadata_size());
code->set_relocation_info(*reloc_info); code->set_relocation_info(*reloc_info);
code->initialize_flags(kind_, is_turbofanned_, stack_slots_, code->initialize_flags(kind_, is_turbofanned_, stack_slots_,
kIsNotOffHeapTrampoline); kIsNotOffHeapTrampoline);
...@@ -167,7 +167,6 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal( ...@@ -167,7 +167,6 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal(
code->set_code_data_container(*data_container, kReleaseStore); code->set_code_data_container(*data_container, kReleaseStore);
code->set_deoptimization_data(*deoptimization_data_); code->set_deoptimization_data(*deoptimization_data_);
code->set_source_position_table(*source_position_table_); code->set_source_position_table(*source_position_table_);
code->set_safepoint_table_offset(code_desc_.safepoint_table_offset);
code->set_handler_table_offset(code_desc_.handler_table_offset); code->set_handler_table_offset(code_desc_.handler_table_offset);
code->set_constant_pool_offset(code_desc_.constant_pool_offset); code->set_constant_pool_offset(code_desc_.constant_pool_offset);
code->set_code_comments_offset(code_desc_.code_comments_offset); code->set_code_comments_offset(code_desc_.code_comments_offset);
...@@ -2057,6 +2056,11 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code, ...@@ -2057,6 +2056,11 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
isolate(), off_heap_entry, isolate(), off_heap_entry,
code->code_data_container(kAcquireLoad).kind_specific_flags(), code->code_data_container(kAcquireLoad).kind_specific_flags(),
generate_jump_to_instruction_stream); generate_jump_to_instruction_stream);
// Trampolines may not contain any metadata since all metadata offsets,
// stored on the Code object, refer to the off-heap metadata area.
CHECK_EQ(result->raw_metadata_size(), 0);
// The CodeDataContainer should not be modified beyond this point since it's // The CodeDataContainer should not be modified beyond this point since it's
// now possibly canonicalized. // now possibly canonicalized.
...@@ -2071,7 +2075,6 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code, ...@@ -2071,7 +2075,6 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
result->initialize_flags(code->kind(), code->is_turbofanned(), stack_slots, result->initialize_flags(code->kind(), code->is_turbofanned(), stack_slots,
set_is_off_heap_trampoline); set_is_off_heap_trampoline);
result->set_builtin_index(code->builtin_index()); result->set_builtin_index(code->builtin_index());
result->set_safepoint_table_offset(code->safepoint_table_offset());
result->set_handler_table_offset(code->handler_table_offset()); result->set_handler_table_offset(code->handler_table_offset());
result->set_constant_pool_offset(code->constant_pool_offset()); result->set_constant_pool_offset(code->constant_pool_offset());
result->set_code_comments_offset(code->code_comments_offset()); result->set_code_comments_offset(code->code_comments_offset());
......
...@@ -164,7 +164,7 @@ OBJECT_CONSTRUCTORS_IMPL(Code, HeapObject) ...@@ -164,7 +164,7 @@ OBJECT_CONSTRUCTORS_IMPL(Code, HeapObject)
NEVER_READ_ONLY_SPACE_IMPL(Code) NEVER_READ_ONLY_SPACE_IMPL(Code)
INT_ACCESSORS(Code, raw_instruction_size, kInstructionSizeOffset) INT_ACCESSORS(Code, raw_instruction_size, kInstructionSizeOffset)
INT_ACCESSORS(Code, safepoint_table_offset, kSafepointTableOffsetOffset) INT_ACCESSORS(Code, raw_metadata_size, kMetadataSizeOffset)
INT_ACCESSORS(Code, handler_table_offset, kHandlerTableOffsetOffset) INT_ACCESSORS(Code, handler_table_offset, kHandlerTableOffsetOffset)
INT_ACCESSORS(Code, code_comments_offset, kCodeCommentsOffsetOffset) INT_ACCESSORS(Code, code_comments_offset, kCodeCommentsOffsetOffset)
INT32_ACCESSORS(Code, unwinding_info_offset, kUnwindingInfoOffsetOffset) INT32_ACCESSORS(Code, unwinding_info_offset, kUnwindingInfoOffsetOffset)
...@@ -222,18 +222,30 @@ void Code::set_next_code_link(Object value) { ...@@ -222,18 +222,30 @@ 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::raw_body_end() const { return raw_instruction_end(); } Address Code::BodyStart() const {
STATIC_ASSERT(kBodyIsContiguous);
return InstructionStart();
}
Address Code::raw_body_end() const {
return raw_body_start() + raw_body_size();
}
int Code::raw_body_size() const { int Code::raw_body_size() const {
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas. return raw_instruction_size() + raw_metadata_size();
DCHECK_EQ(unwinding_info_offset() + unwinding_info_size(), InstructionSize()); }
return raw_instruction_size();
Address Code::BodyEnd() const {
STATIC_ASSERT(kBodyIsContiguous);
return MetadataEnd();
} }
int Code::BodySize() const { int Code::BodySize() const {
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas. // TODO(jgruber,v8:11036): Update once embedded instructions and metadata are
DCHECK_EQ(unwinding_info_offset() + unwinding_info_size(), InstructionSize()); // separate.
return InstructionSize(); return V8_UNLIKELY(is_off_heap_trampoline())
? OffHeapInstructionSize() + OffHeapMetadataSize()
: raw_body_size();
} }
int Code::InstructionSize() const { int Code::InstructionSize() const {
...@@ -259,27 +271,37 @@ Address Code::InstructionEnd() const { ...@@ -259,27 +271,37 @@ Address Code::InstructionEnd() const {
: raw_instruction_end(); : raw_instruction_end();
} }
Address Code::raw_instruction_start_future() const { Address Code::raw_metadata_start() const {
return raw_instruction_start(); return raw_instruction_start() + raw_instruction_size();
} }
Address Code::raw_instruction_end_future() const { Address Code::MetadataStart() const {
return raw_metadata_start(); STATIC_ASSERT(kBodyIsContiguous);
return V8_UNLIKELY(is_off_heap_trampoline()) ? OffHeapMetadataStart()
: raw_metadata_start();
} }
int Code::raw_instruction_size_future() const { Address Code::raw_metadata_end() const {
return raw_instruction_size() - raw_metadata_size(); return raw_metadata_start() + raw_metadata_size();
} }
Address Code::raw_metadata_start() const { Address Code::MetadataEnd() const {
return raw_instruction_start() + safepoint_table_offset(); STATIC_ASSERT(kBodyIsContiguous);
return V8_UNLIKELY(is_off_heap_trampoline()) ? OffHeapMetadataEnd()
: raw_metadata_end();
} }
Address Code::raw_metadata_end() const { return raw_instruction_end(); } int Code::MetadataSize() const {
STATIC_ASSERT(kBodyIsContiguous);
return V8_UNLIKELY(is_off_heap_trampoline()) ? OffHeapMetadataSize()
: raw_metadata_size();
}
int Code::raw_metadata_size() const { int Code::safepoint_table_offset() const {
DCHECK_LE(raw_metadata_start(), raw_metadata_end()); // TODO(jgruber,v8:11036): Update once embedded instructions and metadata are
return static_cast<int>(raw_metadata_end() - raw_metadata_start()); // separate.
STATIC_ASSERT(kBodyIsContiguous);
return InstructionSize();
} }
int Code::SizeIncludingMetadata() const { int Code::SizeIncludingMetadata() const {
...@@ -555,7 +577,7 @@ Address Code::unwinding_info_start() const { ...@@ -555,7 +577,7 @@ Address Code::unwinding_info_start() const {
return InstructionStart() + unwinding_info_offset(); return InstructionStart() + unwinding_info_offset();
} }
Address Code::unwinding_info_end() const { return InstructionEnd(); } Address Code::unwinding_info_end() const { return MetadataEnd(); }
int Code::unwinding_info_size() const { int Code::unwinding_info_size() const {
DCHECK_GE(unwinding_info_end(), unwinding_info_start()); DCHECK_GE(unwinding_info_end(), unwinding_info_start());
......
...@@ -88,14 +88,13 @@ void Code::Relocate(intptr_t delta) { ...@@ -88,14 +88,13 @@ void Code::Relocate(intptr_t delta) {
} }
void Code::FlushICache() const { void Code::FlushICache() const {
// TODO(jgruber,v8:11036): This should likely flush only actual instructions,
// not metadata.
FlushInstructionCache(raw_instruction_start(), raw_instruction_size()); FlushInstructionCache(raw_instruction_start(), raw_instruction_size());
} }
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. // TODO(jgruber,v8:11036): Distinguish instruction and metadata areas.
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));
// TODO(jgruber,v8:11036): Merge with the above. // TODO(jgruber,v8:11036): Merge with the above.
...@@ -140,29 +139,60 @@ SafepointEntry Code::GetSafepointEntry(Address pc) { ...@@ -140,29 +139,60 @@ SafepointEntry Code::GetSafepointEntry(Address pc) {
int Code::OffHeapInstructionSize() const { int Code::OffHeapInstructionSize() const {
DCHECK(is_off_heap_trampoline()); DCHECK(is_off_heap_trampoline());
if (Isolate::CurrentEmbeddedBlobCode() == nullptr) if (Isolate::CurrentEmbeddedBlobCode() == nullptr) {
return raw_instruction_size(); return raw_instruction_size();
}
EmbeddedData d = EmbeddedData::FromBlob(); EmbeddedData d = EmbeddedData::FromBlob();
return d.InstructionSizeOfBuiltin(builtin_index()); return d.InstructionSizeOfBuiltin(builtin_index());
} }
Address Code::OffHeapInstructionStart() const { Address Code::OffHeapInstructionStart() const {
DCHECK(is_off_heap_trampoline()); DCHECK(is_off_heap_trampoline());
if (Isolate::CurrentEmbeddedBlobCode() == nullptr) if (Isolate::CurrentEmbeddedBlobCode() == nullptr) {
return raw_instruction_start(); return raw_instruction_size();
}
EmbeddedData d = EmbeddedData::FromBlob(); EmbeddedData d = EmbeddedData::FromBlob();
return d.InstructionStartOfBuiltin(builtin_index()); return d.InstructionStartOfBuiltin(builtin_index());
} }
Address Code::OffHeapInstructionEnd() const { Address Code::OffHeapInstructionEnd() const {
DCHECK(is_off_heap_trampoline()); DCHECK(is_off_heap_trampoline());
if (Isolate::CurrentEmbeddedBlobCode() == nullptr) if (Isolate::CurrentEmbeddedBlobCode() == nullptr) {
return raw_instruction_end(); return raw_instruction_size();
}
EmbeddedData d = EmbeddedData::FromBlob(); EmbeddedData d = EmbeddedData::FromBlob();
return d.InstructionStartOfBuiltin(builtin_index()) + return d.InstructionStartOfBuiltin(builtin_index()) +
d.InstructionSizeOfBuiltin(builtin_index()); d.InstructionSizeOfBuiltin(builtin_index());
} }
int Code::OffHeapMetadataSize() const {
DCHECK(is_off_heap_trampoline());
if (Isolate::CurrentEmbeddedBlobCode() == nullptr) {
return raw_instruction_size();
}
EmbeddedData d = EmbeddedData::FromBlob();
return d.MetadataSizeOfBuiltin(builtin_index());
}
Address Code::OffHeapMetadataStart() const {
DCHECK(is_off_heap_trampoline());
if (Isolate::CurrentEmbeddedBlobCode() == nullptr) {
return raw_instruction_size();
}
EmbeddedData d = EmbeddedData::FromBlob();
return d.MetadataStartOfBuiltin(builtin_index());
}
Address Code::OffHeapMetadataEnd() const {
DCHECK(is_off_heap_trampoline());
if (Isolate::CurrentEmbeddedBlobCode() == nullptr) {
return raw_instruction_size();
}
EmbeddedData d = EmbeddedData::FromBlob();
return d.MetadataStartOfBuiltin(builtin_index()) +
d.MetadataSizeOfBuiltin(builtin_index());
}
int AbstractCode::SourcePosition(int offset) { int AbstractCode::SourcePosition(int offset) {
Object maybe_table = source_position_table(); Object maybe_table = source_position_table();
if (maybe_table.IsException()) return kNoSourcePosition; if (maybe_table.IsException()) return kNoSourcePosition;
......
...@@ -83,45 +83,45 @@ class Code : public HeapObject { ...@@ -83,45 +83,45 @@ class Code : public HeapObject {
// +--------------------------+ // +--------------------------+
// | header | // | header |
// | padded to code alignment | // | padded to code alignment |
// +--------------------------+ <-- raw_instruction_start() (= IS) // +--------------------------+ <-- raw_body_start()
// | instructions | // | instructions | == raw_instruction_start() (IS)
// | ... | // | ... |
// +--------------------------+ <-- raw_metadata_start() // +--------------------------+ <-- raw_instruction_end()
// | metadata | // | metadata | == raw_metadata_start()
// | ... | == IS + safepoint_table_offset() // | ... | == IS + safepoint_table_offset()
// | |
// | | <-- IS + handler_table_offset() // | | <-- IS + handler_table_offset()
// | | <-- IS + constant_pool_offset() // | | <-- IS + constant_pool_offset()
// | | <-- IS + code_comments_offset() // | | <-- IS + code_comments_offset()
// | | <-- IS + unwinding_info_offset() // | | <-- IS + unwinding_info_offset()
// | padded to obj alignment | // | padded to obj alignment |
// +--------------------------+ <-- raw_metadata_end() // +--------------------------+ <-- raw_metadata_end() == raw_body_end()
// | | == raw_instruction_end()
// | padded to code alignment | // | padded to code alignment |
// +--------------------------+ // +--------------------------+
// //
// In other words, the variable-size 'body' consists of 'instructions' and // In other words, the variable-size 'body' consists of 'instructions' and
// 'metadata'. Both are currently inside [InstructionStart,InstructionEnd[. // 'metadata'.
// //
// Note the accessor functions below may be prefixed with 'raw'. In this case, // Note the accessor functions below may be prefixed with 'raw'. In this case,
// raw accessors (e.g. raw_instruction_start) always refer to the on-heap // raw accessors (e.g. raw_instruction_start) always refer to the on-heap
// Code object, while camel-case accessors (e.g. InstructionStart) may refer // Code object, while camel-case accessors (e.g. InstructionStart) may refer
// to an off-heap area in the case of embedded builtins. // to an off-heap area in the case of embedded builtins.
// TODO(jgruber,v8:11036): Update once no longer true for embedded builtins.
static constexpr bool kOnHeapBodyIsContiguous = true;
static constexpr bool kOffHeapBodyIsContiguous = true;
static constexpr bool kBodyIsContiguous =
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 // TODO(jgruber,v8:11036): Replace this once the off-heap instruction and
// metadata areas are separate. // metadata areas are separate.
inline int BodySize() const; inline int BodySize() const;
// TODO(jgruber,v8:11036): Shrink the instructions area to contain only
// instructions. Until that happens, the state of the world is:
//
// raw_body_start == raw_instruction_start
// raw_metadata_start == raw_instruction_start + safepoint_table_offset
// raw_body_end == raw_instruction_end == raw_metadata_end
inline Address raw_instruction_start() const; inline Address raw_instruction_start() const;
inline Address InstructionStart() const; inline Address InstructionStart() const;
V8_EXPORT_PRIVATE Address OffHeapInstructionStart() const; V8_EXPORT_PRIVATE Address OffHeapInstructionStart() const;
...@@ -135,21 +135,23 @@ class Code : public HeapObject { ...@@ -135,21 +135,23 @@ class Code : public HeapObject {
inline int InstructionSize() const; inline int InstructionSize() const;
V8_EXPORT_PRIVATE int OffHeapInstructionSize() const; V8_EXPORT_PRIVATE int OffHeapInstructionSize() const;
// TODO(jgruber,v8:11036): Replace legacy accessors with these _future
// accessors. The _future accessors only refer to the range of executable
// instructions, *without* metadata tables.
inline Address raw_instruction_start_future() const;
inline Address raw_instruction_end_future() const;
inline int raw_instruction_size_future() const;
inline Address raw_metadata_start() const; inline Address raw_metadata_start() const;
inline Address MetadataStart() const;
Address OffHeapMetadataStart() const;
inline Address raw_metadata_end() const; inline Address raw_metadata_end() const;
inline Address MetadataEnd() const;
V8_EXPORT_PRIVATE Address OffHeapMetadataEnd() const;
inline int raw_metadata_size() const; inline int raw_metadata_size() const;
inline void set_raw_metadata_size(int value);
inline int MetadataSize() const;
int OffHeapMetadataSize() const;
// TODO(jgruber,v8:11036): Change all these offsets to be relative to
// MetadataStart instead of InstructionStart.
// [safepoint_table_offset]: If {has_safepoint_info()}, the offset in the // [safepoint_table_offset]: If {has_safepoint_info()}, the offset in the
// instruction stream where the safepoint table starts. // instruction stream where the safepoint table starts.
inline int safepoint_table_offset() const; inline int safepoint_table_offset() const;
inline void set_safepoint_table_offset(int offset);
Address SafepointTableAddress() const; Address SafepointTableAddress() const;
int safepoint_table_size() const; int safepoint_table_size() const;
bool has_safepoint_table() const; bool has_safepoint_table() const;
...@@ -413,11 +415,12 @@ class Code : public HeapObject { ...@@ -413,11 +415,12 @@ class Code : public HeapObject {
/* Objects embedded into code is visited via reloc info. */ \ /* Objects embedded into code is visited via reloc info. */ \
V(kDataStart, 0) \ V(kDataStart, 0) \
V(kInstructionSizeOffset, kIntSize) \ V(kInstructionSizeOffset, kIntSize) \
V(kMetadataSizeOffset, kIntSize) \
V(kFlagsOffset, kInt32Size) \ V(kFlagsOffset, kInt32Size) \
V(kBuiltinIndexOffset, kIntSize) \ V(kBuiltinIndexOffset, kIntSize) \
V(kInlinedBytecodeSizeOffset, kIntSize) \ V(kInlinedBytecodeSizeOffset, kIntSize) \
/* Offsets describing inline metadata tables. */ \ /* Offsets describing inline metadata tables, relative to */ \
V(kSafepointTableOffsetOffset, kIntSize) \ /* InstructionStart. */ \
V(kHandlerTableOffsetOffset, kIntSize) \ V(kHandlerTableOffsetOffset, kIntSize) \
V(kConstantPoolOffsetOffset, \ V(kConstantPoolOffsetOffset, \
FLAG_enable_embedded_constant_pool ? kIntSize : 0) \ FLAG_enable_embedded_constant_pool ? kIntSize : 0) \
......
...@@ -172,7 +172,7 @@ int NativeRegExpMacroAssembler::CheckStackGuardState( ...@@ -172,7 +172,7 @@ int NativeRegExpMacroAssembler::CheckStackGuardState(
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
Address old_pc = PointerAuthentication::AuthenticatePC(return_address, 0); Address old_pc = PointerAuthentication::AuthenticatePC(return_address, 0);
DCHECK_LE(re_code.raw_instruction_start(), old_pc); DCHECK_LE(re_code.raw_instruction_start(), old_pc);
DCHECK_LE(old_pc, re_code.raw_instruction_end_future()); DCHECK_LE(old_pc, re_code.raw_instruction_end());
StackLimitCheck check(isolate); StackLimitCheck check(isolate);
bool js_has_overflowed = check.JsHasOverflowed(); bool js_has_overflowed = check.JsHasOverflowed();
......
...@@ -224,11 +224,16 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) { ...@@ -224,11 +224,16 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
Builtins::name(i)); Builtins::name(i));
} }
uint32_t length = static_cast<uint32_t>(code.raw_body_size()); uint32_t instruction_size =
static_cast<uint32_t>(code.raw_instruction_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);
metadata[i].instructions_offset = raw_code_size; metadata[i].instruction_offset = raw_code_size;
metadata[i].instructions_length = length; metadata[i].instruction_length = instruction_size;
metadata[i].metadata_offset = raw_code_size + instruction_size;
metadata[i].metadata_length = metadata_size;
// Align the start of each instruction stream. // Align the start of each instruction stream.
raw_code_size += PadAndAlign(length); raw_code_size += PadAndAlign(length);
...@@ -265,8 +270,9 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) { ...@@ -265,8 +270,9 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
// Write the raw data section. // Write the raw data section.
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 = metadata[i].instructions_offset; uint32_t offset = metadata[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_body_size(), blob_code_size);
std::memcpy(dst, reinterpret_cast<uint8_t*>(code.raw_body_start()), std::memcpy(dst, reinterpret_cast<uint8_t*>(code.raw_body_start()),
...@@ -297,17 +303,30 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) { ...@@ -297,17 +303,30 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
Address EmbeddedData::InstructionStartOfBuiltin(int i) const { Address EmbeddedData::InstructionStartOfBuiltin(int i) const {
DCHECK(Builtins::IsBuiltinId(i)); DCHECK(Builtins::IsBuiltinId(i));
const struct Metadata* metadata = Metadata(); const struct Metadata* metadata = Metadata();
const uint8_t* result = RawCode() + metadata[i].instructions_offset; const uint8_t* result = RawCode() + metadata[i].instruction_offset;
DCHECK_LE(result, code_ + code_size_); DCHECK_LT(result, code_ + code_size_);
DCHECK_IMPLIES(result == code_ + code_size_,
InstructionSizeOfBuiltin(i) == 0);
return reinterpret_cast<Address>(result); return reinterpret_cast<Address>(result);
} }
uint32_t EmbeddedData::InstructionSizeOfBuiltin(int i) const { uint32_t EmbeddedData::InstructionSizeOfBuiltin(int i) const {
DCHECK(Builtins::IsBuiltinId(i)); DCHECK(Builtins::IsBuiltinId(i));
const struct Metadata* metadata = Metadata(); const struct Metadata* metadata = Metadata();
return metadata[i].instructions_length; return metadata[i].instruction_length;
}
Address EmbeddedData::MetadataStartOfBuiltin(int i) const {
DCHECK(Builtins::IsBuiltinId(i));
STATIC_ASSERT(Code::kOffHeapBodyIsContiguous);
const struct Metadata* metadata = Metadata();
const uint8_t* result = RawCode() + metadata[i].metadata_offset;
DCHECK_LT(result, code_ + code_size_);
return reinterpret_cast<Address>(result);
}
uint32_t EmbeddedData::MetadataSizeOfBuiltin(int i) const {
DCHECK(Builtins::IsBuiltinId(i));
const struct Metadata* metadata = Metadata();
return metadata[i].metadata_length;
} }
Address EmbeddedData::InstructionStartOfBytecodeHandlers() const { Address EmbeddedData::InstructionStartOfBytecodeHandlers() const {
......
...@@ -75,7 +75,8 @@ class EmbeddedData final { ...@@ -75,7 +75,8 @@ class EmbeddedData final {
Address InstructionStartOfBytecodeHandlers() const; Address InstructionStartOfBytecodeHandlers() const;
Address InstructionEndOfBytecodeHandlers() const; Address InstructionEndOfBytecodeHandlers() const;
bool ContainsBuiltin(int i) const { return InstructionSizeOfBuiltin(i) > 0; } Address MetadataStartOfBuiltin(int i) const;
uint32_t MetadataSizeOfBuiltin(int i) const;
uint32_t AddressForHashing(Address addr) { uint32_t AddressForHashing(Address addr) {
Address start = reinterpret_cast<Address>(code_); Address start = reinterpret_cast<Address>(code_);
...@@ -84,9 +85,12 @@ class EmbeddedData final { ...@@ -84,9 +85,12 @@ class EmbeddedData final {
} }
// Padded with kCodeAlignment. // Padded with kCodeAlignment.
// TODO(v8:11045): Consider removing code alignment.
uint32_t PaddedInstructionSizeOfBuiltin(int i) const { uint32_t PaddedInstructionSizeOfBuiltin(int i) const {
uint32_t size = InstructionSizeOfBuiltin(i); STATIC_ASSERT(Code::kOffHeapBodyIsContiguous);
return (size == 0) ? 0 : PadAndAlign(size); uint32_t size = InstructionSizeOfBuiltin(i) + MetadataSizeOfBuiltin(i);
CHECK_NE(size, 0);
return PadAndAlign(size);
} }
size_t CreateEmbeddedBlobHash() const; size_t CreateEmbeddedBlobHash() const;
...@@ -99,14 +103,28 @@ class EmbeddedData final { ...@@ -99,14 +103,28 @@ class EmbeddedData final {
return *reinterpret_cast<const size_t*>(metadata_ + IsolateHashOffset()); return *reinterpret_cast<const size_t*>(metadata_ + IsolateHashOffset());
} }
// Blob layout information for a single instruction stream. Corresponds
// roughly to Code object layout (see the instruction and metadata area).
// TODO(jgruber): With the addition of metadata sections in Code objects,
// naming here has become confusing. Metadata refers to both this struct
// and the Code section, and the embedded instruction area currently
// contains both Code's instruction and metadata areas. Fix it.
struct Metadata { struct Metadata {
// Blob layout information. // The offset and (unpadded) length of this builtin's instruction area
uint32_t instructions_offset; // from the start of the embedded code section.
uint32_t instructions_length; uint32_t instruction_offset;
uint32_t instruction_length;
// The offset and (unpadded) length of this builtin's metadata area
// from the start of the embedded code section.
// TODO(jgruber,v8:11036): Move this to the embedded metadata area.
uint32_t metadata_offset;
uint32_t metadata_length;
}; };
STATIC_ASSERT(offsetof(Metadata, instructions_offset) == 0); STATIC_ASSERT(offsetof(Metadata, instruction_offset) == 0 * kUInt32Size);
STATIC_ASSERT(offsetof(Metadata, instructions_length) == kUInt32Size); STATIC_ASSERT(offsetof(Metadata, instruction_length) == 1 * kUInt32Size);
STATIC_ASSERT(sizeof(Metadata) == kUInt32Size + kUInt32Size); STATIC_ASSERT(offsetof(Metadata, metadata_offset) == 2 * kUInt32Size);
STATIC_ASSERT(offsetof(Metadata, metadata_length) == 3 * kUInt32Size);
STATIC_ASSERT(sizeof(Metadata) == 4 * kUInt32Size);
// The layout of the blob is as follows: // The layout of the blob is as follows:
// //
......
...@@ -156,8 +156,8 @@ void EmbeddedFileWriter::WriteInstructionStreams( ...@@ -156,8 +156,8 @@ void EmbeddedFileWriter::WriteInstructionStreams(
w->AlignToCodeAlignment(); w->AlignToCodeAlignment();
w->DeclareLabel(EmbeddedBlobCodeDataSymbol().c_str()); w->DeclareLabel(EmbeddedBlobCodeDataSymbol().c_str());
STATIC_ASSERT(Builtins::kAllBuiltinsAreIsolateIndependent);
for (int i = 0; i < i::Builtins::builtin_count; i++) { for (int i = 0; i < i::Builtins::builtin_count; i++) {
if (!blob->ContainsBuiltin(i)) continue;
WriteBuiltin(w, blob, i); WriteBuiltin(w, blob, i);
} }
w->Newline(); w->Newline();
......
...@@ -109,12 +109,12 @@ void EmitUnwindData(PlatformEmbeddedFileWriterWin* w, ...@@ -109,12 +109,12 @@ void EmitUnwindData(PlatformEmbeddedFileWriterWin* w,
w->Comment(" UnwindInfoAddress"); w->Comment(" UnwindInfoAddress");
w->StartPdataSection(); w->StartPdataSection();
{ {
STATIC_ASSERT(Builtins::kAllBuiltinsAreIsolateIndependent);
Address prev_builtin_end_offset = 0; Address prev_builtin_end_offset = 0;
for (int i = 0; i < Builtins::builtin_count; i++) { for (int i = 0; i < Builtins::builtin_count; i++) {
// Some builtins are leaf functions from the point of view of Win64 stack // Some builtins are leaf functions from the point of view of Win64 stack
// walking: they do not move the stack pointer and do not require a PDATA // walking: they do not move the stack pointer and do not require a PDATA
// entry because the return address can be retrieved from [rsp]. // entry because the return address can be retrieved from [rsp].
if (!blob->ContainsBuiltin(i)) continue;
if (unwind_infos[i].is_leaf_function()) continue; if (unwind_infos[i].is_leaf_function()) continue;
uint64_t builtin_start_offset = blob->InstructionStartOfBuiltin(i) - uint64_t builtin_start_offset = blob->InstructionStartOfBuiltin(i) -
...@@ -193,8 +193,8 @@ void EmitUnwindData(PlatformEmbeddedFileWriterWin* w, ...@@ -193,8 +193,8 @@ void EmitUnwindData(PlatformEmbeddedFileWriterWin* w,
std::vector<int> code_chunks; std::vector<int> code_chunks;
std::vector<win64_unwindinfo::FrameOffsets> fp_adjustments; std::vector<win64_unwindinfo::FrameOffsets> fp_adjustments;
STATIC_ASSERT(Builtins::kAllBuiltinsAreIsolateIndependent);
for (int i = 0; i < Builtins::builtin_count; i++) { for (int i = 0; i < Builtins::builtin_count; i++) {
if (!blob->ContainsBuiltin(i)) continue;
if (unwind_infos[i].is_leaf_function()) continue; if (unwind_infos[i].is_leaf_function()) continue;
uint64_t builtin_start_offset = blob->InstructionStartOfBuiltin(i) - uint64_t builtin_start_offset = blob->InstructionStartOfBuiltin(i) -
......
...@@ -896,9 +896,9 @@ WasmCode* NativeModule::AddCodeForTesting(Handle<Code> code) { ...@@ -896,9 +896,9 @@ 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());
} }
Vector<const byte> instructions( STATIC_ASSERT(Code::kBodyIsContiguous);
reinterpret_cast<byte*>(code->InstructionStart()), Vector<const byte> instructions(reinterpret_cast<byte*>(code->BodyStart()),
static_cast<size_t>(code->InstructionSize())); static_cast<size_t>(code->BodySize()));
const int stack_slots = code->has_safepoint_info() ? code->stack_slots() : 0; const int stack_slots = code->has_safepoint_info() ? code->stack_slots() : 0;
// TODO(jgruber,v8:8758): Remove this translation. It exists only because // TODO(jgruber,v8:8758): Remove this translation. It exists only because
...@@ -1370,10 +1370,10 @@ void NativeModule::AddCodeSpace( ...@@ -1370,10 +1370,10 @@ void NativeModule::AddCodeSpace(
WASM_RUNTIME_STUB_LIST(RUNTIME_STUB, RUNTIME_STUB_TRAP)}; WASM_RUNTIME_STUB_LIST(RUNTIME_STUB, RUNTIME_STUB_TRAP)};
#undef RUNTIME_STUB #undef RUNTIME_STUB
#undef RUNTIME_STUB_TRAP #undef RUNTIME_STUB_TRAP
STATIC_ASSERT(Builtins::kAllBuiltinsAreIsolateIndependent);
Address builtin_addresses[WasmCode::kRuntimeStubCount]; Address builtin_addresses[WasmCode::kRuntimeStubCount];
for (int i = 0; i < WasmCode::kRuntimeStubCount; ++i) { for (int i = 0; i < WasmCode::kRuntimeStubCount; ++i) {
Builtins::Name builtin = stub_names[i]; Builtins::Name builtin = stub_names[i];
CHECK(embedded_data.ContainsBuiltin(builtin));
builtin_addresses[i] = embedded_data.InstructionStartOfBuiltin(builtin); builtin_addresses[i] = embedded_data.InstructionStartOfBuiltin(builtin);
} }
JumpTableAssembler::GenerateFarJumpTable( JumpTableAssembler::GenerateFarJumpTable(
......
...@@ -91,7 +91,7 @@ TEST(CodeLayoutWithUnwindingInfo) { ...@@ -91,7 +91,7 @@ TEST(CodeLayoutWithUnwindingInfo) {
.Build(); .Build();
CHECK(code->has_unwinding_info()); CHECK(code->has_unwinding_info());
CHECK_EQ(code->raw_instruction_size(), buffer_size + unwinding_info_size); CHECK_EQ(code->raw_body_size(), buffer_size + unwinding_info_size);
CHECK_EQ(0, memcmp(reinterpret_cast<void*>(code->raw_instruction_start()), CHECK_EQ(0, memcmp(reinterpret_cast<void*>(code->raw_instruction_start()),
buffer, buffer_size)); buffer, buffer_size));
CHECK_EQ(code->unwinding_info_size(), unwinding_info_size); CHECK_EQ(code->unwinding_info_size(), unwinding_info_size);
......
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