diff options
author | 2015-12-10 13:49:19 +0000 | |
---|---|---|
committer | 2015-12-10 19:42:52 +0000 | |
commit | 49b0f45d5a9023653ab00c355735910aa51ee0ba (patch) | |
tree | 655a013ab75ff1acbeae1e9113b1339f0fd14f2f | |
parent | 6d0aefdc1f536e093305e29770cf749acb3247e2 (diff) |
Refactor and clean up OatWriter and Dex2Oat.
This is in preparation for early writing of dex files
to oat file.
Change-Id: I31195f3c94eb8ff676c600c60bd35ae531f457b4
-rw-r--r-- | compiler/driver/compiler_driver.h | 15 | ||||
-rw-r--r-- | compiler/image_test.cc | 9 | ||||
-rw-r--r-- | compiler/oat_test.cc | 16 | ||||
-rw-r--r-- | compiler/oat_writer.cc | 310 | ||||
-rw-r--r-- | compiler/oat_writer.h | 121 | ||||
-rw-r--r-- | compiler/trampolines/trampoline_compiler.h | 12 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 279 | ||||
-rw-r--r-- | runtime/base/dchecked_vector.h | 2 | ||||
-rw-r--r-- | runtime/oat.cc | 114 | ||||
-rw-r--r-- | runtime/oat.h | 12 |
10 files changed, 458 insertions, 432 deletions
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 1347b37fa0..5c5a63dd84 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -161,16 +161,11 @@ class CompilerDriver { } // Generate the trampolines that are invoked by unresolved direct methods. - const std::vector<uint8_t>* CreateJniDlsymLookup() const - SHARED_REQUIRES(Locks::mutator_lock_); - const std::vector<uint8_t>* CreateQuickGenericJniTrampoline() const - SHARED_REQUIRES(Locks::mutator_lock_); - const std::vector<uint8_t>* CreateQuickImtConflictTrampoline() const - SHARED_REQUIRES(Locks::mutator_lock_); - const std::vector<uint8_t>* CreateQuickResolutionTrampoline() const - SHARED_REQUIRES(Locks::mutator_lock_); - const std::vector<uint8_t>* CreateQuickToInterpreterBridge() const - SHARED_REQUIRES(Locks::mutator_lock_); + const std::vector<uint8_t>* CreateJniDlsymLookup() const; + const std::vector<uint8_t>* CreateQuickGenericJniTrampoline() const; + const std::vector<uint8_t>* CreateQuickImtConflictTrampoline() const; + const std::vector<uint8_t>* CreateQuickResolutionTrampoline() const; + const std::vector<uint8_t>* CreateQuickToInterpreterBridge() const; CompiledClass* GetCompiledClass(ClassReference ref) const REQUIRES(!compiled_classes_lock_); diff --git a/compiler/image_test.cc b/compiler/image_test.cc index cda6240bd4..c3a31ca42a 100644 --- a/compiler/image_test.cc +++ b/compiler/image_test.cc @@ -113,14 +113,9 @@ TEST_F(ImageTest, WriteRead) { elf_writer->EndText(text); elf_writer->SetBssSize(oat_writer.GetBssSize()); - elf_writer->WriteDynamicSection(); - - ArrayRef<const dwarf::MethodDebugInfo> method_infos(oat_writer.GetMethodDebugInfo()); - elf_writer->WriteDebugInfo(method_infos); - - ArrayRef<const uintptr_t> patch_locations(oat_writer.GetAbsolutePatchLocations()); - elf_writer->WritePatchLocations(patch_locations); + elf_writer->WriteDebugInfo(oat_writer.GetMethodDebugInfo()); + elf_writer->WritePatchLocations(oat_writer.GetAbsolutePatchLocations()); success = elf_writer->End(); diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index b8610d0a7a..f995cd7f03 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -157,14 +157,9 @@ class OatTest : public CommonCompilerTest { elf_writer->EndText(text); elf_writer->SetBssSize(oat_writer.GetBssSize()); - elf_writer->WriteDynamicSection(); - - ArrayRef<const dwarf::MethodDebugInfo> method_infos(oat_writer.GetMethodDebugInfo()); - elf_writer->WriteDebugInfo(method_infos); - - ArrayRef<const uintptr_t> patch_locations(oat_writer.GetAbsolutePatchLocations()); - elf_writer->WritePatchLocations(patch_locations); + elf_writer->WriteDebugInfo(oat_writer.GetMethodDebugInfo()); + elf_writer->WritePatchLocations(oat_writer.GetAbsolutePatchLocations()); return elf_writer->End(); } @@ -269,14 +264,9 @@ TEST_F(OatTest, OatHeaderIsValid) { std::unique_ptr<const InstructionSetFeatures> insn_features( InstructionSetFeatures::FromVariant(insn_set, "default", &error_msg)); ASSERT_TRUE(insn_features.get() != nullptr) << error_msg; - std::vector<const DexFile*> dex_files; - uint32_t image_file_location_oat_checksum = 0; - uint32_t image_file_location_oat_begin = 0; std::unique_ptr<OatHeader> oat_header(OatHeader::Create(insn_set, insn_features.get(), - &dex_files, - image_file_location_oat_checksum, - image_file_location_oat_begin, + 0u, nullptr)); ASSERT_NE(oat_header.get(), nullptr); ASSERT_TRUE(oat_header->IsValid()); diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index e8e775f2c8..2b2f0e8c26 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -52,6 +52,97 @@ namespace art { +class OatWriter::OatClass { + public: + OatClass(size_t offset, + const dchecked_vector<CompiledMethod*>& compiled_methods, + uint32_t num_non_null_compiled_methods, + mirror::Class::Status status); + OatClass(OatClass&& src) = default; + size_t GetOatMethodOffsetsOffsetFromOatHeader(size_t class_def_method_index_) const; + size_t GetOatMethodOffsetsOffsetFromOatClass(size_t class_def_method_index_) const; + size_t SizeOf() const; + bool Write(OatWriter* oat_writer, OutputStream* out, const size_t file_offset) const; + + CompiledMethod* GetCompiledMethod(size_t class_def_method_index) const { + return compiled_methods_[class_def_method_index]; + } + + // Offset of start of OatClass from beginning of OatHeader. It is + // used to validate file position when writing. + size_t offset_; + + // CompiledMethods for each class_def_method_index, or null if no method is available. + dchecked_vector<CompiledMethod*> compiled_methods_; + + // Offset from OatClass::offset_ to the OatMethodOffsets for the + // class_def_method_index. If 0, it means the corresponding + // CompiledMethod entry in OatClass::compiled_methods_ should be + // null and that the OatClass::type_ should be kOatClassBitmap. + dchecked_vector<uint32_t> oat_method_offsets_offsets_from_oat_class_; + + // Data to write. + + static_assert(mirror::Class::Status::kStatusMax < (1 << 16), "class status won't fit in 16bits"); + int16_t status_; + + static_assert(OatClassType::kOatClassMax < (1 << 16), "oat_class type won't fit in 16bits"); + uint16_t type_; + + uint32_t method_bitmap_size_; + + // bit vector indexed by ClassDef method index. When + // OatClassType::type_ is kOatClassBitmap, a set bit indicates the + // method has an OatMethodOffsets in methods_offsets_, otherwise + // the entry was ommited to save space. If OatClassType::type_ is + // not is kOatClassBitmap, the bitmap will be null. + std::unique_ptr<BitVector> method_bitmap_; + + // OatMethodOffsets and OatMethodHeaders for each CompiledMethod + // present in the OatClass. Note that some may be missing if + // OatClass::compiled_methods_ contains null values (and + // oat_method_offsets_offsets_from_oat_class_ should contain 0 + // values in this case). + dchecked_vector<OatMethodOffsets> method_offsets_; + dchecked_vector<OatQuickMethodHeader> method_headers_; + + private: + size_t GetMethodOffsetsRawSize() const { + return method_offsets_.size() * sizeof(method_offsets_[0]); + } + + DISALLOW_COPY_AND_ASSIGN(OatClass); +}; + +class OatWriter::OatDexFile { + public: + OatDexFile(size_t offset, const DexFile& dex_file); + OatDexFile(OatDexFile&& src) = default; + + size_t SizeOf() const; + bool Write(OatWriter* oat_writer, OutputStream* out, const size_t file_offset) const; + + // Offset of start of OatDexFile from beginning of OatHeader. It is + // used to validate file position when writing. + size_t offset_; + + // Data to write. + uint32_t dex_file_location_size_; + const uint8_t* dex_file_location_data_; + uint32_t dex_file_location_checksum_; + uint32_t dex_file_offset_; + uint32_t lookup_table_offset_; + TypeLookupTable* lookup_table_; // Owned by the dex file. + dchecked_vector<uint32_t> class_offsets_; + + private: + size_t GetClassOffsetsRawSize() const { + return class_offsets_.size() * sizeof(class_offsets_[0]); + } + + DISALLOW_COPY_AND_ASSIGN(OatDexFile); +}; + #define DCHECK_OFFSET() \ DCHECK_EQ(static_cast<off_t>(file_offset + relative_offset), out->Seek(0, kSeekCurrent)) \ << "file_offset=" << file_offset << " relative_offset=" << relative_offset @@ -106,14 +197,14 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, size_oat_dex_file_location_data_(0), size_oat_dex_file_location_checksum_(0), size_oat_dex_file_offset_(0), - size_oat_dex_file_methods_offsets_(0), + size_oat_dex_file_lookup_table_offset_(0), + size_oat_dex_file_class_offsets_(0), + size_oat_lookup_table_alignment_(0), + size_oat_lookup_table_(0), size_oat_class_type_(0), size_oat_class_status_(0), size_oat_class_method_bitmaps_(0), size_oat_class_method_offsets_(0), - size_oat_lookup_table_alignment_(0), - size_oat_lookup_table_offset_(0), - size_oat_lookup_table_(0), method_offset_map_() { CHECK(key_value_store != nullptr); if (compiling_boot_image) { @@ -180,9 +271,6 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, } OatWriter::~OatWriter() { - delete oat_header_; - STLDeleteElements(&oat_dex_files_); - STLDeleteElements(&oat_classes_); } struct OatWriter::GcMapDataAccess { @@ -326,6 +414,11 @@ class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor { : DexMethodVisitor(writer, offset), compiled_methods_(), num_non_null_compiled_methods_(0u) { + size_t num_classes = 0u; + for (const OatDexFile& oat_dex_file : writer_->oat_dex_files_) { + num_classes += oat_dex_file.class_offsets_.size(); + } + writer_->oat_classes_.reserve(num_classes); compiled_methods_.reserve(256u); } @@ -364,16 +457,16 @@ class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor { status = mirror::Class::kStatusNotReady; } - OatClass* oat_class = new OatClass(offset_, compiled_methods_, - num_non_null_compiled_methods_, status); - writer_->oat_classes_.push_back(oat_class); - oat_class->UpdateChecksum(writer_->oat_header_); - offset_ += oat_class->SizeOf(); + writer_->oat_classes_.emplace_back(offset_, + compiled_methods_, + num_non_null_compiled_methods_, + status); + offset_ += writer_->oat_classes_.back().SizeOf(); return DexMethodVisitor::EndClass(); } private: - std::vector<CompiledMethod*> compiled_methods_; + dchecked_vector<CompiledMethod*> compiled_methods_; size_t num_non_null_compiled_methods_; }; @@ -396,7 +489,7 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) SHARED_REQUIRES(Locks::mutator_lock_) { - OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; + OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); if (compiled_method != nullptr) { @@ -583,7 +676,7 @@ class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor { bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it ATTRIBUTE_UNUSED) SHARED_REQUIRES(Locks::mutator_lock_) { - OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; + OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); if (compiled_method != nullptr) { @@ -600,7 +693,6 @@ class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor { DataAccess::SetOffset(oat_class, method_offsets_index_, offset_); dedupe_map_.PutBefore(lb, map.data(), offset_); offset_ += map_size; - writer_->oat_header_->UpdateChecksum(&map[0], map_size); } } ++method_offsets_index_; @@ -624,7 +716,7 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor { bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) SHARED_REQUIRES(Locks::mutator_lock_) { - OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; + OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); OatMethodOffsets offsets(0u); @@ -715,7 +807,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) SHARED_REQUIRES(Locks::mutator_lock_) { - OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; + OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); // No thread suspension since dex_cache_ that may get invalidated if that occurs. @@ -752,8 +844,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { << PrettyMethod(it.GetMemberIndex(), *dex_file_); const OatQuickMethodHeader& method_header = oat_class->method_headers_[method_offsets_index_]; - writer_->oat_header_->UpdateChecksum(&method_header, sizeof(method_header)); - if (!out->WriteFully(&method_header, sizeof(method_header))) { + if (!writer_->WriteData(out, &method_header, sizeof(method_header))) { ReportWriteFailure("method header", it); return false; } @@ -790,8 +881,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { } } - writer_->oat_header_->UpdateChecksum(quick_code.data(), code_size); - if (!out->WriteFully(quick_code.data(), code_size)) { + if (!writer_->WriteData(out, quick_code.data(), code_size)) { ReportWriteFailure("method code", it); return false; } @@ -945,7 +1035,7 @@ class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor { } bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) { - OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; + OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); if (compiled_method != nullptr) { // ie. not an abstract method @@ -963,7 +1053,7 @@ class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor { << map_size << " " << map_offset << " " << offset_ << " " << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " for " << DataAccess::Name(); if (map_size != 0u && map_offset == offset_) { - if (UNLIKELY(!out->WriteFully(&map[0], map_size))) { + if (UNLIKELY(!writer_->WriteData(out, map.data(), map_size))) { ReportWriteFailure(it); return false; } @@ -1028,12 +1118,12 @@ bool OatWriter::VisitDexMethods(DexMethodVisitor* visitor) { } size_t OatWriter::InitOatHeader() { - oat_header_ = OatHeader::Create(compiler_driver_->GetInstructionSet(), - compiler_driver_->GetInstructionSetFeatures(), - dex_files_, - image_file_location_oat_checksum_, - image_file_location_oat_begin_, - key_value_store_); + oat_header_.reset(OatHeader::Create(compiler_driver_->GetInstructionSet(), + compiler_driver_->GetInstructionSetFeatures(), + dchecked_integral_cast<uint32_t>(dex_files_->size()), + key_value_store_)); + oat_header_->SetImageFileLocationOatChecksum(image_file_location_oat_checksum_); + oat_header_->SetImageFileLocationOatDataBegin(image_file_location_oat_begin_); return oat_header_->GetHeaderSize(); } @@ -1043,9 +1133,8 @@ size_t OatWriter::InitOatDexFiles(size_t offset) { for (size_t i = 0; i != dex_files_->size(); ++i) { const DexFile* dex_file = (*dex_files_)[i]; CHECK(dex_file != nullptr); - OatDexFile* oat_dex_file = new OatDexFile(offset, *dex_file); - oat_dex_files_.push_back(oat_dex_file); - offset += oat_dex_file->SizeOf(); + oat_dex_files_.emplace_back(offset, *dex_file); + offset += oat_dex_files_.back().SizeOf(); } return offset; } @@ -1059,12 +1148,12 @@ size_t OatWriter::InitDexFiles(size_t offset) { size_dex_file_alignment_ += offset - original_offset; // set offset in OatDexFile to DexFile - oat_dex_files_[i]->dex_file_offset_ = offset; + oat_dex_files_[i].dex_file_offset_ = offset; const DexFile* dex_file = (*dex_files_)[i]; // Initialize type lookup table - oat_dex_files_[i]->lookup_table_ = dex_file->GetTypeLookupTable(); + oat_dex_files_[i].lookup_table_ = dex_file->GetTypeLookupTable(); offset += dex_file->GetHeader().file_size_; } @@ -1072,14 +1161,14 @@ size_t OatWriter::InitDexFiles(size_t offset) { } size_t OatWriter::InitLookupTables(size_t offset) { - for (OatDexFile* oat_dex_file : oat_dex_files_) { - if (oat_dex_file->lookup_table_ != nullptr) { + for (OatDexFile& oat_dex_file : oat_dex_files_) { + if (oat_dex_file.lookup_table_ != nullptr) { uint32_t aligned_offset = RoundUp(offset, 4); - oat_dex_file->lookup_table_offset_ = aligned_offset; + oat_dex_file.lookup_table_offset_ = aligned_offset; size_oat_lookup_table_alignment_ += aligned_offset - offset; - offset = aligned_offset + oat_dex_file->lookup_table_->RawDataLength(); + offset = aligned_offset + oat_dex_file.lookup_table_->RawDataLength(); } else { - oat_dex_file->lookup_table_offset_ = 0; + oat_dex_file.lookup_table_offset_ = 0; } } return offset; @@ -1094,13 +1183,12 @@ size_t OatWriter::InitOatClasses(size_t offset) { // Update oat_dex_files_. auto oat_class_it = oat_classes_.begin(); - for (OatDexFile* oat_dex_file : oat_dex_files_) { - for (uint32_t& method_offset : oat_dex_file->methods_offsets_) { + for (OatDexFile& oat_dex_file : oat_dex_files_) { + for (uint32_t& class_offset : oat_dex_file.class_offsets_) { DCHECK(oat_class_it != oat_classes_.end()); - method_offset = (*oat_class_it)->offset_; + class_offset = oat_class_it->offset_; ++oat_class_it; } - oat_dex_file->UpdateChecksum(oat_header_); } CHECK(oat_class_it == oat_classes_.end()); @@ -1184,17 +1272,14 @@ size_t OatWriter::InitOatCodeDexFiles(size_t offset) { } bool OatWriter::WriteRodata(OutputStream* out) { - const off_t raw_file_offset = out->Seek(0, kSeekCurrent); - if (raw_file_offset == (off_t) -1) { - LOG(ERROR) << "Failed to get file offset in " << out->GetLocation(); + if (!GetOatDataOffset(out)) { return false; } - const size_t file_offset = static_cast<size_t>(raw_file_offset); - oat_data_offset_ = file_offset; + const size_t file_offset = oat_data_offset_; // Reserve space for header. It will be written last - after updating the checksum. size_t header_size = oat_header_->GetHeaderSize(); - if (out->Seek(header_size, kSeekCurrent) == (off_t) -1) { + if (out->Seek(header_size, kSeekCurrent) == static_cast<off_t>(-1)) { PLOG(ERROR) << "Failed to reserve space for oat header in " << out->GetLocation(); return false; } @@ -1207,7 +1292,7 @@ bool OatWriter::WriteRodata(OutputStream* out) { } off_t tables_end_offset = out->Seek(0, kSeekCurrent); - if (tables_end_offset == (off_t) -1) { + if (tables_end_offset == static_cast<off_t>(-1)) { LOG(ERROR) << "Failed to seek to oat code position in " << out->GetLocation(); return false; } @@ -1252,7 +1337,7 @@ bool OatWriter::WriteCode(OutputStream* out) { } const off_t oat_end_file_offset = out->Seek(0, kSeekCurrent); - if (oat_end_file_offset == (off_t) -1) { + if (oat_end_file_offset == static_cast<off_t>(-1)) { LOG(ERROR) << "Failed to get oat end file offset in " << out->GetLocation(); return false; } @@ -1288,14 +1373,14 @@ bool OatWriter::WriteCode(OutputStream* out) { DO_STAT(size_oat_dex_file_location_data_); DO_STAT(size_oat_dex_file_location_checksum_); DO_STAT(size_oat_dex_file_offset_); - DO_STAT(size_oat_dex_file_methods_offsets_); + DO_STAT(size_oat_dex_file_lookup_table_offset_); + DO_STAT(size_oat_dex_file_class_offsets_); + DO_STAT(size_oat_lookup_table_alignment_); + DO_STAT(size_oat_lookup_table_); DO_STAT(size_oat_class_type_); DO_STAT(size_oat_class_status_); DO_STAT(size_oat_class_method_bitmaps_); DO_STAT(size_oat_class_method_offsets_); - DO_STAT(size_oat_lookup_table_alignment_); - DO_STAT(size_oat_lookup_table_offset_); - DO_STAT(size_oat_lookup_table_); #undef DO_STAT VLOG(compiler) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)"; \ @@ -1306,17 +1391,20 @@ bool OatWriter::WriteCode(OutputStream* out) { CHECK_EQ(file_offset + size_, static_cast<size_t>(oat_end_file_offset)); CHECK_EQ(size_, relative_offset); + // Finalize the header checksum. + oat_header_->UpdateChecksumWithHeaderData(); + // Write the header now that the checksum is final. - if (out->Seek(file_offset, kSeekSet) == (off_t) -1) { + if (out->Seek(file_offset, kSeekSet) == static_cast<off_t>(-1)) { PLOG(ERROR) << "Failed to seek to oat header position in " << out->GetLocation(); return false; } DCHECK_EQ(file_offset, static_cast<size_t>(out->Seek(0, kSeekCurrent))); - if (!out->WriteFully(oat_header_, header_size)) { + if (!out->WriteFully(oat_header_.get(), header_size)) { PLOG(ERROR) << "Failed to write oat header to " << out->GetLocation(); return false; } - if (out->Seek(oat_end_file_offset, kSeekSet) == (off_t) -1) { + if (out->Seek(oat_end_file_offset, kSeekSet) == static_cast<off_t>(-1)) { PLOG(ERROR) << "Failed to seek to end after writing oat header to " << out->GetLocation(); return false; } @@ -1327,13 +1415,13 @@ bool OatWriter::WriteCode(OutputStream* out) { bool OatWriter::WriteTables(OutputStream* out, const size_t file_offset) { for (size_t i = 0; i != oat_dex_files_.size(); ++i) { - if (!oat_dex_files_[i]->Write(this, out, file_offset)) { + if (!oat_dex_files_[i].Write(this, out, file_offset)) { PLOG(ERROR) << "Failed to write oat dex information to " << out->GetLocation(); return false; } } for (size_t i = 0; i != oat_dex_files_.size(); ++i) { - uint32_t expected_offset = file_offset + oat_dex_files_[i]->dex_file_offset_; + uint32_t expected_offset = file_offset + oat_dex_files_[i].dex_file_offset_; off_t actual_offset = out->Seek(expected_offset, kSeekSet); if (static_cast<uint32_t>(actual_offset) != expected_offset) { const DexFile* dex_file = (*dex_files_)[i]; @@ -1353,7 +1441,7 @@ bool OatWriter::WriteTables(OutputStream* out, const size_t file_offset) { return false; } for (size_t i = 0; i != oat_classes_.size(); ++i) { - if (!oat_classes_[i]->Write(this, out, file_offset)) { + if (!oat_classes_[i].Write(this, out, file_offset)) { PLOG(ERROR) << "Failed to write oat methods information to " << out->GetLocation(); return false; } @@ -1363,8 +1451,8 @@ bool OatWriter::WriteTables(OutputStream* out, const size_t file_offset) { bool OatWriter::WriteLookupTables(OutputStream* out, const size_t file_offset) { for (size_t i = 0; i < oat_dex_files_.size(); ++i) { - const uint32_t lookup_table_offset = oat_dex_files_[i]->lookup_table_offset_; - const TypeLookupTable* table = oat_dex_files_[i]->lookup_table_; + const uint32_t lookup_table_offset = oat_dex_files_[i].lookup_table_offset_; + const TypeLookupTable* table = oat_dex_files_[i].lookup_table_; DCHECK_EQ(lookup_table_offset == 0, table == nullptr); if (lookup_table_offset == 0) { continue; @@ -1378,7 +1466,7 @@ bool OatWriter::WriteLookupTables(OutputStream* out, const size_t file_offset) { return false; } if (table != nullptr) { - if (!out->WriteFully(table->RawData(), table->RawDataLength())) { + if (!WriteData(out, table->RawData(), table->RawDataLength())) { const DexFile* dex_file = (*dex_files_)[i]; PLOG(ERROR) << "Failed to write lookup table for " << dex_file->GetLocation() << " to " << out->GetLocation(); @@ -1427,7 +1515,7 @@ size_t OatWriter::WriteCode(OutputStream* out, const size_t file_offset, size_t uint32_t alignment_padding = aligned_offset - relative_offset; \ out->Seek(alignment_padding, kSeekCurrent); \ size_trampoline_alignment_ += alignment_padding; \ - if (!out->WriteFully(&(*field)[0], field->size())) { \ + if (!WriteData(out, field->data(), field->size())) { \ PLOG(ERROR) << "Failed to write " # field " to " << out->GetLocation(); \ return false; \ } \ @@ -1469,6 +1557,17 @@ size_t OatWriter::WriteCodeDexFiles(OutputStream* out, return relative_offset; } +bool OatWriter::GetOatDataOffset(OutputStream* out) { + // Get the elf file offset of the oat file. + const off_t raw_file_offset = out->Seek(0, kSeekCurrent); + if (raw_file_offset == static_cast<off_t>(-1)) { + LOG(ERROR) << "Failed to get file offset in " << out->GetLocation(); + return false; + } + oat_data_offset_ = static_cast<size_t>(raw_file_offset); + return true; +} + bool OatWriter::WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta) { static const uint8_t kPadding[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u @@ -1481,6 +1580,11 @@ bool OatWriter::WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delt return true; } +bool OatWriter::WriteData(OutputStream* out, const void* data, size_t size) { + oat_header_->UpdateChecksum(data, size); + return out->WriteFully(data, size); +} + std::pair<bool, uint32_t> OatWriter::MethodOffsetMap::FindMethodOffset(MethodReference ref) { auto it = map.find(ref); if (it == map.end()) { @@ -1498,7 +1602,7 @@ OatWriter::OatDexFile::OatDexFile(size_t offset, const DexFile& dex_file) { dex_file_location_checksum_ = dex_file.GetLocationChecksum(); dex_file_offset_ = 0; lookup_table_offset_ = 0; - methods_offsets_.resize(dex_file.NumClassDefs()); + class_offsets_.resize(dex_file.NumClassDefs()); } size_t OatWriter::OatDexFile::SizeOf() const { @@ -1507,63 +1611,50 @@ size_t OatWriter::OatDexFile::SizeOf() const { + sizeof(dex_file_location_checksum_) + sizeof(dex_file_offset_) + sizeof(lookup_table_offset_) - + (sizeof(methods_offsets_[0]) * methods_offsets_.size()); -} - -void OatWriter::OatDexFile::UpdateChecksum(OatHeader* oat_header) const { - oat_header->UpdateChecksum(&dex_file_location_size_, sizeof(dex_file_location_size_)); - oat_header->UpdateChecksum(dex_file_location_data_, dex_file_location_size_); - oat_header->UpdateChecksum(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_)); - oat_header->UpdateChecksum(&dex_file_offset_, sizeof(dex_file_offset_)); - oat_header->UpdateChecksum(&lookup_table_offset_, sizeof(lookup_table_offset_)); - if (lookup_table_ != nullptr) { - oat_header->UpdateChecksum(lookup_table_->RawData(), lookup_table_->RawDataLength()); - } - oat_header->UpdateChecksum(&methods_offsets_[0], - sizeof(methods_offsets_[0]) * methods_offsets_.size()); + + (sizeof(class_offsets_[0]) * class_offsets_.size()); } bool OatWriter::OatDexFile::Write(OatWriter* oat_writer, OutputStream* out, const size_t file_offset) const { DCHECK_OFFSET_(); - if (!out->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) { + if (!oat_writer->WriteData(out, &dex_file_location_size_, sizeof(dex_file_location_size_))) { PLOG(ERROR) << "Failed to write dex file location length to " << out->GetLocation(); return false; } oat_writer->size_oat_dex_file_location_size_ += sizeof(dex_file_location_size_); - if (!out->WriteFully(dex_file_location_data_, dex_file_location_size_)) { + if (!oat_writer->WriteData(out, dex_file_location_data_, dex_file_location_size_)) { PLOG(ERROR) << "Failed to write dex file location data to " << out->GetLocation(); return false; } oat_writer->size_oat_dex_file_location_data_ += dex_file_location_size_; - if (!out->WriteFully(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_))) { + if (!oat_writer->WriteData(out, + &dex_file_location_checksum_, + sizeof(dex_file_location_checksum_))) { PLOG(ERROR) << "Failed to write dex file location checksum to " << out->GetLocation(); return false; } oat_writer->size_oat_dex_file_location_checksum_ += sizeof(dex_file_location_checksum_); - if (!out->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) { + if (!oat_writer->WriteData(out, &dex_file_offset_, sizeof(dex_file_offset_))) { PLOG(ERROR) << "Failed to write dex file offset to " << out->GetLocation(); return false; } oat_writer->size_oat_dex_file_offset_ += sizeof(dex_file_offset_); - if (!out->WriteFully(&lookup_table_offset_, sizeof(lookup_table_offset_))) { + if (!oat_writer->WriteData(out, &lookup_table_offset_, sizeof(lookup_table_offset_))) { PLOG(ERROR) << "Failed to write lookup table offset to " << out->GetLocation(); return false; } - oat_writer->size_oat_lookup_table_offset_ += sizeof(lookup_table_offset_); - if (!out->WriteFully(&methods_offsets_[0], - sizeof(methods_offsets_[0]) * methods_offsets_.size())) { + oat_writer->size_oat_dex_file_lookup_table_offset_ += sizeof(lookup_table_offset_); + if (!oat_writer->WriteData(out, class_offsets_.data(), GetClassOffsetsRawSize())) { PLOG(ERROR) << "Failed to write methods offsets to " << out->GetLocation(); return false; } - oat_writer->size_oat_dex_file_methods_offsets_ += - sizeof(methods_offsets_[0]) * methods_offsets_.size(); + oat_writer->size_oat_dex_file_class_offsets_ += GetClassOffsetsRawSize(); return true; } OatWriter::OatClass::OatClass(size_t offset, - const std::vector<CompiledMethod*>& compiled_methods, + const dchecked_vector<CompiledMethod*>& compiled_methods, uint32_t num_non_null_compiled_methods, mirror::Class::Status status) : compiled_methods_(compiled_methods) { @@ -1593,7 +1684,7 @@ OatWriter::OatClass::OatClass(size_t offset, uint32_t oat_method_offsets_offset_from_oat_class = sizeof(type_) + sizeof(status_); if (type_ == kOatClassSomeCompiled) { - method_bitmap_ = new BitVector(num_methods, false, Allocator::GetMallocAllocator()); + method_bitmap_.reset(new BitVector(num_methods, false, Allocator::GetMallocAllocator())); method_bitmap_size_ = method_bitmap_->GetSizeOf(); oat_method_offsets_offset_from_oat_class += sizeof(method_bitmap_size_); oat_method_offsets_offset_from_oat_class += method_bitmap_size_; @@ -1616,10 +1707,6 @@ OatWriter::OatClass::OatClass(size_t offset, } } -OatWriter::OatClass::~OatClass() { - delete method_bitmap_; -} - size_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatHeader( size_t class_def_method_index_) const { uint32_t method_offset = GetOatMethodOffsetsOffsetFromOatClass(class_def_method_index_); @@ -1642,51 +1729,42 @@ size_t OatWriter::OatClass::SizeOf() const { + (sizeof(method_offsets_[0]) * method_offsets_.size()); } -void OatWriter::OatClass::UpdateChecksum(OatHeader* oat_header) const { - oat_header->UpdateChecksum(&status_, sizeof(status_)); - oat_header->UpdateChecksum(&type_, sizeof(type_)); - if (method_bitmap_size_ != 0) { - CHECK_EQ(kOatClassSomeCompiled, type_); - oat_header->UpdateChecksum(&method_bitmap_size_, sizeof(method_bitmap_size_)); - oat_header->UpdateChecksum(method_bitmap_->GetRawStorage(), method_bitmap_size_); - } - oat_header->UpdateChecksum(&method_offsets_[0], - sizeof(method_offsets_[0]) * method_offsets_.size()); -} - bool OatWriter::OatClass::Write(OatWriter* oat_writer, OutputStream* out, const size_t file_offset) const { DCHECK_OFFSET_(); - if (!out->WriteFully(&status_, sizeof(status_))) { + if (!oat_writer->WriteData(out, &status_, sizeof(status_))) { PLOG(ERROR) << "Failed to write class status to " << out->GetLocation(); return false; } oat_writer->size_oat_class_status_ += sizeof(status_); - if (!out->WriteFully(&type_, sizeof(type_))) { + + if (!oat_writer->WriteData(out, &type_, sizeof(type_))) { PLOG(ERROR) << "Failed to write oat class type to " << out->GetLocation(); return false; } oat_writer->size_oat_class_type_ += sizeof(type_); + if (method_bitmap_size_ != 0) { CHECK_EQ(kOatClassSomeCompiled, type_); - if (!out->WriteFully(&method_bitmap_size_, sizeof(method_bitmap_size_))) { + if (!oat_writer->WriteData(out, &method_bitmap_size_, sizeof(method_bitmap_size_))) { PLOG(ERROR) << "Failed to write method bitmap size to " << out->GetLocation(); return false; } oat_writer->size_oat_class_method_bitmaps_ += sizeof(method_bitmap_size_); - if (!out->WriteFully(method_bitmap_->GetRawStorage(), method_bitmap_size_)) { + + if (!oat_writer->WriteData(out, method_bitmap_->GetRawStorage(), method_bitmap_size_)) { PLOG(ERROR) << "Failed to write method bitmap to " << out->GetLocation(); return false; } oat_writer->size_oat_class_method_bitmaps_ += method_bitmap_size_; } - if (!out->WriteFully(&method_offsets_[0], - sizeof(method_offsets_[0]) * method_offsets_.size())) { + + if (!oat_writer->WriteData(out, method_offsets_.data(), GetMethodOffsetsRawSize())) { PLOG(ERROR) << "Failed to write method offsets to " << out->GetLocation(); return false; } - oat_writer->size_oat_class_method_offsets_ += sizeof(method_offsets_[0]) * method_offsets_.size(); + oat_writer->size_oat_class_method_offsets_ += GetMethodOffsetsRawSize(); return true; } diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h index 6c46ebc4ec..5feb5fc516 100644 --- a/compiler/oat_writer.h +++ b/compiler/oat_writer.h @@ -21,12 +21,14 @@ #include <cstddef> #include <memory> +#include "base/dchecked_vector.h" #include "linker/relative_patcher.h" // For linker::RelativePatcherTargetProvider. #include "mem_map.h" #include "method_reference.h" #include "mirror/class.h" #include "oat.h" #include "safe_map.h" +#include "utils/array_ref.h" namespace art { @@ -124,8 +126,8 @@ class OatWriter { return bss_size_; } - const std::vector<uintptr_t>& GetAbsolutePatchLocations() const { - return absolute_patch_locations_; + ArrayRef<const uintptr_t> GetAbsolutePatchLocations() const { + return ArrayRef<const uintptr_t>(absolute_patch_locations_); } bool WriteRodata(OutputStream* out); @@ -133,8 +135,8 @@ class OatWriter { ~OatWriter(); - const std::vector<dwarf::MethodDebugInfo>& GetMethodDebugInfo() const { - return method_info_; + ArrayRef<const dwarf::MethodDebugInfo> GetMethodDebugInfo() const { + return ArrayRef<const dwarf::MethodDebugInfo>(method_info_); } const CompilerDriver* GetCompilerDriver() { @@ -142,6 +144,9 @@ class OatWriter { } private: + class OatClass; + class OatDexFile; + // The DataAccess classes are helper classes that provide access to members related to // a given map, i.e. GC map, mapping table or vmap table. By abstracting these away // we can share a lot of code for processing the maps with template classes below. @@ -175,10 +180,8 @@ class OatWriter { size_t InitDexFiles(size_t offset); size_t InitOatClasses(size_t offset); size_t InitOatMaps(size_t offset); - size_t InitOatCode(size_t offset) - SHARED_REQUIRES(Locks::mutator_lock_); - size_t InitOatCodeDexFiles(size_t offset) - SHARED_REQUIRES(Locks::mutator_lock_); + size_t InitOatCode(size_t offset); + size_t InitOatCodeDexFiles(size_t offset); bool WriteTables(OutputStream* out, const size_t file_offset); bool WriteLookupTables(OutputStream* out, const size_t file_offset); @@ -186,93 +189,11 @@ class OatWriter { size_t WriteCode(OutputStream* out, const size_t file_offset, size_t relative_offset); size_t WriteCodeDexFiles(OutputStream* out, const size_t file_offset, size_t relative_offset); + bool GetOatDataOffset(OutputStream* out); bool WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta); + bool WriteData(OutputStream* out, const void* data, size_t size); - class OatDexFile { - public: - OatDexFile(size_t offset, const DexFile& dex_file); - size_t SizeOf() const; - void UpdateChecksum(OatHeader* oat_header) const; - bool Write(OatWriter* oat_writer, OutputStream* out, const size_t file_offset) const; - - // Offset of start of OatDexFile from beginning of OatHeader. It is - // used to validate file position when writing. - size_t offset_; - - // data to write - uint32_t dex_file_location_size_; - const uint8_t* dex_file_location_data_; - uint32_t dex_file_location_checksum_; - uint32_t dex_file_offset_; - uint32_t lookup_table_offset_; - TypeLookupTable* lookup_table_; // Owned by the dex file. - std::vector<uint32_t> methods_offsets_; - - private: - DISALLOW_COPY_AND_ASSIGN(OatDexFile); - }; - - class OatClass { - public: - OatClass(size_t offset, - const std::vector<CompiledMethod*>& compiled_methods, - uint32_t num_non_null_compiled_methods, - mirror::Class::Status status); - ~OatClass(); - size_t GetOatMethodOffsetsOffsetFromOatHeader(size_t class_def_method_index_) const; - size_t GetOatMethodOffsetsOffsetFromOatClass(size_t class_def_method_index_) const; - size_t SizeOf() const; - void UpdateChecksum(OatHeader* oat_header) const; - bool Write(OatWriter* oat_writer, OutputStream* out, const size_t file_offset) const; - - CompiledMethod* GetCompiledMethod(size_t class_def_method_index) const { - DCHECK_LT(class_def_method_index, compiled_methods_.size()); - return compiled_methods_[class_def_method_index]; - } - - // Offset of start of OatClass from beginning of OatHeader. It is - // used to validate file position when writing. - size_t offset_; - - // CompiledMethods for each class_def_method_index, or null if no method is available. - std::vector<CompiledMethod*> compiled_methods_; - - // Offset from OatClass::offset_ to the OatMethodOffsets for the - // class_def_method_index. If 0, it means the corresponding - // CompiledMethod entry in OatClass::compiled_methods_ should be - // null and that the OatClass::type_ should be kOatClassBitmap. - std::vector<uint32_t> oat_method_offsets_offsets_from_oat_class_; - - // data to write - - static_assert(mirror::Class::Status::kStatusMax < (2 ^ 16), "class status won't fit in 16bits"); - int16_t status_; - - static_assert(OatClassType::kOatClassMax < (2 ^ 16), "oat_class type won't fit in 16bits"); - uint16_t type_; - - uint32_t method_bitmap_size_; - - // bit vector indexed by ClassDef method index. When - // OatClassType::type_ is kOatClassBitmap, a set bit indicates the - // method has an OatMethodOffsets in methods_offsets_, otherwise - // the entry was ommited to save space. If OatClassType::type_ is - // not is kOatClassBitmap, the bitmap will be null. - BitVector* method_bitmap_; - - // OatMethodOffsets and OatMethodHeaders for each CompiledMethod - // present in the OatClass. Note that some may be missing if - // OatClass::compiled_methods_ contains null values (and - // oat_method_offsets_offsets_from_oat_class_ should contain 0 - // values in this case). - std::vector<OatMethodOffsets> method_offsets_; - std::vector<OatQuickMethodHeader> method_headers_; - - private: - DISALLOW_COPY_AND_ASSIGN(OatClass); - }; - - std::vector<dwarf::MethodDebugInfo> method_info_; + dchecked_vector<dwarf::MethodDebugInfo> method_info_; const CompilerDriver* const compiler_driver_; ImageWriter* const image_writer_; @@ -301,9 +222,9 @@ class OatWriter { // data to write SafeMap<std::string, std::string>* key_value_store_; - OatHeader* oat_header_; - std::vector<OatDexFile*> oat_dex_files_; - std::vector<OatClass*> oat_classes_; + std::unique_ptr<OatHeader> oat_header_; + dchecked_vector<OatDexFile> oat_dex_files_; + dchecked_vector<OatClass> oat_classes_; std::unique_ptr<const std::vector<uint8_t>> jni_dlsym_lookup_; std::unique_ptr<const std::vector<uint8_t>> quick_generic_jni_trampoline_; std::unique_ptr<const std::vector<uint8_t>> quick_imt_conflict_trampoline_; @@ -336,14 +257,14 @@ class OatWriter { uint32_t size_oat_dex_file_location_data_; uint32_t size_oat_dex_file_location_checksum_; uint32_t size_oat_dex_file_offset_; - uint32_t size_oat_dex_file_methods_offsets_; + uint32_t size_oat_dex_file_lookup_table_offset_; + uint32_t size_oat_dex_file_class_offsets_; + uint32_t size_oat_lookup_table_alignment_; + uint32_t size_oat_lookup_table_; uint32_t size_oat_class_type_; uint32_t size_oat_class_status_; uint32_t size_oat_class_method_bitmaps_; uint32_t size_oat_class_method_offsets_; - uint32_t size_oat_lookup_table_alignment_; - uint32_t size_oat_lookup_table_offset_; - uint32_t size_oat_lookup_table_; std::unique_ptr<linker::RelativePatcher> relative_patcher_; diff --git a/compiler/trampolines/trampoline_compiler.h b/compiler/trampolines/trampoline_compiler.h index 9fb22452ea..66d5ac3b53 100644 --- a/compiler/trampolines/trampoline_compiler.h +++ b/compiler/trampolines/trampoline_compiler.h @@ -25,12 +25,12 @@ namespace art { // Create code that will invoke the function held in thread local storage. -const std::vector<uint8_t>* CreateTrampoline32(InstructionSet isa, EntryPointCallingConvention abi, - ThreadOffset<4> entry_point_offset) - SHARED_REQUIRES(Locks::mutator_lock_); -const std::vector<uint8_t>* CreateTrampoline64(InstructionSet isa, EntryPointCallingConvention abi, - ThreadOffset<8> entry_point_offset) - SHARED_REQUIRES(Locks::mutator_lock_); +const std::vector<uint8_t>* CreateTrampoline32(InstructionSet isa, + EntryPointCallingConvention abi, + ThreadOffset<4> entry_point_offset); +const std::vector<uint8_t>* CreateTrampoline64(InstructionSet isa, + EntryPointCallingConvention abi, + ThreadOffset<8> entry_point_offset); } // namespace art diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 2aa4085fb1..d19d80b339 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -71,6 +71,7 @@ #include "oat_writer.h" #include "os.h" #include "runtime.h" +#include "runtime_options.h" #include "ScopedLocalRef.h" #include "scoped_thread_state_change.h" #include "utils.h" @@ -667,15 +668,14 @@ class Dex2Oat FINAL { parser_options->boot_image_filename += "/framework/boot.art"; } if (!parser_options->boot_image_filename.empty()) { - boot_image_option_ += "-Ximage:"; - boot_image_option_ += parser_options->boot_image_filename; + boot_image_filename_ = parser_options->boot_image_filename; } if (image_classes_filename_ != nullptr && !IsBootImage()) { Usage("--image-classes should only be used with --image"); } - if (image_classes_filename_ != nullptr && !boot_image_option_.empty()) { + if (image_classes_filename_ != nullptr && !boot_image_filename_.empty()) { Usage("--image-classes should not be used with --boot-image"); } @@ -687,7 +687,7 @@ class Dex2Oat FINAL { Usage("--compiled-classes should only be used with --image"); } - if (compiled_classes_filename_ != nullptr && !boot_image_option_.empty()) { + if (compiled_classes_filename_ != nullptr && !boot_image_filename_.empty()) { Usage("--compiled-classes should not be used with --boot-image"); } @@ -719,7 +719,7 @@ class Dex2Oat FINAL { Usage("--zip-location should be supplied with --zip-fd"); } - if (boot_image_option_.empty()) { + if (boot_image_filename_.empty()) { if (image_base_ == 0) { Usage("Non-zero --base not specified"); } @@ -1014,20 +1014,10 @@ class Dex2Oat FINAL { // boot class path. bool Setup() { TimingLogger::ScopedTiming t("dex2oat Setup", timings_); - RuntimeOptions runtime_options; art::MemMap::Init(); // For ZipEntry::ExtractToMemMap. - if (boot_image_option_.empty()) { - std::string boot_class_path = "-Xbootclasspath:"; - boot_class_path += Join(dex_filenames_, ':'); - runtime_options.push_back(std::make_pair(boot_class_path, nullptr)); - std::string boot_class_path_locations = "-Xbootclasspath-locations:"; - boot_class_path_locations += Join(dex_locations_, ':'); - runtime_options.push_back(std::make_pair(boot_class_path_locations, nullptr)); - } else { - runtime_options.push_back(std::make_pair(boot_image_option_, nullptr)); - } - for (size_t i = 0; i < runtime_args_.size(); i++) { - runtime_options.push_back(std::make_pair(runtime_args_[i], nullptr)); + + if (!PrepareImageClasses() || !PrepareCompiledClasses() || !PrepareCompiledMethods()) { + return false; } verification_results_.reset(new VerificationResults(compiler_options_.get())); @@ -1037,23 +1027,15 @@ class Dex2Oat FINAL { IsBootImage() ? CompilerCallbacks::CallbackMode::kCompileBootImage : CompilerCallbacks::CallbackMode::kCompileApp)); - runtime_options.push_back(std::make_pair("compilercallbacks", callbacks_.get())); - runtime_options.push_back( - std::make_pair("imageinstructionset", GetInstructionSetString(instruction_set_))); - // Only allow no boot image for the runtime if we're compiling one. When we compile an app, - // we don't want fallback mode, it will abort as we do not push a boot classpath (it might - // have been stripped in preopting, anyways). - if (!IsBootImage()) { - runtime_options.push_back(std::make_pair("-Xno-dex-file-fallback", nullptr)); + RuntimeArgumentMap runtime_options; + if (!PrepareRuntimeOptions(&runtime_options)) { + return false; } - // Disable libsigchain. We don't don't need it during compilation and it prevents us - // from getting a statically linked version of dex2oat (because of dlsym and RTLD_NEXT). - runtime_options.push_back(std::make_pair("-Xno-sig-chain", nullptr)); { TimingLogger::ScopedTiming t_runtime("Create runtime", timings_); - if (!CreateRuntime(runtime_options)) { + if (!CreateRuntime(std::move(runtime_options))) { return false; } } @@ -1068,66 +1050,8 @@ class Dex2Oat FINAL { // Whilst we're in native take the opportunity to initialize well known classes. WellKnownClasses::Init(self->GetJniEnv()); - // If --image-classes was specified, calculate the full list of classes to include in the image - if (image_classes_filename_ != nullptr) { - std::string error_msg; - if (image_classes_zip_filename_ != nullptr) { - image_classes_.reset(ReadImageClassesFromZip(image_classes_zip_filename_, - image_classes_filename_, - &error_msg)); - } else { - image_classes_.reset(ReadImageClassesFromFile(image_classes_filename_)); - } - if (image_classes_.get() == nullptr) { - LOG(ERROR) << "Failed to create list of image classes from '" << image_classes_filename_ << - "': " << error_msg; - return false; - } - } else if (IsBootImage()) { - image_classes_.reset(new std::unordered_set<std::string>); - } - // If --compiled-classes was specified, calculate the full list of classes to compile in the - // image. - if (compiled_classes_filename_ != nullptr) { - std::string error_msg; - if (compiled_classes_zip_filename_ != nullptr) { - compiled_classes_.reset(ReadImageClassesFromZip(compiled_classes_zip_filename_, - compiled_classes_filename_, - &error_msg)); - } else { - compiled_classes_.reset(ReadImageClassesFromFile(compiled_classes_filename_)); - } - if (compiled_classes_.get() == nullptr) { - LOG(ERROR) << "Failed to create list of compiled classes from '" - << compiled_classes_filename_ << "': " << error_msg; - return false; - } - } else { - compiled_classes_.reset(nullptr); // By default compile everything. - } - // If --compiled-methods was specified, read the methods to compile from the given file(s). - if (compiled_methods_filename_ != nullptr) { - std::string error_msg; - if (compiled_methods_zip_filename_ != nullptr) { - compiled_methods_.reset(ReadCommentedInputFromZip(compiled_methods_zip_filename_, - compiled_methods_filename_, - nullptr, // No post-processing. - &error_msg)); - } else { - compiled_methods_.reset(ReadCommentedInputFromFile(compiled_methods_filename_, - nullptr)); // No post-processing. - } - if (compiled_methods_.get() == nullptr) { - LOG(ERROR) << "Failed to create list of compiled methods from '" - << compiled_methods_filename_ << "': " << error_msg; - return false; - } - } else { - compiled_methods_.reset(nullptr); // By default compile everything. - } - ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); - if (boot_image_option_.empty()) { + if (boot_image_filename_.empty()) { dex_files_ = class_linker->GetBootClassPath(); } else { TimingLogger::ScopedTiming t_dex("Opening dex files", timings_); @@ -1164,22 +1088,7 @@ class Dex2Oat FINAL { constexpr bool kSaveDexInput = false; if (kSaveDexInput) { - for (size_t i = 0; i < dex_files_.size(); ++i) { - const DexFile* dex_file = dex_files_[i]; - std::string tmp_file_name(StringPrintf("/data/local/tmp/dex2oat.%d.%zd.dex", - getpid(), i)); - std::unique_ptr<File> tmp_file(OS::CreateEmptyFile(tmp_file_name.c_str())); - if (tmp_file.get() == nullptr) { - PLOG(ERROR) << "Failed to open file " << tmp_file_name - << ". Try: adb shell chmod 777 /data/local/tmp"; - continue; - } - // This is just dumping files for debugging. Ignore errors, and leave remnants. - UNUSED(tmp_file->WriteFully(dex_file->Begin(), dex_file->Size())); - UNUSED(tmp_file->Flush()); - UNUSED(tmp_file->Close()); - LOG(INFO) << "Wrote input to " << tmp_file_name; - } + SaveDexInput(); } } // Ensure opened dex files are writable for dex-to-dex transformations. Also ensure that @@ -1238,16 +1147,13 @@ class Dex2Oat FINAL { jobject class_path_class_loader = nullptr; Thread* self = Thread::Current(); - if (!boot_image_option_.empty()) { + if (!boot_image_filename_.empty()) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); OpenClassPathFiles(runtime_->GetClassPathString(), dex_files_, &class_path_files_); ScopedObjectAccess soa(self); // Classpath: first the class-path given. - std::vector<const DexFile*> class_path_files; - for (auto& class_path_file : class_path_files_) { - class_path_files.push_back(class_path_file.get()); - } + std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector(class_path_files_); // Store the classpath we have right now. key_value_store_->Put(OatHeader::kClassPathKey, @@ -1432,14 +1338,9 @@ class Dex2Oat FINAL { elf_writer->EndText(text); elf_writer->SetBssSize(oat_writer->GetBssSize()); - elf_writer->WriteDynamicSection(); - - ArrayRef<const dwarf::MethodDebugInfo> method_infos(oat_writer->GetMethodDebugInfo()); - elf_writer->WriteDebugInfo(method_infos); - - ArrayRef<const uintptr_t> patch_locations(oat_writer->GetAbsolutePatchLocations()); - elf_writer->WritePatchLocations(patch_locations); + elf_writer->WriteDebugInfo(oat_writer->GetMethodDebugInfo()); + elf_writer->WritePatchLocations(oat_writer->GetAbsolutePatchLocations()); if (!elf_writer->End()) { LOG(ERROR) << "Failed to write ELF file " << oat_file_->GetPath(); @@ -1552,6 +1453,16 @@ class Dex2Oat FINAL { } private: + template <typename T> + static std::vector<T*> MakeNonOwningPointerVector(const std::vector<std::unique_ptr<T>>& src) { + std::vector<T*> result; + result.reserve(src.size()); + for (const std::unique_ptr<T>& t : src) { + result.push_back(t.get()); + } + return result; + } + static size_t OpenDexFiles(const std::vector<const char*>& dex_filenames, const std::vector<const char*>& dex_locations, std::vector<std::unique_ptr<const DexFile>>* dex_files) { @@ -1612,10 +1523,138 @@ class Dex2Oat FINAL { } } + bool PrepareImageClasses() { + // If --image-classes was specified, calculate the full list of classes to include in the image. + if (image_classes_filename_ != nullptr) { + image_classes_ = + ReadClasses(image_classes_zip_filename_, image_classes_filename_, "image"); + if (image_classes_ == nullptr) { + return false; + } + } else if (IsBootImage()) { + image_classes_.reset(new std::unordered_set<std::string>); + } + return true; + } + + bool PrepareCompiledClasses() { + // If --compiled-classes was specified, calculate the full list of classes to compile in the + // image. + if (compiled_classes_filename_ != nullptr) { + compiled_classes_ = + ReadClasses(compiled_classes_zip_filename_, compiled_classes_filename_, "compiled"); + if (compiled_classes_ == nullptr) { + return false; + } + } else { + compiled_classes_.reset(nullptr); // By default compile everything. + } + return true; + } + + static std::unique_ptr<std::unordered_set<std::string>> ReadClasses(const char* zip_filename, + const char* classes_filename, + const char* tag) { + std::unique_ptr<std::unordered_set<std::string>> classes; + std::string error_msg; + if (zip_filename != nullptr) { + classes.reset(ReadImageClassesFromZip(zip_filename, classes_filename, &error_msg)); + } else { + classes.reset(ReadImageClassesFromFile(classes_filename)); + } + if (classes == nullptr) { + LOG(ERROR) << "Failed to create list of " << tag << " classes from '" + << classes_filename << "': " << error_msg; + } + return classes; + } + + bool PrepareCompiledMethods() { + // If --compiled-methods was specified, read the methods to compile from the given file(s). + if (compiled_methods_filename_ != nullptr) { + std::string error_msg; + if (compiled_methods_zip_filename_ != nullptr) { + compiled_methods_.reset(ReadCommentedInputFromZip(compiled_methods_zip_filename_, + compiled_methods_filename_, + nullptr, // No post-processing. + &error_msg)); + } else { + compiled_methods_.reset(ReadCommentedInputFromFile(compiled_methods_filename_, + nullptr)); // No post-processing. + } + if (compiled_methods_.get() == nullptr) { + LOG(ERROR) << "Failed to create list of compiled methods from '" + << compiled_methods_filename_ << "': " << error_msg; + return false; + } + } else { + compiled_methods_.reset(nullptr); // By default compile everything. + } + return true; + } + + void SaveDexInput() { + for (size_t i = 0; i < dex_files_.size(); ++i) { + const DexFile* dex_file = dex_files_[i]; + std::string tmp_file_name(StringPrintf("/data/local/tmp/dex2oat.%d.%zd.dex", + getpid(), i)); + std::unique_ptr<File> tmp_file(OS::CreateEmptyFile(tmp_file_name.c_str())); + if (tmp_file.get() == nullptr) { + PLOG(ERROR) << "Failed to open file " << tmp_file_name + << ". Try: adb shell chmod 777 /data/local/tmp"; + continue; + } + // This is just dumping files for debugging. Ignore errors, and leave remnants. + UNUSED(tmp_file->WriteFully(dex_file->Begin(), dex_file->Size())); + UNUSED(tmp_file->Flush()); + UNUSED(tmp_file->Close()); + LOG(INFO) << "Wrote input to " << tmp_file_name; + } + } + + bool PrepareRuntimeOptions(RuntimeArgumentMap* runtime_options) { + RuntimeOptions raw_options; + if (boot_image_filename_.empty()) { + std::string boot_class_path = "-Xbootclasspath:"; + boot_class_path += Join(dex_filenames_, ':'); + raw_options.push_back(std::make_pair(boot_class_path, nullptr)); + std::string boot_class_path_locations = "-Xbootclasspath-locations:"; + boot_class_path_locations += Join(dex_locations_, ':'); + raw_options.push_back(std::make_pair(boot_class_path_locations, nullptr)); + } else { + std::string boot_image_option = "-Ximage:"; + boot_image_option += boot_image_filename_; + raw_options.push_back(std::make_pair(boot_image_option, nullptr)); + } + for (size_t i = 0; i < runtime_args_.size(); i++) { + raw_options.push_back(std::make_pair(runtime_args_[i], nullptr)); + } + + raw_options.push_back(std::make_pair("compilercallbacks", callbacks_.get())); + raw_options.push_back( + std::make_pair("imageinstructionset", GetInstructionSetString(instruction_set_))); + + // Only allow no boot image for the runtime if we're compiling one. When we compile an app, + // we don't want fallback mode, it will abort as we do not push a boot classpath (it might + // have been stripped in preopting, anyways). + if (!IsBootImage()) { + raw_options.push_back(std::make_pair("-Xno-dex-file-fallback", nullptr)); + } + // Disable libsigchain. We don't don't need it during compilation and it prevents us + // from getting a statically linked version of dex2oat (because of dlsym and RTLD_NEXT). + raw_options.push_back(std::make_pair("-Xno-sig-chain", nullptr)); + + if (!Runtime::ParseOptions(raw_options, false, runtime_options)) { + LOG(ERROR) << "Failed to parse runtime options"; + return false; + } + return true; + } + // Create a runtime necessary for compilation. - bool CreateRuntime(const RuntimeOptions& runtime_options) + bool CreateRuntime(RuntimeArgumentMap&& runtime_options) SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) { - if (!Runtime::Create(runtime_options, false)) { + if (!Runtime::Create(std::move(runtime_options))) { LOG(ERROR) << "Failed to create runtime"; return false; } @@ -1812,7 +1851,7 @@ class Dex2Oat FINAL { std::vector<const char*> dex_locations_; int zip_fd_; std::string zip_location_; - std::string boot_image_option_; + std::string boot_image_filename_; std::vector<const char*> runtime_args_; std::string image_filename_; uintptr_t image_base_; diff --git a/runtime/base/dchecked_vector.h b/runtime/base/dchecked_vector.h index 2bd12df2c3..51dfba87eb 100644 --- a/runtime/base/dchecked_vector.h +++ b/runtime/base/dchecked_vector.h @@ -33,7 +33,7 @@ namespace art { // but we do not use exceptions, so this accessor is deliberately hidden. // Note: The common pattern &v[0] used to retrieve pointer to the data is not // valid for an empty dchecked_vector<>. Use data() to avoid checking empty(). -template <typename T, typename Alloc> +template <typename T, typename Alloc = std::allocator<T>> class dchecked_vector : private std::vector<T, Alloc> { private: // std::vector<> has a slightly different specialization for bool. We don't provide that. diff --git a/runtime/oat.cc b/runtime/oat.cc index 40aca0d249..c787b9adb1 100644 --- a/runtime/oat.cc +++ b/runtime/oat.cc @@ -45,9 +45,7 @@ static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* vari OatHeader* OatHeader::Create(InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features, - const std::vector<const DexFile*>* dex_files, - uint32_t image_file_location_oat_checksum, - uint32_t image_file_location_oat_data_begin, + uint32_t dex_file_count, const SafeMap<std::string, std::string>* variable_data) { // Estimate size of optional data. size_t needed_size = ComputeOatHeaderSize(variable_data); @@ -58,18 +56,29 @@ OatHeader* OatHeader::Create(InstructionSet instruction_set, // Create the OatHeader in-place. return new (memory) OatHeader(instruction_set, instruction_set_features, - dex_files, - image_file_location_oat_checksum, - image_file_location_oat_data_begin, + dex_file_count, variable_data); } OatHeader::OatHeader(InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features, - const std::vector<const DexFile*>* dex_files, - uint32_t image_file_location_oat_checksum, - uint32_t image_file_location_oat_data_begin, - const SafeMap<std::string, std::string>* variable_data) { + uint32_t dex_file_count, + const SafeMap<std::string, std::string>* variable_data) + : adler32_checksum_(adler32(0L, Z_NULL, 0)), + instruction_set_(instruction_set), + instruction_set_features_bitmap_(instruction_set_features->AsBitmap()), + dex_file_count_(dex_file_count), + executable_offset_(0), + interpreter_to_interpreter_bridge_offset_(0), + interpreter_to_compiled_code_bridge_offset_(0), + jni_dlsym_lookup_offset_(0), + quick_generic_jni_trampoline_offset_(0), + quick_imt_conflict_trampoline_offset_(0), + quick_resolution_trampoline_offset_(0), + quick_to_interpreter_bridge_offset_(0), + image_patch_delta_(0), + image_file_location_oat_checksum_(0), + image_file_location_oat_data_begin_(0) { // Don't want asserts in header as they would be checked in each file that includes it. But the // fields are private, so we check inside a method. static_assert(sizeof(magic_) == sizeof(kOatMagic), @@ -79,46 +88,11 @@ OatHeader::OatHeader(InstructionSet instruction_set, memcpy(magic_, kOatMagic, sizeof(kOatMagic)); memcpy(version_, kOatVersion, sizeof(kOatVersion)); - executable_offset_ = 0; - image_patch_delta_ = 0; - - adler32_checksum_ = adler32(0L, Z_NULL, 0); CHECK_NE(instruction_set, kNone); - instruction_set_ = instruction_set; - UpdateChecksum(&instruction_set_, sizeof(instruction_set_)); - - instruction_set_features_bitmap_ = instruction_set_features->AsBitmap(); - UpdateChecksum(&instruction_set_features_bitmap_, sizeof(instruction_set_features_bitmap_)); - - dex_file_count_ = dex_files->size(); - UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_)); - - image_file_location_oat_checksum_ = image_file_location_oat_checksum; - UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_)); - - CHECK_ALIGNED(image_file_location_oat_data_begin, kPageSize); - image_file_location_oat_data_begin_ = image_file_location_oat_data_begin; - UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_)); // Flatten the map. Will also update variable_size_data_size_. Flatten(variable_data); - - // Update checksum for variable data size. - UpdateChecksum(&key_value_store_size_, sizeof(key_value_store_size_)); - - // Update for data, if existing. - if (key_value_store_size_ > 0U) { - UpdateChecksum(&key_value_store_, key_value_store_size_); - } - - interpreter_to_interpreter_bridge_offset_ = 0; - interpreter_to_compiled_code_bridge_offset_ = 0; - jni_dlsym_lookup_offset_ = 0; - quick_generic_jni_trampoline_offset_ = 0; - quick_imt_conflict_trampoline_offset_ = 0; - quick_resolution_trampoline_offset_ = 0; - quick_to_interpreter_bridge_offset_ = 0; } bool OatHeader::IsValid() const { @@ -175,6 +149,37 @@ uint32_t OatHeader::GetChecksum() const { return adler32_checksum_; } +void OatHeader::UpdateChecksumWithHeaderData() { + UpdateChecksum(&instruction_set_, sizeof(instruction_set_)); + UpdateChecksum(&instruction_set_features_bitmap_, sizeof(instruction_set_features_bitmap_)); + UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_)); + UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_)); + UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_)); + + // Update checksum for variable data size. + UpdateChecksum(&key_value_store_size_, sizeof(key_value_store_size_)); + + // Update for data, if existing. + if (key_value_store_size_ > 0U) { + UpdateChecksum(&key_value_store_, key_value_store_size_); + } + + UpdateChecksum(&executable_offset_, sizeof(executable_offset_)); + UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, + sizeof(interpreter_to_interpreter_bridge_offset_)); + UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, + sizeof(interpreter_to_compiled_code_bridge_offset_)); + UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(jni_dlsym_lookup_offset_)); + UpdateChecksum(&quick_generic_jni_trampoline_offset_, + sizeof(quick_generic_jni_trampoline_offset_)); + UpdateChecksum(&quick_imt_conflict_trampoline_offset_, + sizeof(quick_imt_conflict_trampoline_offset_)); + UpdateChecksum(&quick_resolution_trampoline_offset_, + sizeof(quick_resolution_trampoline_offset_)); + UpdateChecksum(&quick_to_interpreter_bridge_offset_, + sizeof(quick_to_interpreter_bridge_offset_)); +} + void OatHeader::UpdateChecksum(const void* data, size_t length) { DCHECK(IsValid()); const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data); @@ -205,7 +210,6 @@ void OatHeader::SetExecutableOffset(uint32_t executable_offset) { DCHECK_EQ(executable_offset_, 0U); executable_offset_ = executable_offset; - UpdateChecksum(&executable_offset_, sizeof(executable_offset)); } const void* OatHeader::GetInterpreterToInterpreterBridge() const { @@ -225,7 +229,6 @@ void OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) { DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset; interpreter_to_interpreter_bridge_offset_ = offset; - UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, sizeof(offset)); } const void* OatHeader::GetInterpreterToCompiledCodeBridge() const { @@ -244,7 +247,6 @@ void OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) { DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset; interpreter_to_compiled_code_bridge_offset_ = offset; - UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, sizeof(offset)); } const void* OatHeader::GetJniDlsymLookup() const { @@ -263,7 +265,6 @@ void OatHeader::SetJniDlsymLookupOffset(uint32_t offset) { DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset; jni_dlsym_lookup_offset_ = offset; - UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(offset)); } const void* OatHeader::GetQuickGenericJniTrampoline() const { @@ -282,7 +283,6 @@ void OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) { DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset; quick_generic_jni_trampoline_offset_ = offset; - UpdateChecksum(&quick_generic_jni_trampoline_offset_, sizeof(offset)); } const void* OatHeader::GetQuickImtConflictTrampoline() const { @@ -301,7 +301,6 @@ void OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) { DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset; quick_imt_conflict_trampoline_offset_ = offset; - UpdateChecksum(&quick_imt_conflict_trampoline_offset_, sizeof(offset)); } const void* OatHeader::GetQuickResolutionTrampoline() const { @@ -320,7 +319,6 @@ void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) { DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset; quick_resolution_trampoline_offset_ = offset; - UpdateChecksum(&quick_resolution_trampoline_offset_, sizeof(offset)); } const void* OatHeader::GetQuickToInterpreterBridge() const { @@ -339,7 +337,6 @@ void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) { DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset; quick_to_interpreter_bridge_offset_ = offset; - UpdateChecksum(&quick_to_interpreter_bridge_offset_, sizeof(offset)); } int32_t OatHeader::GetImagePatchDelta() const { @@ -367,11 +364,22 @@ uint32_t OatHeader::GetImageFileLocationOatChecksum() const { return image_file_location_oat_checksum_; } +void OatHeader::SetImageFileLocationOatChecksum(uint32_t image_file_location_oat_checksum) { + CHECK(IsValid()); + image_file_location_oat_checksum_ = image_file_location_oat_checksum; +} + uint32_t OatHeader::GetImageFileLocationOatDataBegin() const { CHECK(IsValid()); return image_file_location_oat_data_begin_; } +void OatHeader::SetImageFileLocationOatDataBegin(uint32_t image_file_location_oat_data_begin) { + CHECK(IsValid()); + CHECK_ALIGNED(image_file_location_oat_data_begin, kPageSize); + image_file_location_oat_data_begin_ = image_file_location_oat_data_begin; +} + uint32_t OatHeader::GetKeyValueStoreSize() const { CHECK(IsValid()); return key_value_store_size_; diff --git a/runtime/oat.h b/runtime/oat.h index 5b780c38f8..a063b2b13e 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -45,15 +45,14 @@ class PACKED(4) OatHeader { static OatHeader* Create(InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features, - const std::vector<const DexFile*>* dex_files, - uint32_t image_file_location_oat_checksum, - uint32_t image_file_location_oat_data_begin, + uint32_t dex_file_count, const SafeMap<std::string, std::string>* variable_data); bool IsValid() const; std::string GetValidationErrorMessage() const; const char* GetMagic() const; uint32_t GetChecksum() const; + void UpdateChecksumWithHeaderData(); void UpdateChecksum(const void* data, size_t length); uint32_t GetDexFileCount() const { DCHECK(IsValid()); @@ -92,8 +91,11 @@ class PACKED(4) OatHeader { InstructionSet GetInstructionSet() const; uint32_t GetInstructionSetFeaturesBitmap() const; + uint32_t GetImageFileLocationOatChecksum() const; + void SetImageFileLocationOatChecksum(uint32_t image_file_location_oat_checksum); uint32_t GetImageFileLocationOatDataBegin() const; + void SetImageFileLocationOatDataBegin(uint32_t image_file_location_oat_data_begin); uint32_t GetKeyValueStoreSize() const; const uint8_t* GetKeyValueStore() const; @@ -107,9 +109,7 @@ class PACKED(4) OatHeader { private: OatHeader(InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features, - const std::vector<const DexFile*>* dex_files, - uint32_t image_file_location_oat_checksum, - uint32_t image_file_location_oat_data_begin, + uint32_t dex_file_count, const SafeMap<std::string, std::string>* variable_data); // Returns true if the value of the given key is "true", false otherwise. |