diff options
| -rw-r--r-- | compiler/image_test.cc | 3 | ||||
| -rw-r--r-- | compiler/oat_test.cc | 3 | ||||
| -rw-r--r-- | compiler/oat_writer.cc | 195 | ||||
| -rw-r--r-- | compiler/oat_writer.h | 24 | ||||
| -rw-r--r-- | dex2oat/dex2oat.cc | 18 | ||||
| -rw-r--r-- | oatdump/oatdump.cc | 13 | ||||
| -rw-r--r-- | runtime/art_method.cc | 13 | ||||
| -rw-r--r-- | runtime/oat_file.h | 4 | ||||
| -rw-r--r-- | runtime/vdex_file.cc | 7 | ||||
| -rw-r--r-- | runtime/vdex_file.h | 4 |
10 files changed, 225 insertions, 59 deletions
diff --git a/compiler/image_test.cc b/compiler/image_test.cc index 9e94b9d861..8fdf6fca68 100644 --- a/compiler/image_test.cc +++ b/compiler/image_test.cc @@ -260,7 +260,8 @@ void CompilationHelper::Compile(CompilerDriver* driver, OatWriter* const oat_writer = oat_writers[i].get(); ElfWriter* const elf_writer = elf_writers[i].get(); std::vector<const DexFile*> cur_dex_files(1u, class_path[i]); - oat_writer->PrepareLayout(driver, writer.get(), cur_dex_files, &patcher); + oat_writer->Initialize(driver, writer.get(), cur_dex_files); + oat_writer->PrepareLayout(&patcher); size_t rodata_size = oat_writer->GetOatHeader().GetExecutableOffset(); size_t text_size = oat_writer->GetOatSize() - rodata_size; elf_writer->PrepareDynamicSection(rodata_size, diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index ffeff760c6..fd1b1354a1 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -203,7 +203,8 @@ class OatTest : public CommonCompilerTest { } linker::MultiOatRelativePatcher patcher(compiler_driver_->GetInstructionSet(), instruction_set_features_.get()); - oat_writer.PrepareLayout(compiler_driver_.get(), nullptr, dex_files, &patcher); + oat_writer.Initialize(compiler_driver_.get(), nullptr, dex_files); + oat_writer.PrepareLayout(&patcher); size_t rodata_size = oat_writer.GetOatHeader().GetExecutableOffset(); size_t text_size = oat_writer.GetOatSize() - rodata_size; elf_writer->PrepareDynamicSection(rodata_size, diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 52134e8b9b..6cbca7a6dc 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -299,6 +299,7 @@ OatWriter::OatWriter(bool compiling_boot_image, TimingLogger* timings) vdex_size_(0u), vdex_dex_files_offset_(0u), vdex_verifier_deps_offset_(0u), + vdex_quickening_info_offset_(0u), oat_size_(0u), bss_start_(0u), bss_size_(0u), @@ -314,6 +315,8 @@ OatWriter::OatWriter(bool compiling_boot_image, TimingLogger* timings) size_dex_file_(0), size_verifier_deps_(0), size_verifier_deps_alignment_(0), + size_quickening_info_(0), + size_quickening_info_alignment_(0), size_interpreter_to_interpreter_bridge_(0), size_interpreter_to_compiled_code_bridge_(0), size_jni_dlsym_lookup_(0), @@ -519,15 +522,9 @@ bool OatWriter::WriteAndOpenDexFiles( return true; } -void OatWriter::PrepareLayout(const CompilerDriver* compiler, - ImageWriter* image_writer, - const std::vector<const DexFile*>& dex_files, - linker::MultiOatRelativePatcher* relative_patcher) { +void OatWriter::PrepareLayout(linker::MultiOatRelativePatcher* relative_patcher) { CHECK(write_state_ == WriteState::kPrepareLayout); - compiler_driver_ = compiler; - image_writer_ = image_writer; - dex_files_ = &dex_files; relative_patcher_ = relative_patcher; SetMultiOatRelativePatcherAdjustment(); @@ -706,9 +703,10 @@ class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor { class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { public: - InitCodeMethodVisitor(OatWriter* writer, size_t offset) + InitCodeMethodVisitor(OatWriter* writer, size_t offset, size_t quickening_info_offset) : OatDexMethodVisitor(writer, offset), - debuggable_(writer->GetCompilerDriver()->GetCompilerOptions().GetDebuggable()) { + debuggable_(writer->GetCompilerDriver()->GetCompilerOptions().GetDebuggable()), + current_quickening_info_offset_(quickening_info_offset) { writer_->absolute_patch_locations_.reserve( writer_->compiler_driver_->GetNonRelativeLinkerPatchCount()); } @@ -726,6 +724,9 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); + if (it.GetMethodCodeItem() != nullptr) { + current_quickening_info_offset_ += sizeof(uint32_t); + } if (compiled_method != nullptr) { // Derived from CompiledMethod. uint32_t quick_code_offset = 0; @@ -771,15 +772,28 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size()); OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_]; uint32_t vmap_table_offset = method_header->vmap_table_offset_; - // If we don't have quick code, then we must have a vmap, as that is how the dex2dex - // compiler records its transformations. - DCHECK(!quick_code.empty() || vmap_table_offset != 0); // 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; - if (vmap_table_offset != 0u && code_offset != 0u) { - vmap_table_offset += code_offset; - DCHECK_LT(vmap_table_offset, code_offset) << "Overflow in oat offsets"; + if (!compiled_method->GetQuickCode().empty()) { + // If the code is compiled, we write the offset of the stack map relative + // to the code, + if (vmap_table_offset != 0u) { + vmap_table_offset += code_offset; + DCHECK_LT(vmap_table_offset, code_offset); + } + } else { + if (kIsVdexEnabled) { + // We write the offset in the .vdex file. + DCHECK_EQ(vmap_table_offset, 0u); + vmap_table_offset = current_quickening_info_offset_; + ArrayRef<const uint8_t> map = compiled_method->GetVmapTable(); + current_quickening_info_offset_ += map.size() * sizeof(map.front()); + } else { + // We write the offset of the quickening info relative to the code. + vmap_table_offset += code_offset; + DCHECK_LT(vmap_table_offset, code_offset); + } } uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); uint32_t core_spill_mask = compiled_method->GetCoreSpillMask(); @@ -878,6 +892,9 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { // Cache of compiler's --debuggable option. const bool debuggable_; + + // Offset in the vdex file for the quickening info. + uint32_t current_quickening_info_offset_; }; class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor { @@ -893,21 +910,25 @@ class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor { if (compiled_method != nullptr) { DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size()); - DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].vmap_table_offset_, 0u); + // If vdex is enabled, we only emit the stack map of compiled code. The quickening info will + // be in the vdex file. + if (!compiled_method->GetQuickCode().empty() || !kIsVdexEnabled) { + DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].vmap_table_offset_, 0u); - ArrayRef<const uint8_t> map = compiled_method->GetVmapTable(); - uint32_t map_size = map.size() * sizeof(map[0]); - if (map_size != 0u) { - size_t offset = dedupe_map_.GetOrCreate( - map.data(), - [this, map_size]() { - uint32_t new_offset = offset_; - offset_ += map_size; - return new_offset; - }); - // 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_].vmap_table_offset_ = 0u - offset; + ArrayRef<const uint8_t> map = compiled_method->GetVmapTable(); + uint32_t map_size = map.size() * sizeof(map[0]); + if (map_size != 0u) { + size_t offset = dedupe_map_.GetOrCreate( + map.data(), + [this, map_size]() { + uint32_t new_offset = offset_; + offset_ += map_size; + return new_offset; + }); + // 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_].vmap_table_offset_ = 0u - offset; + } } ++method_offsets_index_; } @@ -1372,7 +1393,10 @@ class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor { << compiled_method->GetVmapTable().size() << " " << map_offset << " " << dex_file_->PrettyMethod(it.GetMemberIndex()); - if (map_offset != 0u) { + // If vdex is enabled, only emit the map for compiled code. The quickening info + // is emitted in the vdex already. + if (map_offset != 0u && + !(kIsVdexEnabled && compiled_method->GetQuickCode().empty())) { // Transform map_offset to actual oat data offset. map_offset = (code_offset - compiled_method->CodeDelta()) - map_offset; DCHECK_NE(map_offset, 0u); @@ -1539,21 +1563,18 @@ size_t OatWriter::InitOatCode(size_t offset) { } size_t OatWriter::InitOatCodeDexFiles(size_t offset) { - #define VISIT(VisitorType) \ - do { \ - VisitorType visitor(this, offset); \ - bool success = VisitDexMethods(&visitor); \ - DCHECK(success); \ - offset = visitor.GetOffset(); \ - } while (false) + InitCodeMethodVisitor code_visitor(this, offset, vdex_quickening_info_offset_); + bool success = VisitDexMethods(&code_visitor); + DCHECK(success); + offset = code_visitor.GetOffset(); - VISIT(InitCodeMethodVisitor); if (HasImage()) { - VISIT(InitImageMethodVisitor); + InitImageMethodVisitor image_visitor(this, offset); + success = VisitDexMethods(&image_visitor); + DCHECK(success); + offset = image_visitor.GetOffset(); } - #undef VISIT - return offset; } @@ -1626,6 +1647,90 @@ bool OatWriter::WriteRodata(OutputStream* out) { return true; } +class OatWriter::WriteQuickeningInfoMethodVisitor : public DexMethodVisitor { + public: + WriteQuickeningInfoMethodVisitor(OatWriter* writer, OutputStream* out, uint32_t offset) + : DexMethodVisitor(writer, offset), + out_(out), + written_bytes_(0u) {} + + bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED, + const ClassDataItemIterator& it) { + if (it.GetMethodCodeItem() == nullptr) { + // No CodeItem. Native or abstract method. + return true; + } + + uint32_t method_idx = it.GetMemberIndex(); + CompiledMethod* compiled_method = + writer_->compiler_driver_->GetCompiledMethod(MethodReference(dex_file_, method_idx)); + + uint32_t length = 0; + const uint8_t* data = nullptr; + // VMap only contains quickening info if this method is not compiled. + if (compiled_method != nullptr && compiled_method->GetQuickCode().empty()) { + ArrayRef<const uint8_t> map = compiled_method->GetVmapTable(); + data = map.data(); + length = map.size() * sizeof(map.front()); + } + + if (!out_->WriteFully(&length, sizeof(length)) || + !out_->WriteFully(data, length)) { + PLOG(ERROR) << "Failed to write quickening info for " + << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to " << out_->GetLocation(); + return false; + } + offset_ += sizeof(length) + length; + written_bytes_ += sizeof(length) + length; + return true; + } + + size_t GetNumberOfWrittenBytes() const { + return written_bytes_; + } + + private: + OutputStream* const out_; + size_t written_bytes_; +}; + +bool OatWriter::WriteQuickeningInfo(OutputStream* vdex_out) { + if (!kIsVdexEnabled) { + return true; + } + + size_t initial_offset = vdex_size_; + size_t start_offset = RoundUp(initial_offset, 4u); + + vdex_size_ = start_offset; + vdex_quickening_info_offset_ = vdex_size_; + size_quickening_info_alignment_ = start_offset - initial_offset; + + off_t actual_offset = vdex_out->Seek(start_offset, kSeekSet); + if (actual_offset != static_cast<off_t>(start_offset)) { + PLOG(ERROR) << "Failed to seek to quickening info section. Actual: " << actual_offset + << " Expected: " << start_offset + << " Output: " << vdex_out->GetLocation(); + return false; + } + + WriteQuickeningInfoMethodVisitor visitor(this, vdex_out, start_offset); + if (!VisitDexMethods(&visitor)) { + PLOG(ERROR) << "Failed to write the vdex quickening info. File: " << vdex_out->GetLocation(); + return false; + } + + if (!vdex_out->Flush()) { + PLOG(ERROR) << "Failed to flush stream after writing quickening info." + << " File: " << vdex_out->GetLocation(); + return false; + } + + size_quickening_info_ = visitor.GetNumberOfWrittenBytes(); + vdex_size_ += size_quickening_info_; + return true; +} + bool OatWriter::WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps) { if (!kIsVdexEnabled) { return true; @@ -1717,6 +1822,8 @@ bool OatWriter::WriteCode(OutputStream* out) { DO_STAT(size_dex_file_); DO_STAT(size_verifier_deps_); DO_STAT(size_verifier_deps_alignment_); + DO_STAT(size_quickening_info_); + DO_STAT(size_quickening_info_alignment_); DO_STAT(size_interpreter_to_interpreter_bridge_); DO_STAT(size_interpreter_to_compiled_code_bridge_); DO_STAT(size_jni_dlsym_lookup_); @@ -2434,9 +2541,11 @@ bool OatWriter::WriteVdexHeader(OutputStream* vdex_out) { DCHECK_NE(vdex_verifier_deps_offset_, 0u); size_t dex_section_size = vdex_verifier_deps_offset_ - vdex_dex_files_offset_; - size_t verifier_deps_section_size = vdex_size_ - vdex_verifier_deps_offset_; + size_t verifier_deps_section_size = vdex_quickening_info_offset_ - vdex_verifier_deps_offset_; + size_t quickening_info_section_size = vdex_size_ - vdex_quickening_info_offset_; - VdexFile::Header vdex_header(dex_section_size, verifier_deps_section_size); + VdexFile::Header vdex_header( + dex_section_size, verifier_deps_section_size, quickening_info_section_size); if (!vdex_out->WriteFully(&vdex_header, sizeof(VdexFile::Header))) { PLOG(ERROR) << "Failed to write vdex header. File: " << vdex_out->GetLocation(); return false; diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h index 1cc193b341..3d08ad3173 100644 --- a/compiler/oat_writer.h +++ b/compiler/oat_writer.h @@ -118,6 +118,10 @@ class OatWriter { // - AddRawDexFileSource(). // Then the user must call in order // - WriteAndOpenDexFiles() + // - Initialize() + // - WriteVerifierDeps() + // - WriteQuickeningInfo() + // - WriteVdexHeader() // - PrepareLayout(), // - WriteRodata(), // - WriteCode(), @@ -154,14 +158,20 @@ class OatWriter { bool verify, /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map, /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files); + bool WriteQuickeningInfo(OutputStream* vdex_out); bool WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps); bool WriteVdexHeader(OutputStream* vdex_out); + // Initialize the writer with the given parameters. + void Initialize(const CompilerDriver* compiler, + ImageWriter* image_writer, + const std::vector<const DexFile*>& dex_files) { + compiler_driver_ = compiler; + image_writer_ = image_writer; + dex_files_ = &dex_files; + } // Prepare layout of remaining data. - void PrepareLayout(const CompilerDriver* compiler, - ImageWriter* image_writer, - const std::vector<const DexFile*>& dex_files, - linker::MultiOatRelativePatcher* relative_patcher); + void PrepareLayout(linker::MultiOatRelativePatcher* relative_patcher); // Write the rest of .rodata section (ClassOffsets[], OatClass[], maps). bool WriteRodata(OutputStream* out); // Write the code to the .text section. @@ -239,6 +249,7 @@ class OatWriter { class InitImageMethodVisitor; class WriteCodeMethodVisitor; class WriteMapMethodVisitor; + class WriteQuickeningInfoMethodVisitor; // Visit all the methods in all the compiled dex files in their definition order // with a given DexMethodVisitor. @@ -325,6 +336,9 @@ class OatWriter { // Offset of section holding VerifierDeps inside Vdex. size_t vdex_verifier_deps_offset_; + // Offset of section holding quickening info inside Vdex. + size_t vdex_quickening_info_offset_; + // Size required for Oat data structures. size_t oat_size_; @@ -368,6 +382,8 @@ class OatWriter { uint32_t size_dex_file_; uint32_t size_verifier_deps_; uint32_t size_verifier_deps_alignment_; + uint32_t size_quickening_info_; + uint32_t size_quickening_info_alignment_; uint32_t size_interpreter_to_interpreter_bridge_; uint32_t size_interpreter_to_compiled_code_bridge_; uint32_t size_jni_dlsym_lookup_; diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 0ce13626a2..8bbe685ef9 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -1777,6 +1777,14 @@ class Dex2Oat FINAL { } } + // Initialize the writers with the compiler driver, image writer, and their + // dex files. The writers were created without those being there yet. + for (size_t i = 0, size = oat_files_.size(); i != size; ++i) { + std::unique_ptr<OatWriter>& oat_writer = oat_writers_[i]; + std::vector<const DexFile*>& dex_files = dex_files_per_oat_file_[i]; + oat_writer->Initialize(driver_.get(), image_writer_.get(), dex_files); + } + { TimingLogger::ScopedTiming t2("dex2oat Write VDEX", timings_); DCHECK(IsBootImage() || oat_files_.size() == 1u); @@ -1791,6 +1799,11 @@ class Dex2Oat FINAL { return false; } + if (!oat_writers_[i]->WriteQuickeningInfo(vdex_out.get())) { + LOG(ERROR) << "Failed to write quickening info into VDEX " << vdex_file->GetPath(); + return false; + } + // VDEX finalized, seek back to the beginning and write the header. if (!oat_writers_[i]->WriteVdexHeader(vdex_out.get())) { LOG(ERROR) << "Failed to write vdex header into VDEX " << vdex_file->GetPath(); @@ -1799,15 +1812,14 @@ class Dex2Oat FINAL { } } - linker::MultiOatRelativePatcher patcher(instruction_set_, instruction_set_features_.get()); { TimingLogger::ScopedTiming t2("dex2oat Write ELF", timings_); + linker::MultiOatRelativePatcher patcher(instruction_set_, instruction_set_features_.get()); for (size_t i = 0, size = oat_files_.size(); i != size; ++i) { std::unique_ptr<ElfWriter>& elf_writer = elf_writers_[i]; std::unique_ptr<OatWriter>& oat_writer = oat_writers_[i]; - std::vector<const DexFile*>& dex_files = dex_files_per_oat_file_[i]; - oat_writer->PrepareLayout(driver_.get(), image_writer_.get(), dex_files, &patcher); + oat_writer->PrepareLayout(&patcher); size_t rodata_size = oat_writer->GetOatHeader().GetExecutableOffset(); size_t text_size = oat_writer->GetOatSize() - rodata_size; diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index c7bf231e03..4e81d50ac2 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -64,6 +64,7 @@ #include "string_reference.h" #include "thread_list.h" #include "type_lookup_table.h" +#include "vdex_file.h" #include "verifier/method_verifier.h" #include "well_known_classes.h" @@ -1029,13 +1030,19 @@ class OatDumper { if (options_.absolute_addresses_) { vios->Stream() << StringPrintf("%p ", oat_method.GetVmapTable()); } - uint32_t vmap_table_offset = oat_method.GetVmapTableOffset(); + uint32_t vmap_table_offset = method_header == nullptr ? 0 : method_header->vmap_table_offset_; vios->Stream() << StringPrintf("(offset=0x%08x)\n", vmap_table_offset); - if (vmap_table_offset > oat_file_.Size()) { + + size_t vmap_table_offset_limit = + (kIsVdexEnabled && IsMethodGeneratedByDexToDexCompiler(oat_method, code_item)) + ? oat_file_.GetVdexFile()->Size() + : method_header->GetCode() - oat_file_.Begin(); + if (vmap_table_offset >= vmap_table_offset_limit) { vios->Stream() << StringPrintf("WARNING: " "vmap table offset 0x%08x is past end of file 0x%08zx. " "vmap table offset was loaded from offset 0x%08x.\n", - vmap_table_offset, oat_file_.Size(), + vmap_table_offset, + vmap_table_offset_limit, oat_method.GetVmapTableOffsetOffset()); success = false; } else if (options_.dump_vmap_) { diff --git a/runtime/art_method.cc b/runtime/art_method.cc index 3065f68fc4..c550a1b6bd 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -468,7 +468,18 @@ const uint8_t* ArtMethod::GetQuickenedInfo(PointerSize pointer_size) { if (!found || (oat_method.GetQuickCode() != nullptr)) { return nullptr; } - return oat_method.GetVmapTable(); + if (kIsVdexEnabled) { + const OatQuickMethodHeader* header = oat_method.GetOatQuickMethodHeader(); + // OatMethod without a header: no quickening table. + if (header == nullptr) { + return nullptr; + } + // The table is in the .vdex file. + const OatFile::OatDexFile* oat_dex_file = GetDexCache()->GetDexFile()->GetOatDexFile(); + return oat_dex_file->GetOatFile()->DexBegin() + header->vmap_table_offset_; + } else { + return oat_method.GetVmapTable(); + } } const OatQuickMethodHeader* ArtMethod::GetOatQuickMethodHeader(uintptr_t pc) { diff --git a/runtime/oat_file.h b/runtime/oat_file.h index b99bcb5f7d..63a0e14bf3 100644 --- a/runtime/oat_file.h +++ b/runtime/oat_file.h @@ -301,6 +301,10 @@ class OatFile { // error and sets found to false. static OatClass FindOatClass(const DexFile& dex_file, uint16_t class_def_idx, bool* found); + VdexFile* GetVdexFile() const { + return vdex_.get(); + } + protected: OatFile(const std::string& filename, bool executable); diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc index 9fbf87595b..b3dab581d5 100644 --- a/runtime/vdex_file.cc +++ b/runtime/vdex_file.cc @@ -34,9 +34,12 @@ bool VdexFile::Header::IsVersionValid() const { return (memcmp(version_, kVdexVersion, sizeof(kVdexVersion)) == 0); } -VdexFile::Header::Header(uint32_t dex_size, uint32_t verifier_deps_size) +VdexFile::Header::Header(uint32_t dex_size, + uint32_t verifier_deps_size, + uint32_t quickening_info_size) : dex_size_(dex_size), - verifier_deps_size_(verifier_deps_size) { + verifier_deps_size_(verifier_deps_size), + quickening_info_size_(quickening_info_size) { memcpy(magic_, kVdexMagic, sizeof(kVdexMagic)); memcpy(version_, kVdexVersion, sizeof(kVdexVersion)); DCHECK(IsMagicValid()); diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h index 6bea153d29..28f9bb3481 100644 --- a/runtime/vdex_file.h +++ b/runtime/vdex_file.h @@ -42,13 +42,14 @@ class VdexFile { public: struct Header { public: - Header(uint32_t dex_size, uint32_t verifier_deps_size); + Header(uint32_t dex_size, uint32_t verifier_deps_size, uint32_t quickening_info_size); bool IsMagicValid() const; bool IsVersionValid() const; uint32_t GetDexSize() const { return dex_size_; } uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; } + uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; } private: static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' }; @@ -58,6 +59,7 @@ class VdexFile { uint8_t version_[4]; uint32_t dex_size_; uint32_t verifier_deps_size_; + uint32_t quickening_info_size_; }; static VdexFile* Open(const std::string& vdex_filename, |