Revert "Remove code size from OatQuickMethodHeader"
This reverts commit 131f23a4c2c34b689c07e6efd05cea74190f0113.
Bug: 123510633
Bug: 127305289
Reason for revert: b/127305289
Change-Id: I59905779fe8c7d7551c0fa6c8693fb64eb6760b2
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 2dd6fdd..d59cb17 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -56,7 +56,7 @@
ArrayRef<const uint8_t> vmap_table = compiled_method->GetVmapTable();
const uint32_t vmap_table_offset = vmap_table.empty() ? 0u
: sizeof(OatQuickMethodHeader) + vmap_table.size();
- OatQuickMethodHeader method_header(vmap_table_offset);
+ OatQuickMethodHeader method_header(vmap_table_offset, code_size);
header_code_and_maps_chunks_.push_back(std::vector<uint8_t>());
std::vector<uint8_t>* chunk = &header_code_and_maps_chunks_.back();
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc
index 48d1ed6..f978cc6 100644
--- a/compiler/exception_test.cc
+++ b/compiler/exception_test.cc
@@ -93,7 +93,7 @@
AlignUp(&fake_header_code_and_maps_[stack_maps_size + header_size], code_alignment);
memcpy(&fake_header_code_and_maps_[0], stack_map.data(), stack_maps_size);
- OatQuickMethodHeader method_header(code_ptr - fake_header_code_and_maps_.data());
+ OatQuickMethodHeader method_header(code_ptr - fake_header_code_and_maps_.data(), code_size);
static_assert(std::is_trivially_copyable<OatQuickMethodHeader>::value, "Cannot use memcpy");
memcpy(code_ptr - header_size, &method_header, header_size);
memcpy(code_ptr, fake_code_.data(), fake_code_.size());
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 2f11f8e..be9a0cb 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -1319,16 +1319,18 @@
// Update quick method header.
DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size());
OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_];
- uint32_t code_info_offset = method_header->GetVmapTableOffset();
+ uint32_t vmap_table_offset = method_header->GetVmapTableOffset();
+ // The code offset was 0 when the mapping/vmap table offset was set, so it's set
+ // to 0-offset and we need to adjust it by code_offset.
uint32_t code_offset = quick_code_offset - thumb_offset;
CHECK(!compiled_method->GetQuickCode().empty());
// If the code is compiled, we write the offset of the stack map relative
- // to the code. The offset was previously stored relative to start of file.
- if (code_info_offset != 0u) {
- DCHECK_LT(code_info_offset, code_offset);
- code_info_offset = code_offset - code_info_offset;
+ // to the code.
+ if (vmap_table_offset != 0u) {
+ vmap_table_offset += code_offset;
+ DCHECK_LT(vmap_table_offset, code_offset);
}
- *method_header = OatQuickMethodHeader(code_info_offset);
+ *method_header = OatQuickMethodHeader(vmap_table_offset, code_size);
if (!deduped) {
// Update offsets. (Checksum is updated when writing.)
@@ -1460,9 +1462,9 @@
// Deduplicate the inner BitTable<>s within the CodeInfo.
return offset_ + dedupe_bit_table_.Dedupe(map.data());
});
- // Code offset is not initialized yet, so set file offset for now.
+ // Code offset is not initialized yet, so set the map offset to 0u-offset.
DCHECK_EQ(oat_class->method_offsets_[method_offsets_index_].code_offset_, 0u);
- oat_class->method_headers_[method_offsets_index_].SetVmapTableOffset(offset);
+ oat_class->method_headers_[method_offsets_index_].SetVmapTableOffset(0u - offset);
}
++method_offsets_index_;
}
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index 1277cc7..ea12440 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -468,7 +468,7 @@
// it is time to update OatHeader::kOatVersion
EXPECT_EQ(64U, sizeof(OatHeader));
EXPECT_EQ(4U, sizeof(OatMethodOffsets));
- EXPECT_EQ(4U, sizeof(OatQuickMethodHeader));
+ EXPECT_EQ(8U, sizeof(OatQuickMethodHeader));
EXPECT_EQ(166 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)),
sizeof(QuickEntryPoints));
}
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 35f8ee2..e623f77 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1247,45 +1247,65 @@
}
{
vios->Stream() << "CODE: ";
- const void* code = oat_method.GetQuickCode();
- uint32_t aligned_code_begin = AlignCodeOffset(code_offset);
- uint64_t aligned_code_end = aligned_code_begin + code_size;
- if (AddStatsObject(code)) {
- stats_.Child("Code")->AddBytes(code_size);
- }
-
- if (options_.absolute_addresses_) {
- vios->Stream() << StringPrintf("%p ", code);
- }
- vios->Stream() << StringPrintf("(code_offset=0x%08x size=%u)%s\n",
- code_offset,
- code_size,
- code != nullptr ? "..." : "");
-
- ScopedIndentation indent2(vios);
- if (aligned_code_begin > oat_file_.Size()) {
+ uint32_t code_size_offset = oat_method.GetQuickCodeSizeOffset();
+ if (code_size_offset > oat_file_.Size()) {
+ ScopedIndentation indent2(vios);
vios->Stream() << StringPrintf("WARNING: "
- "start of code at 0x%08x is past end of file 0x%08zx.",
- aligned_code_begin, oat_file_.Size());
+ "code size offset 0x%08x is past end of file 0x%08zx.",
+ code_size_offset, oat_file_.Size());
success = false;
- } else if (aligned_code_end > oat_file_.Size()) {
- vios->Stream() << StringPrintf(
- "WARNING: "
- "end of code at 0x%08" PRIx64 " is past end of file 0x%08zx. "
- "code size is 0x%08x.\n",
- aligned_code_end, oat_file_.Size(),
- code_size);
- success = false;
- } else if (code_size > kMaxCodeSize) {
- vios->Stream() << StringPrintf(
- "WARNING: "
- "code size %d is bigger than max expected threshold of %d. "
- "code size is 0x%08x.\n",
- code_size, kMaxCodeSize,
- code_size);
- success = false;
- } else if (options_.disassemble_code_) {
- DumpCode(vios, oat_method, code_item_accessor, !success, 0);
+ } else {
+ const void* code = oat_method.GetQuickCode();
+ uint32_t aligned_code_begin = AlignCodeOffset(code_offset);
+ uint64_t aligned_code_end = aligned_code_begin + code_size;
+ if (AddStatsObject(code)) {
+ stats_.Child("Code")->AddBytes(code_size);
+ }
+
+ if (options_.absolute_addresses_) {
+ vios->Stream() << StringPrintf("%p ", code);
+ }
+ vios->Stream() << StringPrintf("(code_offset=0x%08x size_offset=0x%08x size=%u)%s\n",
+ code_offset,
+ code_size_offset,
+ code_size,
+ code != nullptr ? "..." : "");
+
+ ScopedIndentation indent2(vios);
+ if (aligned_code_begin > oat_file_.Size()) {
+ vios->Stream() << StringPrintf("WARNING: "
+ "start of code at 0x%08x is past end of file 0x%08zx.",
+ aligned_code_begin, oat_file_.Size());
+ success = false;
+ } else if (aligned_code_end > oat_file_.Size()) {
+ vios->Stream() << StringPrintf(
+ "WARNING: "
+ "end of code at 0x%08" PRIx64 " is past end of file 0x%08zx. "
+ "code size is 0x%08x loaded from offset 0x%08x.\n",
+ aligned_code_end, oat_file_.Size(),
+ code_size, code_size_offset);
+ success = false;
+ if (options_.disassemble_code_) {
+ if (code_size_offset + kPrologueBytes <= oat_file_.Size()) {
+ DumpCode(vios, oat_method, code_item_accessor, true, kPrologueBytes);
+ }
+ }
+ } else if (code_size > kMaxCodeSize) {
+ vios->Stream() << StringPrintf(
+ "WARNING: "
+ "code size %d is bigger than max expected threshold of %d. "
+ "code size is 0x%08x loaded from offset 0x%08x.\n",
+ code_size, kMaxCodeSize,
+ code_size, code_size_offset);
+ success = false;
+ if (options_.disassemble_code_) {
+ if (code_size_offset + kPrologueBytes <= oat_file_.Size()) {
+ DumpCode(vios, oat_method, code_item_accessor, true, kPrologueBytes);
+ }
+ }
+ } else if (options_.disassemble_code_) {
+ DumpCode(vios, oat_method, code_item_accessor, !success, 0);
+ }
}
}
vios->Stream() << std::flush;
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index a9823e5..c1b9a1a 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -990,7 +990,8 @@
}
new (method_header) OatQuickMethodHeader(
- (stack_map != nullptr) ? code_ptr - stack_map : 0u);
+ (stack_map != nullptr) ? code_ptr - stack_map : 0u,
+ code_size);
DCHECK(!Runtime::Current()->IsAotCompiler());
if (has_should_deoptimize_flag) {
diff --git a/runtime/oat.h b/runtime/oat.h
index bd4a6e3..b824729 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -31,8 +31,8 @@
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- // Last oat version changed reason: Remove code size from OatQuickMethodHeader.
- static constexpr uint8_t kOatVersion[] = { '1', '6', '8', '\0' };
+ // Last oat version changed reason: Add code size to CodeInfo.
+ static constexpr uint8_t kOatVersion[] = { '1', '6', '7', '\0' };
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
static constexpr const char* kDebuggableKey = "debuggable";
diff --git a/runtime/oat_file-inl.h b/runtime/oat_file-inl.h
index 6ff86b8..b71c4e8 100644
--- a/runtime/oat_file-inl.h
+++ b/runtime/oat_file-inl.h
@@ -41,6 +41,14 @@
return reinterpret_cast<const uint8_t*>(method_header) - begin_;
}
+inline uint32_t OatFile::OatMethod::GetQuickCodeSizeOffset() const {
+ const OatQuickMethodHeader* method_header = GetOatQuickMethodHeader();
+ if (method_header == nullptr) {
+ return 0u;
+ }
+ return reinterpret_cast<const uint8_t*>(method_header->GetCodeSizeAddr()) - begin_;
+}
+
inline size_t OatFile::OatMethod::GetFrameSizeInBytes() const {
const void* code = EntryPointToCodePointer(GetQuickCode());
if (code == nullptr) {
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index e2c6633..04b666c 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -155,6 +155,7 @@
// Returns size of quick code.
uint32_t GetQuickCodeSize() const;
+ uint32_t GetQuickCodeSizeOffset() const;
// Returns OatQuickMethodHeader for debugging. Most callers should
// use more specific methods such as GetQuickCodeSize.
diff --git a/runtime/oat_quick_method_header.h b/runtime/oat_quick_method_header.h
index 745be40..6c123c4 100644
--- a/runtime/oat_quick_method_header.h
+++ b/runtime/oat_quick_method_header.h
@@ -31,8 +31,12 @@
class PACKED(4) OatQuickMethodHeader {
public:
OatQuickMethodHeader() = default;
- OatQuickMethodHeader(uint32_t code_info_offset) : code_info_offset_(code_info_offset) {
- DCHECK_NE(code_info_offset, 0u);
+ OatQuickMethodHeader(uint32_t vmap_table_offset,
+ uint32_t code_size)
+ : vmap_table_offset_(vmap_table_offset),
+ code_size_(code_size) {
+ DCHECK_NE(vmap_table_offset, 0u);
+ DCHECK_NE(code_size, 0u);
}
static OatQuickMethodHeader* FromCodePointer(const void* code_ptr) {
@@ -56,17 +60,17 @@
}
bool IsOptimized() const {
- return true;
+ return (code_size_ & kCodeSizeMask) != 0 && vmap_table_offset_ != 0;
}
const uint8_t* GetOptimizedCodeInfoPtr() const {
- DCHECK_NE(code_info_offset_, 0u);
- return code_ - GetVmapTableOffset();
+ DCHECK(IsOptimized());
+ return code_ - vmap_table_offset_;
}
uint8_t* GetOptimizedCodeInfoPtr() {
- DCHECK_NE(code_info_offset_, 0u);
- return code_ - GetVmapTableOffset();
+ DCHECK(IsOptimized());
+ return code_ - vmap_table_offset_;
}
const uint8_t* GetCode() const {
@@ -74,26 +78,32 @@
}
uint32_t GetCodeSize() const {
- return CodeInfo::DecodeCodeSize(GetOptimizedCodeInfoPtr());
+ DCHECK(IsOptimized());
+ size_t code_size1 = code_size_ & kCodeSizeMask;
+ size_t code_size2 = CodeInfo::DecodeCodeSize(GetOptimizedCodeInfoPtr());
+ DCHECK_EQ(code_size1, code_size2);
+ return code_size2;
+ }
+
+ const uint32_t* GetCodeSizeAddr() const {
+ return &code_size_;
}
uint32_t GetVmapTableOffset() const {
- return code_info_offset_ & kCodeInfoMask;
+ return vmap_table_offset_;
}
void SetVmapTableOffset(uint32_t offset) {
- DCHECK(!HasShouldDeoptimizeFlag());
- code_info_offset_ = offset;
- DCHECK_EQ(GetVmapTableOffset(), offset);
+ vmap_table_offset_ = offset;
}
const uint32_t* GetVmapTableOffsetAddr() const {
- return &code_info_offset_;
+ return &vmap_table_offset_;
}
const uint8_t* GetVmapTable() const {
CHECK(!IsOptimized()) << "Unimplemented vmap table for optimizing compiler";
- return (code_info_offset_ == 0) ? nullptr : code_ - code_info_offset_;
+ return (vmap_table_offset_ == 0) ? nullptr : code_ - vmap_table_offset_;
}
bool Contains(uintptr_t pc) const {
@@ -139,21 +149,23 @@
uint32_t ToDexPc(ArtMethod* method, const uintptr_t pc, bool abort_on_failure = true) const;
void SetHasShouldDeoptimizeFlag() {
- DCHECK_EQ(code_info_offset_ & kShouldDeoptimizeMask, 0u);
- code_info_offset_ |= kShouldDeoptimizeMask;
+ DCHECK_EQ(code_size_ & kShouldDeoptimizeMask, 0u);
+ code_size_ |= kShouldDeoptimizeMask;
}
bool HasShouldDeoptimizeFlag() const {
- return (code_info_offset_ & kShouldDeoptimizeMask) != 0;
+ return (code_size_ & kShouldDeoptimizeMask) != 0;
}
private:
static constexpr uint32_t kShouldDeoptimizeMask = 0x80000000;
- static constexpr uint32_t kCodeInfoMask = ~kShouldDeoptimizeMask;
+ static constexpr uint32_t kCodeSizeMask = ~kShouldDeoptimizeMask;
- // The offset in bytes from the start of the code_info to the end of the header.
- // The highest bit is used to store the should_deoptimize flag.
- uint32_t code_info_offset_ = 0u;
+ // The offset in bytes from the start of the vmap table to the end of the header.
+ uint32_t vmap_table_offset_ = 0u;
+ // The code size in bytes. The highest bit is used to signify if the compiled
+ // code with the method header has should_deoptimize flag.
+ uint32_t code_size_ = 0u;
// The actual code.
uint8_t code_[0];
};