oat_writer.cc revision 0755ec5ea1dce0b549fc1adefeb52d89f119ebec
1e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom// Copyright 2011 Google Inc. All Rights Reserved. 2e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 3e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat_writer.h" 4e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 5e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "class_linker.h" 6e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "class_loader.h" 7e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "file.h" 8e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "os.h" 9e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "stl_util.h" 10e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 11e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art { 12e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 13234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughesbool OatWriter::Create(File* file, 143320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const ClassLoader* class_loader, 153320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const Compiler& compiler) { 16aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom const std::vector<const DexFile*>& dex_files = ClassLoader::GetCompileTimeClassPath(class_loader); 173320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom OatWriter oat_writer(dex_files, class_loader, compiler); 18234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes return oat_writer.Write(file); 19e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 20e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 213320cf46afd082398aa401b246e6f301cebdf64dBrian CarlstromOatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, 223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const ClassLoader* class_loader, 233320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const Compiler& compiler) { 243320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom compiler_ = &compiler; 25e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_loader_ = class_loader; 26e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_files_ = &dex_files; 270571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers oat_header_ = NULL; 280571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers executable_offset_padding_length_ = 0; 29e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 30e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t offset = InitOatHeader(); 31e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatDexFiles(offset); 3289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom offset = InitDexFiles(offset); 33389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom offset = InitOatClasses(offset); 34e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCode(offset); 35e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCodeDexFiles(offset); 36e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 37e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK_EQ(dex_files_->size(), oat_dex_files_.size()); 38e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 39e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 400571d357843c53e042f370f5f2c2e9aa3fe803a9Ian RogersOatWriter::~OatWriter() { 410571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers delete oat_header_; 420571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers STLDeleteElements(&oat_dex_files_); 43389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom STLDeleteElements(&oat_classes_); 440571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers} 450571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 46e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatHeader() { 47e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // create the OatHeader 48e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header_ = new OatHeader(dex_files_); 49e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t offset = sizeof(*oat_header_); 50e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 51e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 52e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 53e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatDexFiles(size_t offset) { 54e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // create the OatDexFiles 55e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 56e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 57e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 58e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom OatDexFile* oat_dex_file = new OatDexFile(*dex_file); 59e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_dex_files_.push_back(oat_dex_file); 60e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset += oat_dex_file->SizeOf(); 61e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 62e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 63e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 64e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 6589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstromsize_t OatWriter::InitDexFiles(size_t offset) { 6689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // calculate the offsets within OatDexFiles to the DexFiles 6789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 6889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // dex files are required to be 4 byte aligned 6989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom offset = RoundUp(offset, 4); 7089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 7189521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // set offset in OatDexFile to DexFile 7289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom oat_dex_files_[i]->dex_file_offset_ = offset; 7389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 7489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 7589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom offset += dex_file->GetHeader().file_size_; 7689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 7789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return offset; 7889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom} 7989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 80389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstromsize_t OatWriter::InitOatClasses(size_t offset) { 81389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom // create the OatClasses 82389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom // calculate the offsets within OatDexFiles to OatClasses 83e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t class_index = 0; 84e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 85e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 86e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t class_def_index = 0; 87e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index < dex_file->NumClassDefs(); 88e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index++, class_index++) { 896e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom oat_dex_files_[i]->methods_offsets_[class_def_index] = offset; 90e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); 91e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file->GetClassData(class_def); 920571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers uint32_t num_methods = 0; 930571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (class_data != NULL) { // ie not an empty class, such as a marker interface 940571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassDataItemIterator it(*dex_file, class_data); 950571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t num_direct_methods = it.NumDirectMethods(); 960571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t num_virtual_methods = it.NumVirtualMethods(); 970571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers num_methods = num_direct_methods + num_virtual_methods; 980571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 990755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 1000755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom CompiledClass* compiled_class = 1010755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom compiler_->GetCompiledClass(art::Compiler::MethodReference(dex_file, class_def_index)); 1020755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom Class::Status status = 1030755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady; 1040755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 1050755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom OatClass* oat_class = new OatClass(status, num_methods); 106389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom oat_classes_.push_back(oat_class); 107389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom offset += oat_class->SizeOf(); 108e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 1096e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom oat_dex_files_[i]->UpdateChecksum(*oat_header_); 110e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 111e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 112e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 113e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 114e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCode(size_t offset) { 115e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // calculate the offsets within OatHeader to executable code 116e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t old_offset = offset; 117e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // required to be on a new page boundary 118e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = RoundUp(offset, kPageSize); 119e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header_->SetExecutableOffset(offset); 120e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom executable_offset_padding_length_ = offset - old_offset; 121e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 122e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 123e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 124e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeDexFiles(size_t offset) { 125e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t oat_class_index = 0; 126e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 127e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 128e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 129e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCodeDexFile(offset, oat_class_index, *dex_file); 130e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 131e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 132e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 133e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 134e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeDexFile(size_t offset, 135e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t& oat_class_index, 136e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file) { 137389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom for (size_t class_def_index = 0; 138e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index < dex_file.NumClassDefs(); 139e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index++, oat_class_index++) { 140e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); 141e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCodeClassDef(offset, oat_class_index, dex_file, class_def); 142389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom oat_classes_[oat_class_index]->UpdateChecksum(*oat_header_); 143e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 144e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 145e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 146e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 147e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeClassDef(size_t offset, 148e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t oat_class_index, 149e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file, 150e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def) { 151e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file.GetClassData(class_def); 1520571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (class_data == NULL) { 1530571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // empty class, such as a marker interface 154387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers return offset; 155387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers } 1560571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassDataItemIterator it(dex_file, class_data); 157389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom CHECK_EQ(oat_classes_[oat_class_index]->method_offsets_.size(), 1580571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.NumDirectMethods() + it.NumVirtualMethods()); 1590571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Skip fields 1600571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextStaticField()) { 1610571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 162e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 1630571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextInstanceField()) { 1640571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 165e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 1660571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Process methods 1670571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t class_def_method_index = 0; 1680571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextDirectMethod()) { 1690571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0; 1700571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, is_static, true, 1710571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.GetMemberIndex(), &dex_file); 1720571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 1730571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 1740571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 1750571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextVirtualMethod()) { 1760571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers CHECK_EQ(it.GetMemberAccessFlags() & kAccStatic, 0U); 1770571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, false, false, 1780571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.GetMemberIndex(), &dex_file); 1790571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 1800571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 1810571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 1820571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK(!it.HasNext()); 183e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 184e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 185e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1860571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogerssize_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, 1870571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t class_def_method_index, bool is_static, bool is_direct, 1880571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers uint32_t method_idx, const DexFile* dex_file) { 1893320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // derived from CompiledMethod if available 1903320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t code_offset = 0; 1913320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t frame_size_in_bytes = kStackAlignment; 1923320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t core_spill_mask = 0; 1933320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t fp_spill_mask = 0; 1943320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t mapping_table_offset = 0; 1953320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t vmap_table_offset = 0; 1963320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // derived from CompiledInvokeStub if available 1973320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t invoke_stub_offset = 0; 1983320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 1990571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers CompiledMethod* compiled_method = 2000571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers compiler_->GetCompiledMethod(art::Compiler::MethodReference(dex_file, method_idx)); 2013320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_method != NULL) { 2023320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset = compiled_method->AlignCode(offset); 20306b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(offset, kArmAlignment); 2043320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& code = compiled_method->GetCode(); 2053320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t code_size = code.size() * sizeof(code[0]); 2063320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t thumb_offset = compiled_method->CodeDelta(); 2073320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset = (code_size == 0) ? 0 : offset + thumb_offset; 20855d782146917f9afabc98aedcab4b5874a74e55cjeffhao 20955d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate code arrays 210f479dccf294c256181c7ec2884d215424ff5a900jeffhao std::map<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); 21155d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (code_iter != code_offsets_.end()) { 21255d782146917f9afabc98aedcab4b5874a74e55cjeffhao code_offset = code_iter->second; 21355d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 214f479dccf294c256181c7ec2884d215424ff5a900jeffhao code_offsets_.insert(std::pair<const std::vector<uint8_t>*, uint32_t>(&code, code_offset)); 21555d782146917f9afabc98aedcab4b5874a74e55cjeffhao offset += code_size; 21655d782146917f9afabc98aedcab4b5874a74e55cjeffhao oat_header_->UpdateChecksum(&code[0], code_size); 21755d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 2183320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2193320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); 2203320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom core_spill_mask = compiled_method->GetCoreSpillMask(); 2213320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom fp_spill_mask = compiled_method->GetFpSpillMask(); 222e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 2233320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2243320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += sizeof(frame_size_in_bytes); 2253320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&frame_size_in_bytes, sizeof(frame_size_in_bytes)); 2263320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2273320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += sizeof(core_spill_mask); 2283320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&core_spill_mask, sizeof(core_spill_mask)); 2293320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2303320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += sizeof(fp_spill_mask); 2313320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&fp_spill_mask, sizeof(fp_spill_mask)); 2323320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2333320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_method != NULL) { 2343320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); 2353320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); 2363320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom mapping_table_offset = (mapping_table_size == 0) ? 0 : offset; 23755d782146917f9afabc98aedcab4b5874a74e55cjeffhao 23855d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate mapping tables 239f479dccf294c256181c7ec2884d215424ff5a900jeffhao std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table); 24055d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (mapping_iter != mapping_table_offsets_.end()) { 24155d782146917f9afabc98aedcab4b5874a74e55cjeffhao mapping_table_offset = mapping_iter->second; 24255d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 243f479dccf294c256181c7ec2884d215424ff5a900jeffhao mapping_table_offsets_.insert(std::pair<const std::vector<uint32_t>*, uint32_t>(&mapping_table, mapping_table_offset)); 24455d782146917f9afabc98aedcab4b5874a74e55cjeffhao offset += mapping_table_size; 24555d782146917f9afabc98aedcab4b5874a74e55cjeffhao oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size); 24655d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 2473320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2483320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); 2493320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); 2503320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom vmap_table_offset = (vmap_table_size == 0) ? 0 : offset; 25155d782146917f9afabc98aedcab4b5874a74e55cjeffhao 25255d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate vmap tables 253f479dccf294c256181c7ec2884d215424ff5a900jeffhao std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table); 25455d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (vmap_iter != vmap_table_offsets_.end()) { 25555d782146917f9afabc98aedcab4b5874a74e55cjeffhao vmap_table_offset = vmap_iter->second; 25655d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 257f479dccf294c256181c7ec2884d215424ff5a900jeffhao vmap_table_offsets_.insert(std::pair<const std::vector<uint16_t>*, uint32_t>(&vmap_table, vmap_table_offset)); 25855d782146917f9afabc98aedcab4b5874a74e55cjeffhao offset += vmap_table_size; 25955d782146917f9afabc98aedcab4b5874a74e55cjeffhao oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size); 26055d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 2613320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 2623320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2630571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx)); 2640571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty); 2653320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_invoke_stub != NULL) { 2663320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet()); 26706b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(offset, kArmAlignment); 2683320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); 2693320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); 2703320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom invoke_stub_offset = (invoke_stub_size == 0) ? 0 : offset; 27155d782146917f9afabc98aedcab4b5874a74e55cjeffhao 27255d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate invoke stubs 273f479dccf294c256181c7ec2884d215424ff5a900jeffhao std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub); 27455d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (stub_iter != code_offsets_.end()) { 27555d782146917f9afabc98aedcab4b5874a74e55cjeffhao invoke_stub_offset = stub_iter->second; 27655d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 277f479dccf294c256181c7ec2884d215424ff5a900jeffhao code_offsets_.insert(std::pair<const std::vector<uint8_t>*, uint32_t>(&invoke_stub, invoke_stub_offset)); 27855d782146917f9afabc98aedcab4b5874a74e55cjeffhao offset += invoke_stub_size; 27955d782146917f9afabc98aedcab4b5874a74e55cjeffhao oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size); 28055d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 2813320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 2823320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 283389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom oat_classes_[oat_class_index]->method_offsets_[class_def_method_index] 2843320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom = OatMethodOffsets(code_offset, 2853320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom frame_size_in_bytes, 2863320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom core_spill_mask, 2873320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom fp_spill_mask, 2883320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom mapping_table_offset, 2893320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom vmap_table_offset, 2903320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom invoke_stub_offset); 2913320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2920571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (compiler_->IsImage()) { 2930571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassLinker* linker = Runtime::Current()->GetClassLinker(); 2940571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DexCache* dex_cache = linker->FindDexCache(*dex_file); 2950571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers Method* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader_, 2960571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers is_direct); 2970571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers CHECK(method != NULL); 2980571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetFrameSizeInBytes(frame_size_in_bytes); 2990571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetCoreSpillMask(core_spill_mask); 3000571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetFpSpillMask(fp_spill_mask); 3010571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetOatMappingTableOffset(mapping_table_offset); 3020571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetOatCodeOffset(code_offset); 3030571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetOatVmapTableOffset(vmap_table_offset); 3040571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetOatInvokeStubOffset(invoke_stub_offset); 3050571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 306e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 307e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 308e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 3093320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#define DCHECK_CODE_OFFSET() \ 3102a2ff56f2197b031ced66450e340f656c281c85fElliott Hughes DCHECK_EQ(static_cast<off_t>(code_offset), lseek(file->Fd(), 0, SEEK_CUR)) 3113320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 312234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughesbool OatWriter::Write(File* file) { 313e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(oat_header_, sizeof(*oat_header_))) { 314234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write oat header to " << file->name(); 315e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 316e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 317e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 318234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes if (!WriteTables(file)) { 319234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes LOG(ERROR) << "Failed to write oat tables to " << file->name(); 320e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 321e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 322e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 323234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes size_t code_offset = WriteCode(file); 324e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 325234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes LOG(ERROR) << "Failed to write oat code to " << file->name(); 326e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 327e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 328e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 329234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes code_offset = WriteCodeDexFiles(file, code_offset); 330e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 331234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes LOG(ERROR) << "Failed to write oat code for dex files to " << file->name(); 332e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 333e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 334e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 335e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 336e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 337e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 338e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatWriter::WriteTables(File* file) { 339e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 340e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!oat_dex_files_[i]->Write(file)) { 341234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write oat dex information to " << file->name(); 342e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 343e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 344e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 34589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 34689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom uint32_t expected_offset = oat_dex_files_[i]->dex_file_offset_; 3472a2ff56f2197b031ced66450e340f656c281c85fElliott Hughes off_t actual_offset = lseek(file->Fd(), expected_offset, SEEK_SET); 34889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom if (static_cast<uint32_t>(actual_offset) != expected_offset) { 34989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 35089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset 35189521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom << " Expected: " << expected_offset << " File: " << dex_file->GetLocation(); 35289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 35389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 35489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 35589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom if (!file->WriteFully(&dex_file->GetHeader(), dex_file->GetHeader().file_size_)) { 35689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom PLOG(ERROR) << "Failed to write dex file " << dex_file->GetLocation() << " to " << file->name(); 35789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 35889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 35989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 360389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom for (size_t i = 0; i != oat_classes_.size(); ++i) { 361389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom if (!oat_classes_[i]->Write(file)) { 362234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write oat methods information to " << file->name(); 363e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 364e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 365e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 366e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 367e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 368e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 369e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::WriteCode(File* file) { 370e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom uint32_t code_offset = oat_header_->GetExecutableOffset(); 3712a2ff56f2197b031ced66450e340f656c281c85fElliott Hughes off_t new_offset = lseek(file->Fd(), executable_offset_padding_length_, SEEK_CUR); 372e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (static_cast<uint32_t>(new_offset) != code_offset) { 3733320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset 374234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes << " Expected: " << code_offset << " File: " << file->name(); 375e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 376e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 3773320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 378e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 379e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 380e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 381e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::WriteCodeDexFiles(File* file, size_t code_offset) { 3820571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t oat_class_index = 0; 3836e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 384e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 385e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 3860571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset = WriteCodeDexFile(file, code_offset, oat_class_index, *dex_file); 387e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 388e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 389e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 390e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 391e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 392e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 393e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 3940571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogerssize_t OatWriter::WriteCodeDexFile(File* file, size_t code_offset, size_t& oat_class_index, 3950571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const DexFile& dex_file) { 3960571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); 3970571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_index++, oat_class_index++) { 398e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); 3990571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset = WriteCodeClassDef(file, code_offset, oat_class_index, dex_file, class_def); 400e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 401e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 402e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 403e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 404e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 405e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 406e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 4070571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersvoid OatWriter::ReportWriteFailure(const char* what, uint32_t method_idx, 4080571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const DexFile& dex_file, File* f) const { 4090571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers PLOG(ERROR) << "Failed to write " << what << " for " << PrettyMethod(method_idx, dex_file) 4100571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << " to " << f->name(); 411234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes} 412234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes 413e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::WriteCodeClassDef(File* file, 4140571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t code_offset, size_t oat_class_index, 415e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file, 416e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def) { 417e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file.GetClassData(class_def); 4180571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (class_data == NULL) { 4190571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // ie. an empty class such as a marker interface 420387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers return code_offset; 421387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers } 4220571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassDataItemIterator it(dex_file, class_data); 4230571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Skip fields 4240571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextStaticField()) { 4250571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 4260571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 4270571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextInstanceField()) { 4280571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 4290571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 4300571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Process methods 4310571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t class_def_method_index = 0; 4320571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextDirectMethod()) { 4330571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0; 4340571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index, 4350571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers is_static, it.GetMemberIndex(), dex_file); 436e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 437e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 438e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 4390571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 4400571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 441e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 4420571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextVirtualMethod()) { 4430571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index, 4440571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers false, it.GetMemberIndex(), dex_file); 445e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 446e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 447e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 4480571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 4490571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 450e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 451e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 452e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 453e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 4540571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogerssize_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_class_index, 4550571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t class_def_method_index, bool is_static, 4560571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers uint32_t method_idx, const DexFile& dex_file) { 4570571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const CompiledMethod* compiled_method = 4580571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers compiler_->GetCompiledMethod(art::Compiler::MethodReference(&dex_file, method_idx)); 4590571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 4600571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers uint32_t frame_size_in_bytes = 0; 4610571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers uint32_t core_spill_mask = 0; 4620571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers uint32_t fp_spill_mask = 0; 4630571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 4640571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers OatMethodOffsets method_offsets = 465389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom oat_classes_[oat_class_index]->method_offsets_[class_def_method_index]; 4660571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 4670571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 4680571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (compiled_method != NULL) { // ie. not an abstract method 4693320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset); 470e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom uint32_t aligned_code_delta = aligned_code_offset - code_offset; 471e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (aligned_code_delta != 0) { 4722a2ff56f2197b031ced66450e340f656c281c85fElliott Hughes off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); 473e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { 4743320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset 475234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes << " Expected: " << aligned_code_offset << " File: " << file->name(); 476e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 477e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 478e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom code_offset += aligned_code_delta; 4793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 480e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 48106b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(code_offset, kArmAlignment); 4823320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& code = compiled_method->GetCode(); 4833320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t code_size = code.size() * sizeof(code[0]); 48455d782146917f9afabc98aedcab4b5874a74e55cjeffhao 48555d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate code arrays 48655d782146917f9afabc98aedcab4b5874a74e55cjeffhao size_t offset = code_offset + compiled_method->CodeDelta(); 487f479dccf294c256181c7ec2884d215424ff5a900jeffhao std::map<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); 4880571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) { 4890571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((code_size == 0 && method_offsets.code_offset_ == 0) 4900571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || code_iter->second == method_offsets.code_offset_) 4910571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 49255d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 4930571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((code_size == 0 && method_offsets.code_offset_ == 0) 4940571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || offset == method_offsets.code_offset_) 4950571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 49655d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (!file->WriteFully(&code[0], code_size)) { 4970571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("method code", method_idx, dex_file, file); 49855d782146917f9afabc98aedcab4b5874a74e55cjeffhao return false; 49955d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 50055d782146917f9afabc98aedcab4b5874a74e55cjeffhao code_offset += code_size; 501e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 5023320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 5030571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); 5040571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers core_spill_mask = compiled_method->GetCoreSpillMask(); 5050571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers fp_spill_mask = compiled_method->GetFpSpillMask(); 5063320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5073320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 5083320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&frame_size_in_bytes, sizeof(frame_size_in_bytes))) { 5090571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("method frame size", method_idx, dex_file, file); 5103320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 5113320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5123320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += sizeof(frame_size_in_bytes); 5133320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&core_spill_mask, sizeof(core_spill_mask))) { 5140571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("method core spill mask", method_idx, dex_file, file); 5153320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 5163320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5173320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += sizeof(core_spill_mask); 5183320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&fp_spill_mask, sizeof(fp_spill_mask))) { 5190571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("method fp spill mask", method_idx, dex_file, file); 5203320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 5213320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += sizeof(fp_spill_mask); 5233320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 5243320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_method != NULL) { 5253320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); 5263320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); 52755d782146917f9afabc98aedcab4b5874a74e55cjeffhao 52855d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate mapping tables 5290571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = 5300571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers mapping_table_offsets_.find(&mapping_table); 5310571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (mapping_iter != mapping_table_offsets_.end() && 5320571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset != method_offsets.mapping_table_offset_) { 5330571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) 5340571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || mapping_iter->second == method_offsets.mapping_table_offset_) 5350571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 53655d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 5370571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) 5380571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || code_offset == method_offsets.mapping_table_offset_) 5390571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 54055d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (!file->WriteFully(&mapping_table[0], mapping_table_size)) { 5410571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("mapping table", method_idx, dex_file, file); 54255d782146917f9afabc98aedcab4b5874a74e55cjeffhao return false; 54355d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 54455d782146917f9afabc98aedcab4b5874a74e55cjeffhao code_offset += mapping_table_size; 5453320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5463320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 5473320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 5483320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); 5493320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); 55055d782146917f9afabc98aedcab4b5874a74e55cjeffhao 55155d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate vmap tables 5520571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = 5530571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers vmap_table_offsets_.find(&vmap_table); 5540571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (vmap_iter != vmap_table_offsets_.end() && 5550571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset != method_offsets.vmap_table_offset_) { 5560571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) 5570571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || vmap_iter->second == method_offsets.vmap_table_offset_) 5580571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 55955d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 5600571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) 5610571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || code_offset == method_offsets.vmap_table_offset_) 5620571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 56355d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (!file->WriteFully(&vmap_table[0], vmap_table_size)) { 5640571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("vmap table", method_idx, dex_file, file); 56555d782146917f9afabc98aedcab4b5874a74e55cjeffhao return false; 56655d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 56755d782146917f9afabc98aedcab4b5874a74e55cjeffhao code_offset += vmap_table_size; 5683320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5693320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 570e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 5710571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx)); 5720571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty); 5733320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_invoke_stub != NULL) { 5743320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset, 5753320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom compiler_->GetInstructionSet()); 5763320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t aligned_code_delta = aligned_code_offset - code_offset; 5773320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (aligned_code_delta != 0) { 5782a2ff56f2197b031ced66450e340f656c281c85fElliott Hughes off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); 5793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { 5803320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset 5813320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom << " Expected: " << aligned_code_offset; 5823320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 5833320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5843320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += aligned_code_delta; 5853320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 5863320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 58706b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(code_offset, kArmAlignment); 5883320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); 5893320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); 59055d782146917f9afabc98aedcab4b5874a74e55cjeffhao 59155d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate invoke stubs 5920571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = 5930571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offsets_.find(&invoke_stub); 5940571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (stub_iter != code_offsets_.end() && 5950571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset != method_offsets.invoke_stub_offset_) { 5960571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0) 5970571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || stub_iter->second == method_offsets.invoke_stub_offset_) 5980571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 59955d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 6000571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0) 6010571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || code_offset == method_offsets.invoke_stub_offset_) 6020571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 60355d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) { 6040571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("invoke stub code", method_idx, dex_file, file); 60555d782146917f9afabc98aedcab4b5874a74e55cjeffhao return false; 60655d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 60755d782146917f9afabc98aedcab4b5874a74e55cjeffhao code_offset += invoke_stub_size; 6083320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 6093320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 6103320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 611e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 612e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 613e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 614e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatWriter::OatDexFile::OatDexFile(const DexFile& dex_file) { 615955724179c6c739524f610023287f56b24dc31deElliott Hughes const std::string& location(dex_file.GetLocation()); 616e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_size_ = location.size(); 617e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data()); 618e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_checksum_ = dex_file.GetHeader().checksum_; 61989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom dex_file_offset_ = 0; 6206e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom methods_offsets_.resize(dex_file.NumClassDefs()); 621e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 622e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 623e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::OatDexFile::SizeOf() const { 624e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return sizeof(dex_file_location_size_) 625e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom + dex_file_location_size_ 626e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom + sizeof(dex_file_checksum_) 62789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom + sizeof(dex_file_offset_) 6286e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom + (sizeof(methods_offsets_[0]) * methods_offsets_.size()); 629e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 630e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 631e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid OatWriter::OatDexFile::UpdateChecksum(OatHeader& oat_header) const { 632e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header.UpdateChecksum(&dex_file_location_size_, sizeof(dex_file_location_size_)); 633e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header.UpdateChecksum(dex_file_location_data_, dex_file_location_size_); 634e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header.UpdateChecksum(&dex_file_checksum_, sizeof(dex_file_checksum_)); 63589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom oat_header.UpdateChecksum(&dex_file_offset_, sizeof(dex_file_offset_)); 6366e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom oat_header.UpdateChecksum(&methods_offsets_[0], 6376e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom sizeof(methods_offsets_[0]) * methods_offsets_.size()); 638e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 639e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 640e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatWriter::OatDexFile::Write(File* file) const { 641e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) { 642234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write dex file location length to " << file->name(); 643e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 644e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 645e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(dex_file_location_data_, dex_file_location_size_)) { 646234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write dex file location data to " << file->name(); 647e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 648e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 649e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(&dex_file_checksum_, sizeof(dex_file_checksum_))) { 650234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write dex file checksum to " << file->name(); 651e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 652e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 65389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom if (!file->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) { 65489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom PLOG(ERROR) << "Failed to write dex file offset to " << file->name(); 65589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 65689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 6576e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom if (!file->WriteFully(&methods_offsets_[0], 6586e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom sizeof(methods_offsets_[0]) * methods_offsets_.size())) { 659234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write methods offsets to " << file->name(); 660e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 661e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 662e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 663e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 664e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 6650755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian CarlstromOatWriter::OatClass::OatClass(Class::Status status, uint32_t methods_count) { 6660755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom status_ = status; 667e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom method_offsets_.resize(methods_count); 668e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 669e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 670389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstromsize_t OatWriter::OatClass::SizeOf() const { 6710755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom return sizeof(status_) 6720755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom + (sizeof(method_offsets_[0]) * method_offsets_.size()); 673e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 674e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 675389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstromvoid OatWriter::OatClass::UpdateChecksum(OatHeader& oat_header) const { 6760755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom oat_header.UpdateChecksum(&status_, sizeof(status_)); 6770755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom oat_header.UpdateChecksum(&method_offsets_[0], 6780755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom sizeof(method_offsets_[0]) * method_offsets_.size()); 679e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 680e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 681389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrombool OatWriter::OatClass::Write(File* file) const { 6820755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom if (!file->WriteFully(&status_, sizeof(status_))) { 6830755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom PLOG(ERROR) << "Failed to write class status to " << file->name(); 6840755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom return false; 6850755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom } 6860755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom if (!file->WriteFully(&method_offsets_[0], 6870755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom sizeof(method_offsets_[0]) * method_offsets_.size())) { 688234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write method offsets to " << file->name(); 689e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 690e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 691e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 692e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 693e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 694e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} // namespace art 695