Commit adf5c707 authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

Revert "[code] Move the unwinding info into metadata area"

This reverts commit c5379162.

Reason for revert: Seems to cause MSAN failure - https://ci.chromium.org/p/v8/builders/ci/V8%20Linux%20-%20arm64%20-%20sim%20-%20MSAN/34931

Original change's description:
> [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}

TBR=jgruber@chromium.org,leszeks@chromium.org,dinfuehr@chromium.org

Change-Id: If8417f88f4c55771e455ec85f5efdc6343671ad3
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:11036
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2485500Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70641}
parent c5379162
......@@ -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,11 +73,6 @@ 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,8 +390,9 @@ 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::kBuiltinIndexOffset == Code::kFlagsOffsetEnd + 1);
static constexpr int kStartOffset = Code::kBuiltinIndexOffset;
STATIC_ASSERT(Code::kSafepointTableOffsetOffset ==
Code::kFlagsOffsetEnd + 1);
static constexpr int kStartOffset = Code::kSafepointTableOffsetOffset;
for (int j = kStartOffset; j < Code::kUnalignedHeaderSize; j++) {
hash = base::hash_combine(hash, size_t{code_ptr[j]});
......
......@@ -70,9 +70,16 @@ namespace internal {
namespace {
int ComputeCodeObjectSize(const CodeDesc& desc) {
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas.
int object_size = Code::SizeFor(
Code::AlignedBodySizeFor(desc.instr_size + desc.unwinding_info_size));
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));
DCHECK(IsAligned(static_cast<intptr_t>(object_size), kCodeAlignment));
return object_size;
}
......@@ -165,13 +172,12 @@ MaybeHandle<Code> Factory::CodeBuilder::BuildInternal(
}
constexpr bool kIsNotOffHeapTrampoline = false;
const bool has_unwinding_info = code_desc_.unwinding_info != nullptr;
// 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_raw_instruction_size(code_desc_.instr_size);
code->set_relocation_info(*reloc_info);
code->initialize_flags(kind_, is_turbofanned_, stack_slots_,
kIsNotOffHeapTrampoline);
code->initialize_flags(kind_, has_unwinding_info, 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);
......@@ -181,7 +187,6 @@ 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.
......@@ -2078,14 +2083,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->is_turbofanned(), stack_slots,
result->initialize_flags(code->kind(), code->has_unwinding_info(),
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,7 +174,6 @@ 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))
......@@ -199,18 +198,14 @@ 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));
}
// 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);
Address data_end =
has_unwinding_info() ? unwinding_info_end() : raw_instruction_end();
memset(reinterpret_cast<void*>(data_end), 0,
CodeSize() - (data_end - address()));
}
ByteArray Code::SourcePositionTable() const {
......@@ -252,10 +247,37 @@ 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 {
// TODO(jgruber,v8:11036): Distinguish instruction and metadata areas.
DCHECK_EQ(unwinding_info_offset() + unwinding_info_size(), InstructionSize());
return AlignedBodySizeFor(raw_instruction_size());
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);
}
int Code::SizeIncludingMetadata() const {
......@@ -297,10 +319,6 @@ 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;
......@@ -321,11 +339,13 @@ CodeKind Code::kind() const {
return KindField::decode(ReadField<uint32_t>(kFlagsOffset));
}
void Code::initialize_flags(CodeKind kind, bool is_turbofanned, int stack_slots,
void Code::initialize_flags(CodeKind kind, bool has_unwinding_info,
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 = KindField::encode(kind) |
uint32_t flags = HasUnwindingInfoField::encode(has_unwinding_info) |
KindField::encode(kind) |
IsTurbofannedField::encode(is_turbofanned) |
StackSlotsField::encode(stack_slots) |
IsOffHeapTrampoline::encode(is_off_heap_trampoline);
......@@ -358,6 +378,10 @@ 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));
}
......@@ -538,19 +562,6 @@ 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(unwinding_info_offset() - code_comments_offset(), 0);
return unwinding_info_offset() - code_comments_offset();
DCHECK_GE(InstructionSize() - code_comments_offset(), 0);
return InstructionSize() - code_comments_offset();
}
bool Code::has_code_comments() const { return code_comments_size() > 0; }
......@@ -88,19 +88,22 @@ 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));
// 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 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));
}
// Copy reloc info.
CopyRelocInfoToByteArray(unchecked_relocation_info(), desc);
......
......@@ -168,20 +168,6 @@ 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;
......@@ -212,14 +198,6 @@ 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;
......@@ -283,8 +261,9 @@ 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 is_turbofanned,
int stack_slots, bool is_off_heap_trampoline);
inline void initialize_flags(CodeKind kind, bool has_unwinding_info,
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);
......@@ -310,14 +289,12 @@ class Code : public HeapObject {
inline Address InstructionEnd() const;
V8_EXPORT_PRIVATE Address OffHeapInstructionEnd() const;
// Returns the (padded) body size, including instructions and metadata.
// Returns the size of the instructions, padding, relocation and unwinding
// information.
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.
// relocation information, deoptimization data and handler table.
inline int SizeIncludingMetadata() const;
// Returns the address of the first relocation info (read backwards!).
......@@ -326,6 +303,51 @@ 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;
......@@ -402,15 +424,13 @@ 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(kUnwindingInfoOffsetOffset, kInt32Size) \
V(kBuiltinIndexOffset, kIntSize) \
V(kInlinedBytecodeSizeOffset, kIntSize) \
V(kUnalignedHeaderSize, 0) \
/* Add padding to align the instruction start following right after */ \
/* the Code object header. */ \
......@@ -423,32 +443,35 @@ 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 ? 12 : 24;
static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 16 : 28;
#elif V8_TARGET_ARCH_MIPS64
static constexpr int kHeaderPaddingSize = 24;
static constexpr int kHeaderPaddingSize = 28;
#elif V8_TARGET_ARCH_X64
static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 12 : 24;
static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 16 : 28;
#elif V8_TARGET_ARCH_ARM
static constexpr int kHeaderPaddingSize = 12;
static constexpr int kHeaderPaddingSize = 16;
#elif V8_TARGET_ARCH_IA32
static constexpr int kHeaderPaddingSize = 12;
static constexpr int kHeaderPaddingSize = 16;
#elif V8_TARGET_ARCH_MIPS
static constexpr int kHeaderPaddingSize = 12;
static constexpr int kHeaderPaddingSize = 16;
#elif V8_TARGET_ARCH_PPC64
static constexpr int kHeaderPaddingSize =
FLAG_enable_embedded_constant_pool ? (COMPRESS_POINTERS_BOOL ? 8 : 20)
: (COMPRESS_POINTERS_BOOL ? 12 : 24);
FLAG_enable_embedded_constant_pool ? (COMPRESS_POINTERS_BOOL ? 12 : 24)
: (COMPRESS_POINTERS_BOOL ? 16 : 28);
#elif V8_TARGET_ARCH_S390X
static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 12 : 24;
static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 16 : 28;
#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, _) \
......@@ -456,7 +479,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 == 30);
STATIC_ASSERT(CODE_FLAGS_BIT_FIELDS_Ranges::kBitsCount == 31);
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->raw_instruction_start(),
buffer_size);
CHECK_EQ(code->raw_instruction_end() - code->address(),
Code::kHeaderSize + buffer_size);
}
TEST(CodeLayoutWithUnwindingInfo) {
......@@ -91,15 +91,18 @@ TEST(CodeLayoutWithUnwindingInfo) {
.Build();
CHECK(code->has_unwinding_info());
CHECK_EQ(code->raw_instruction_size(), buffer_size + unwinding_info_size);
CHECK_EQ(code->raw_instruction_size(), buffer_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->raw_instruction_start(),
buffer_size + unwinding_info_size);
CHECK_EQ(code->unwinding_info_end() - code->address(),
Code::kHeaderSize + RoundUp(buffer_size, kInt64Size) + kInt64Size +
unwinding_info_size);
}
} // namespace internal
......
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