Refactor and clean up OatWriter and Dex2Oat.
This is in preparation for early writing of dex files
to oat file.
Change-Id: I31195f3c94eb8ff676c600c60bd35ae531f457b4
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 1347b37..5c5a63d 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -161,16 +161,11 @@
}
// 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 cda6240..c3a31ca 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -113,14 +113,9 @@
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 b8610d0..f995cd7 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -157,14 +157,9 @@
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 @@
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 e8e775f..2b2f0e8 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 @@
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() {
- delete oat_header_;
- STLDeleteElements(&oat_dex_files_);
- STLDeleteElements(&oat_classes_);
}
struct OatWriter::GcMapDataAccess {
@@ -326,6 +414,11 @@
: 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
<< 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 @@
}
}
- 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 @@
}
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 @@
<< 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 @@
}
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 @@
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_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::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 @@
// 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 @@
}
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 @@
}
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 @@
}
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 @@
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 @@
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::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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
+ 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 @@
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() {
- 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 @@
+ (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 6c46ebc..5feb5fc 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 @@
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 @@
~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 @@
}
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 @@
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 @@
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 @@
// 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 @@
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 9fb2245..66d5ac3 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