[code] Move the unwinding info into metadata area
Semantically, the unwinding info is a variable-size metadata table with untagged (i.e. no relocation needed) contents, packed inside Code objects. This is just like other metadata tables (safepoint table, handler table, constant pool, code comments); but for historical reasons it's been treated differently so far. Unlike these other tables, the unwinding info was located *after* InstructionEnd, and its size was written to the first 8 bytes after InstructionEnd. This CL makes unwinding info handling more consistent with other metadata tables by writing its offset into a dedicated kUnwindingInfoOffsetOffset header slot, and by moving the actual data inside the [InstructionStart,InstructionEnd[ area. In follow-up CLs, this area will be split into dedicated instruction- and metadata areas. A picture is worth 1000 words, before: +--------------------------+ <-- raw_instruction_start() | instructions | | ... | +--------------------------+ | embedded metadata | <-- safepoint_table_offset() | ... | <-- handler_table_offset() | | <-- constant_pool_offset() | | <-- code_comments_offset() | padding to the next | | 8-byte aligned address | +--------------------------+ <-- raw_instruction_end() | [unwinding_info_size] | | as uint64_t | +--------------------------+ <-- unwinding_info_start() | unwinding info | | ... | +--------------------------+ <-- unwinding_info_end() After: +--------------------------+ <-- raw_instruction_start() | instructions | | ... | +--------------------------+ | embedded metadata | <-- safepoint_table_offset() | ... | <-- handler_table_offset() | | <-- constant_pool_offset() | | <-- code_comments_offset() | | <-- unwinding_info_offset() | | +--------------------------+ <-- raw_instruction_end() Bug: v8:11036 Change-Id: I649708821acc5365186ca2c9cff2669fc3e91fd3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2484795 Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#70640}
This commit is contained in:
parent
fe1c9190f4
commit
c5379162dc
@ -16,11 +16,11 @@ namespace internal {
|
||||
// the buffer and grows backward. Inlined metadata sections may exist
|
||||
// at the end of the instructions.
|
||||
//
|
||||
// │<--------------- buffer_size ----------------------------------->│
|
||||
// │<---------------- instr_size ------------->│ │<-reloc_size->│
|
||||
// ├───────────────────────────────────────────┼──────┼──────────────┤
|
||||
// │ instructions │ data │ free │ reloc info │
|
||||
// ├───────────────────────────────────────────┴──────┴──────────────┘
|
||||
// |<--------------- buffer_size ----------------------------------->|
|
||||
// |<---------------- instr_size ------------->| |<-reloc_size->|
|
||||
// |--------------+----------------------------+------+--------------|
|
||||
// | instructions | data | free | reloc info |
|
||||
// +--------------+----------------------------+------+--------------+
|
||||
|
||||
// TODO(jgruber): Add a single chokepoint for specifying the instruction area
|
||||
// layout (i.e. the order of inlined metadata fields).
|
||||
@ -73,6 +73,11 @@ class CodeDesc {
|
||||
|
||||
byte* unwinding_info = nullptr;
|
||||
int unwinding_info_size = 0;
|
||||
int unwinding_info_offset() const {
|
||||
// TODO(jgruber,v8:11036): Remove this function once unwinding_info setup
|
||||
// is more consistent with other metadata tables.
|
||||
return code_comments_offset + code_comments_size;
|
||||
}
|
||||
|
||||
Assembler* origin = nullptr;
|
||||
};
|
||||
|
@ -390,9 +390,8 @@ size_t Isolate::HashIsolateForEmbeddedBlob() {
|
||||
// trampolines. Other data fields must remain the same.
|
||||
STATIC_ASSERT(Code::kInstructionSizeOffset == Code::kDataStart);
|
||||
STATIC_ASSERT(Code::kFlagsOffset == Code::kInstructionSizeOffsetEnd + 1);
|
||||
STATIC_ASSERT(Code::kSafepointTableOffsetOffset ==
|
||||
Code::kFlagsOffsetEnd + 1);
|
||||
static constexpr int kStartOffset = Code::kSafepointTableOffsetOffset;
|
||||
STATIC_ASSERT(Code::kBuiltinIndexOffset == Code::kFlagsOffsetEnd + 1);
|
||||
static constexpr int kStartOffset = Code::kBuiltinIndexOffset;
|
||||
|
||||
for (int j = kStartOffset; j < Code::kUnalignedHeaderSize; j++) {
|
||||
hash = base::hash_combine(hash, size_t{code_ptr[j]});
|
||||
|
@ -70,16 +70,9 @@ namespace internal {
|
||||
namespace {
|
||||
|
||||
int ComputeCodeObjectSize(const CodeDesc& desc) {
|
||||
bool has_unwinding_info = desc.unwinding_info != nullptr;
|
||||
DCHECK((has_unwinding_info && desc.unwinding_info_size > 0) ||
|
||||
(!has_unwinding_info && desc.unwinding_info_size == 0));
|
||||
int body_size = desc.instr_size;
|
||||
int unwinding_info_size_field_size = kInt64Size;
|
||||
if (has_unwinding_info) {
|
||||
body_size = RoundUp(body_size, kInt64Size) + desc.unwinding_info_size +
|
||||
unwinding_info_size_field_size;
|
||||
}
|
||||
int object_size = Code::SizeFor(RoundUp(body_size, kObjectAlignment));
|
||||
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas.
|
||||
int object_size = Code::SizeFor(
|
||||
Code::AlignedBodySizeFor(desc.instr_size + desc.unwinding_info_size));
|
||||
DCHECK(IsAligned(static_cast<intptr_t>(object_size), kCodeAlignment));
|
||||
return object_size;
|
||||
}
|
||||
@ -172,12 +165,13 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal(
|
||||
}
|
||||
|
||||
constexpr bool kIsNotOffHeapTrampoline = false;
|
||||
const bool has_unwinding_info = code_desc_.unwinding_info != nullptr;
|
||||
|
||||
code->set_raw_instruction_size(code_desc_.instr_size);
|
||||
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas.
|
||||
code->set_raw_instruction_size(code_desc_.instr_size +
|
||||
code_desc_.unwinding_info_size);
|
||||
code->set_relocation_info(*reloc_info);
|
||||
code->initialize_flags(kind_, has_unwinding_info, is_turbofanned_,
|
||||
stack_slots_, kIsNotOffHeapTrampoline);
|
||||
code->initialize_flags(kind_, is_turbofanned_, stack_slots_,
|
||||
kIsNotOffHeapTrampoline);
|
||||
code->set_builtin_index(builtin_index_);
|
||||
code->set_inlined_bytecode_size(inlined_bytecode_size_);
|
||||
code->set_code_data_container(*data_container, kReleaseStore);
|
||||
@ -187,6 +181,7 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal(
|
||||
code->set_handler_table_offset(code_desc_.handler_table_offset);
|
||||
code->set_constant_pool_offset(code_desc_.constant_pool_offset);
|
||||
code->set_code_comments_offset(code_desc_.code_comments_offset);
|
||||
code->set_unwinding_info_offset(code_desc_.unwinding_info_offset());
|
||||
|
||||
// Allow self references to created code object by patching the handle to
|
||||
// point to the newly allocated Code object.
|
||||
@ -2083,14 +2078,14 @@ Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
|
||||
const bool set_is_off_heap_trampoline = true;
|
||||
const int stack_slots =
|
||||
code->has_safepoint_info() ? code->stack_slots() : 0;
|
||||
result->initialize_flags(code->kind(), code->has_unwinding_info(),
|
||||
code->is_turbofanned(), stack_slots,
|
||||
result->initialize_flags(code->kind(), code->is_turbofanned(), stack_slots,
|
||||
set_is_off_heap_trampoline);
|
||||
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_constant_pool_offset(code->constant_pool_offset());
|
||||
result->set_code_comments_offset(code->code_comments_offset());
|
||||
result->set_unwinding_info_offset(code->unwinding_info_offset());
|
||||
|
||||
// Replace the newly generated trampoline's RelocInfo ByteArray with the
|
||||
// canonical one stored in the roots to avoid duplicating it for every
|
||||
|
@ -174,6 +174,7 @@ INT_ACCESSORS(Code, raw_instruction_size, kInstructionSizeOffset)
|
||||
INT_ACCESSORS(Code, safepoint_table_offset, kSafepointTableOffsetOffset)
|
||||
INT_ACCESSORS(Code, handler_table_offset, kHandlerTableOffsetOffset)
|
||||
INT_ACCESSORS(Code, code_comments_offset, kCodeCommentsOffsetOffset)
|
||||
INT32_ACCESSORS(Code, unwinding_info_offset, kUnwindingInfoOffsetOffset)
|
||||
#define CODE_ACCESSORS(name, type, offset) \
|
||||
ACCESSORS_CHECKED2(Code, name, type, offset, true, \
|
||||
!ObjectInYoungGeneration(value))
|
||||
@ -198,14 +199,18 @@ void Code::WipeOutHeader() {
|
||||
}
|
||||
|
||||
void Code::clear_padding() {
|
||||
// Clear the padding between the header and `raw_instruction_start`.
|
||||
if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
|
||||
memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
|
||||
FIELD_SIZE(kOptionalPaddingOffset));
|
||||
}
|
||||
Address data_end =
|
||||
has_unwinding_info() ? unwinding_info_end() : raw_instruction_end();
|
||||
memset(reinterpret_cast<void*>(data_end), 0,
|
||||
CodeSize() - (data_end - address()));
|
||||
|
||||
// Clear the padding after `raw_instruction_end`.
|
||||
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas.
|
||||
DCHECK_EQ(unwinding_info_offset() + unwinding_info_size(), InstructionSize());
|
||||
size_t trailing_padding_size = body_size() - raw_instruction_size();
|
||||
memset(reinterpret_cast<void*>(raw_instruction_end()), 0,
|
||||
trailing_padding_size);
|
||||
}
|
||||
|
||||
ByteArray Code::SourcePositionTable() const {
|
||||
@ -247,37 +252,10 @@ Address Code::InstructionEnd() const {
|
||||
return raw_instruction_end();
|
||||
}
|
||||
|
||||
int Code::GetUnwindingInfoSizeOffset() const {
|
||||
DCHECK(has_unwinding_info());
|
||||
return RoundUp(kHeaderSize + raw_instruction_size(), kInt64Size);
|
||||
}
|
||||
|
||||
int Code::unwinding_info_size() const {
|
||||
DCHECK(has_unwinding_info());
|
||||
return static_cast<int>(ReadField<uint64_t>(GetUnwindingInfoSizeOffset()));
|
||||
}
|
||||
|
||||
void Code::set_unwinding_info_size(int value) {
|
||||
DCHECK(has_unwinding_info());
|
||||
WriteField<uint64_t>(GetUnwindingInfoSizeOffset(), value);
|
||||
}
|
||||
|
||||
Address Code::unwinding_info_start() const {
|
||||
DCHECK(has_unwinding_info());
|
||||
return FIELD_ADDR(*this, GetUnwindingInfoSizeOffset()) + kInt64Size;
|
||||
}
|
||||
|
||||
Address Code::unwinding_info_end() const {
|
||||
DCHECK(has_unwinding_info());
|
||||
return unwinding_info_start() + unwinding_info_size();
|
||||
}
|
||||
|
||||
int Code::body_size() const {
|
||||
int unpadded_body_size =
|
||||
has_unwinding_info()
|
||||
? static_cast<int>(unwinding_info_end() - raw_instruction_start())
|
||||
: raw_instruction_size();
|
||||
return RoundUp(unpadded_body_size, kObjectAlignment);
|
||||
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas.
|
||||
DCHECK_EQ(unwinding_info_offset() + unwinding_info_size(), InstructionSize());
|
||||
return AlignedBodySizeFor(raw_instruction_size());
|
||||
}
|
||||
|
||||
int Code::SizeIncludingMetadata() const {
|
||||
@ -319,6 +297,10 @@ bool Code::contains(Address inner_pointer) {
|
||||
|
||||
int Code::ExecutableSize() const {
|
||||
// Check that the assumptions about the layout of the code object holds.
|
||||
// TODO(jgruber,v8:11036): It's unclear what this function should return.
|
||||
// Currently, it counts the header, instructions, and metadata tables as
|
||||
// 'executable'. See also ExecutableInstructionSize which counts only
|
||||
// instructions.
|
||||
DCHECK_EQ(static_cast<int>(raw_instruction_start() - address()),
|
||||
Code::kHeaderSize);
|
||||
return raw_instruction_size() + Code::kHeaderSize;
|
||||
@ -339,13 +321,11 @@ CodeKind Code::kind() const {
|
||||
return KindField::decode(ReadField<uint32_t>(kFlagsOffset));
|
||||
}
|
||||
|
||||
void Code::initialize_flags(CodeKind kind, bool has_unwinding_info,
|
||||
bool is_turbofanned, int stack_slots,
|
||||
void Code::initialize_flags(CodeKind kind, bool is_turbofanned, int stack_slots,
|
||||
bool is_off_heap_trampoline) {
|
||||
CHECK(0 <= stack_slots && stack_slots < StackSlotsField::kMax);
|
||||
DCHECK(!CodeKindIsInterpretedJSFunction(kind));
|
||||
uint32_t flags = HasUnwindingInfoField::encode(has_unwinding_info) |
|
||||
KindField::encode(kind) |
|
||||
uint32_t flags = KindField::encode(kind) |
|
||||
IsTurbofannedField::encode(is_turbofanned) |
|
||||
StackSlotsField::encode(stack_slots) |
|
||||
IsOffHeapTrampoline::encode(is_off_heap_trampoline);
|
||||
@ -378,10 +358,6 @@ inline bool Code::has_tagged_params() const {
|
||||
kind() != CodeKind::C_WASM_ENTRY && kind() != CodeKind::WASM_FUNCTION;
|
||||
}
|
||||
|
||||
inline bool Code::has_unwinding_info() const {
|
||||
return HasUnwindingInfoField::decode(ReadField<uint32_t>(kFlagsOffset));
|
||||
}
|
||||
|
||||
inline bool Code::is_turbofanned() const {
|
||||
return IsTurbofannedField::decode(ReadField<uint32_t>(kFlagsOffset));
|
||||
}
|
||||
@ -562,6 +538,19 @@ Address Code::code_comments() const {
|
||||
return InstructionStart() + code_comments_offset();
|
||||
}
|
||||
|
||||
Address Code::unwinding_info_start() const {
|
||||
return InstructionStart() + unwinding_info_offset();
|
||||
}
|
||||
|
||||
Address Code::unwinding_info_end() const { return InstructionEnd(); }
|
||||
|
||||
int Code::unwinding_info_size() const {
|
||||
DCHECK_GE(unwinding_info_end(), unwinding_info_start());
|
||||
return static_cast<int>(unwinding_info_end() - unwinding_info_start());
|
||||
}
|
||||
|
||||
bool Code::has_unwinding_info() const { return unwinding_info_size() > 0; }
|
||||
|
||||
Code Code::GetCodeFromTargetAddress(Address address) {
|
||||
{
|
||||
// TODO(jgruber,v8:6666): Support embedded builtins here. We'd need to pass
|
||||
|
@ -62,8 +62,8 @@ int Code::constant_pool_size() const {
|
||||
bool Code::has_constant_pool() const { return constant_pool_size() > 0; }
|
||||
|
||||
int Code::code_comments_size() const {
|
||||
DCHECK_GE(InstructionSize() - code_comments_offset(), 0);
|
||||
return InstructionSize() - code_comments_offset();
|
||||
DCHECK_GE(unwinding_info_offset() - code_comments_offset(), 0);
|
||||
return unwinding_info_offset() - code_comments_offset();
|
||||
}
|
||||
|
||||
bool Code::has_code_comments() const { return code_comments_size() > 0; }
|
||||
@ -88,22 +88,19 @@ void Code::Relocate(intptr_t delta) {
|
||||
}
|
||||
|
||||
void Code::FlushICache() const {
|
||||
// TODO(jgruber,v8:11036): This should likely flush only actual instructions,
|
||||
// not metadata.
|
||||
FlushInstructionCache(raw_instruction_start(), raw_instruction_size());
|
||||
}
|
||||
|
||||
void Code::CopyFromNoFlush(Heap* heap, const CodeDesc& desc) {
|
||||
// Copy code.
|
||||
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas.
|
||||
CopyBytes(reinterpret_cast<byte*>(raw_instruction_start()), desc.buffer,
|
||||
static_cast<size_t>(desc.instr_size));
|
||||
|
||||
// Copy unwinding info, if any.
|
||||
if (desc.unwinding_info) {
|
||||
DCHECK_GT(desc.unwinding_info_size, 0);
|
||||
set_unwinding_info_size(desc.unwinding_info_size);
|
||||
CopyBytes(reinterpret_cast<byte*>(unwinding_info_start()),
|
||||
desc.unwinding_info,
|
||||
static_cast<size_t>(desc.unwinding_info_size));
|
||||
}
|
||||
// TODO(jgruber,v8:11036): Merge with the above.
|
||||
CopyBytes(reinterpret_cast<byte*>(raw_instruction_start() + desc.instr_size),
|
||||
desc.unwinding_info, static_cast<size_t>(desc.unwinding_info_size));
|
||||
|
||||
// Copy reloc info.
|
||||
CopyRelocInfoToByteArray(unchecked_relocation_info(), desc);
|
||||
|
@ -168,6 +168,20 @@ class Code : public HeapObject {
|
||||
// reserved in the code prologue.
|
||||
inline int stack_slots() const;
|
||||
|
||||
// The body of all Code objects has the following layout.
|
||||
//
|
||||
// +--------------------------+ <-- raw_instruction_start()
|
||||
// | instructions |
|
||||
// | ... |
|
||||
// +--------------------------+
|
||||
// | embedded metadata | <-- safepoint_table_offset()
|
||||
// | ... | <-- handler_table_offset()
|
||||
// | | <-- constant_pool_offset()
|
||||
// | | <-- code_comments_offset()
|
||||
// | | <-- unwinding_info_offset()
|
||||
// | |
|
||||
// +--------------------------+ <-- raw_instruction_end()
|
||||
|
||||
// [safepoint_table_offset]: If {has_safepoint_info()}, the offset in the
|
||||
// instruction stream where the safepoint table starts.
|
||||
inline int safepoint_table_offset() const;
|
||||
@ -198,6 +212,14 @@ class Code : public HeapObject {
|
||||
V8_EXPORT_PRIVATE int code_comments_size() const;
|
||||
V8_EXPORT_PRIVATE bool has_code_comments() const;
|
||||
|
||||
// [unwinding_info_offset]: Offset of the unwinding info section.
|
||||
inline int32_t unwinding_info_offset() const;
|
||||
inline void set_unwinding_info_offset(int32_t offset);
|
||||
inline Address unwinding_info_start() const;
|
||||
inline Address unwinding_info_end() const;
|
||||
inline int unwinding_info_size() const;
|
||||
inline bool has_unwinding_info() const;
|
||||
|
||||
// The size of the executable instruction area, without embedded metadata.
|
||||
int ExecutableInstructionSize() const;
|
||||
|
||||
@ -261,9 +283,8 @@ class Code : public HeapObject {
|
||||
inline void clear_padding();
|
||||
// Initialize the flags field. Similar to clear_padding above this ensure that
|
||||
// the snapshot content is deterministic.
|
||||
inline void initialize_flags(CodeKind kind, bool has_unwinding_info,
|
||||
bool is_turbofanned, int stack_slots,
|
||||
bool is_off_heap_trampoline);
|
||||
inline void initialize_flags(CodeKind kind, bool is_turbofanned,
|
||||
int stack_slots, bool is_off_heap_trampoline);
|
||||
|
||||
// Convert a target address into a code object.
|
||||
static inline Code GetCodeFromTargetAddress(Address address);
|
||||
@ -289,12 +310,14 @@ class Code : public HeapObject {
|
||||
inline Address InstructionEnd() const;
|
||||
V8_EXPORT_PRIVATE Address OffHeapInstructionEnd() const;
|
||||
|
||||
// Returns the size of the instructions, padding, relocation and unwinding
|
||||
// information.
|
||||
// Returns the (padded) body size, including instructions and metadata.
|
||||
inline int body_size() const;
|
||||
static int AlignedBodySizeFor(int unaligned_body_size) {
|
||||
return RoundUp(unaligned_body_size, kObjectAlignment);
|
||||
}
|
||||
|
||||
// Returns the size of code and its metadata. This includes the size of code
|
||||
// relocation information, deoptimization data and handler table.
|
||||
// relocation information, deoptimization data.
|
||||
inline int SizeIncludingMetadata() const;
|
||||
|
||||
// Returns the address of the first relocation info (read backwards!).
|
||||
@ -303,51 +326,6 @@ class Code : public HeapObject {
|
||||
// Returns the address right after the relocation info (read backwards!).
|
||||
inline byte* relocation_end() const;
|
||||
|
||||
// The body of all code objects has the following layout.
|
||||
//
|
||||
// +--------------------------+ <-- raw_instruction_start()
|
||||
// | instructions |
|
||||
// | ... |
|
||||
// +--------------------------+
|
||||
// | embedded metadata | <-- safepoint_table_offset()
|
||||
// | ... | <-- handler_table_offset()
|
||||
// | | <-- constant_pool_offset()
|
||||
// | | <-- code_comments_offset()
|
||||
// | |
|
||||
// +--------------------------+ <-- raw_instruction_end()
|
||||
//
|
||||
// If has_unwinding_info() is false, raw_instruction_end() points to the first
|
||||
// memory location after the end of the code object. Otherwise, the body
|
||||
// continues as follows:
|
||||
//
|
||||
// +--------------------------+
|
||||
// | padding to the next |
|
||||
// | 8-byte aligned address |
|
||||
// +--------------------------+ <-- raw_instruction_end()
|
||||
// | [unwinding_info_size] |
|
||||
// | as uint64_t |
|
||||
// +--------------------------+ <-- unwinding_info_start()
|
||||
// | unwinding info |
|
||||
// | ... |
|
||||
// +--------------------------+ <-- unwinding_info_end()
|
||||
//
|
||||
// and unwinding_info_end() points to the first memory location after the end
|
||||
// of the code object.
|
||||
|
||||
// [has_unwinding_info]: Whether this code object has unwinding information.
|
||||
// If it doesn't, unwinding_information_start() will point to invalid data.
|
||||
inline bool has_unwinding_info() const;
|
||||
|
||||
// [unwinding_info_size]: Size of the unwinding information.
|
||||
inline int unwinding_info_size() const;
|
||||
inline void set_unwinding_info_size(int value);
|
||||
|
||||
// Returns the address of the unwinding information, if any.
|
||||
inline Address unwinding_info_start() const;
|
||||
|
||||
// Returns the address right after the end of the unwinding information.
|
||||
inline Address unwinding_info_end() const;
|
||||
|
||||
// Code entry point.
|
||||
inline Address entry() const;
|
||||
|
||||
@ -424,13 +402,15 @@ class Code : public HeapObject {
|
||||
V(kDataStart, 0) \
|
||||
V(kInstructionSizeOffset, kIntSize) \
|
||||
V(kFlagsOffset, kInt32Size) \
|
||||
V(kBuiltinIndexOffset, kIntSize) \
|
||||
V(kInlinedBytecodeSizeOffset, kIntSize) \
|
||||
/* Offsets describing inline metadata tables. */ \
|
||||
V(kSafepointTableOffsetOffset, kIntSize) \
|
||||
V(kHandlerTableOffsetOffset, kIntSize) \
|
||||
V(kConstantPoolOffsetOffset, \
|
||||
FLAG_enable_embedded_constant_pool ? kIntSize : 0) \
|
||||
V(kCodeCommentsOffsetOffset, kIntSize) \
|
||||
V(kBuiltinIndexOffset, kIntSize) \
|
||||
V(kInlinedBytecodeSizeOffset, kIntSize) \
|
||||
V(kUnwindingInfoOffsetOffset, kInt32Size) \
|
||||
V(kUnalignedHeaderSize, 0) \
|
||||
/* Add padding to align the instruction start following right after */ \
|
||||
/* the Code object header. */ \
|
||||
@ -443,35 +423,32 @@ class Code : public HeapObject {
|
||||
// This documents the amount of free space we have in each Code object header
|
||||
// due to padding for code alignment.
|
||||
#if V8_TARGET_ARCH_ARM64
|
||||
static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 16 : 28;
|
||||
static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 12 : 24;
|
||||
#elif V8_TARGET_ARCH_MIPS64
|
||||
static constexpr int kHeaderPaddingSize = 28;
|
||||
static constexpr int kHeaderPaddingSize = 24;
|
||||
#elif V8_TARGET_ARCH_X64
|
||||
static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 16 : 28;
|
||||
static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 12 : 24;
|
||||
#elif V8_TARGET_ARCH_ARM
|
||||
static constexpr int kHeaderPaddingSize = 16;
|
||||
static constexpr int kHeaderPaddingSize = 12;
|
||||
#elif V8_TARGET_ARCH_IA32
|
||||
static constexpr int kHeaderPaddingSize = 16;
|
||||
static constexpr int kHeaderPaddingSize = 12;
|
||||
#elif V8_TARGET_ARCH_MIPS
|
||||
static constexpr int kHeaderPaddingSize = 16;
|
||||
static constexpr int kHeaderPaddingSize = 12;
|
||||
#elif V8_TARGET_ARCH_PPC64
|
||||
static constexpr int kHeaderPaddingSize =
|
||||
FLAG_enable_embedded_constant_pool ? (COMPRESS_POINTERS_BOOL ? 12 : 24)
|
||||
: (COMPRESS_POINTERS_BOOL ? 16 : 28);
|
||||
FLAG_enable_embedded_constant_pool ? (COMPRESS_POINTERS_BOOL ? 8 : 20)
|
||||
: (COMPRESS_POINTERS_BOOL ? 12 : 24);
|
||||
#elif V8_TARGET_ARCH_S390X
|
||||
static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 16 : 28;
|
||||
static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 12 : 24;
|
||||
#else
|
||||
#error Unknown architecture.
|
||||
#endif
|
||||
STATIC_ASSERT(FIELD_SIZE(kOptionalPaddingOffset) == kHeaderPaddingSize);
|
||||
|
||||
inline int GetUnwindingInfoSizeOffset() const;
|
||||
|
||||
class BodyDescriptor;
|
||||
|
||||
// Flags layout. base::BitField<type, shift, size>.
|
||||
#define CODE_FLAGS_BIT_FIELDS(V, _) \
|
||||
V(HasUnwindingInfoField, bool, 1, _) \
|
||||
V(KindField, CodeKind, 4, _) \
|
||||
V(IsTurbofannedField, bool, 1, _) \
|
||||
V(StackSlotsField, int, 24, _) \
|
||||
@ -479,7 +456,7 @@ class Code : public HeapObject {
|
||||
DEFINE_BIT_FIELDS(CODE_FLAGS_BIT_FIELDS)
|
||||
#undef CODE_FLAGS_BIT_FIELDS
|
||||
STATIC_ASSERT(kCodeKindCount <= KindField::kNumValues);
|
||||
STATIC_ASSERT(CODE_FLAGS_BIT_FIELDS_Ranges::kBitsCount == 31);
|
||||
STATIC_ASSERT(CODE_FLAGS_BIT_FIELDS_Ranges::kBitsCount == 30);
|
||||
STATIC_ASSERT(CODE_FLAGS_BIT_FIELDS_Ranges::kBitsCount <=
|
||||
FIELD_SIZE(kFlagsOffset) * kBitsPerByte);
|
||||
|
||||
|
@ -47,8 +47,8 @@ TEST(CodeLayoutWithoutUnwindingInfo) {
|
||||
CHECK_EQ(code->raw_instruction_size(), buffer_size);
|
||||
CHECK_EQ(0, memcmp(reinterpret_cast<void*>(code->raw_instruction_start()),
|
||||
buffer, buffer_size));
|
||||
CHECK_EQ(code->raw_instruction_end() - code->address(),
|
||||
Code::kHeaderSize + buffer_size);
|
||||
CHECK_EQ(code->raw_instruction_end() - code->raw_instruction_start(),
|
||||
buffer_size);
|
||||
}
|
||||
|
||||
TEST(CodeLayoutWithUnwindingInfo) {
|
||||
@ -91,18 +91,15 @@ TEST(CodeLayoutWithUnwindingInfo) {
|
||||
.Build();
|
||||
|
||||
CHECK(code->has_unwinding_info());
|
||||
CHECK_EQ(code->raw_instruction_size(), buffer_size);
|
||||
CHECK_EQ(code->raw_instruction_size(), buffer_size + unwinding_info_size);
|
||||
CHECK_EQ(0, memcmp(reinterpret_cast<void*>(code->raw_instruction_start()),
|
||||
buffer, buffer_size));
|
||||
CHECK(IsAligned(code->GetUnwindingInfoSizeOffset(), 8));
|
||||
CHECK_EQ(code->unwinding_info_size(), unwinding_info_size);
|
||||
CHECK(IsAligned(code->unwinding_info_start(), 8));
|
||||
CHECK_EQ(memcmp(reinterpret_cast<void*>(code->unwinding_info_start()),
|
||||
unwinding_info, unwinding_info_size),
|
||||
0);
|
||||
CHECK_EQ(code->unwinding_info_end() - code->address(),
|
||||
Code::kHeaderSize + RoundUp(buffer_size, kInt64Size) + kInt64Size +
|
||||
unwinding_info_size);
|
||||
CHECK_EQ(code->unwinding_info_end() - code->raw_instruction_start(),
|
||||
buffer_size + unwinding_info_size);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
Loading…
Reference in New Issue
Block a user