oat_writer.cc revision 1984651929744dd603fd082e23eacd877b9bc177
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 16e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 17e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat_writer.h" 18e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 19e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "class_linker.h" 20e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "class_loader.h" 21e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "file.h" 22e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "os.h" 23e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "stl_util.h" 24e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 25e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art { 26e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 27234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughesbool OatWriter::Create(File* file, 283320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const ClassLoader* class_loader, 2910037c866b04550fc5461058c398c2e3e509381ajeffhao const std::vector<const DexFile*>& dex_files, 303320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const Compiler& compiler) { 313320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom OatWriter oat_writer(dex_files, class_loader, compiler); 32234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes return oat_writer.Write(file); 33e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 34e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 353320cf46afd082398aa401b246e6f301cebdf64dBrian CarlstromOatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, 363320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const ClassLoader* class_loader, 373320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const Compiler& compiler) { 383320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom compiler_ = &compiler; 39e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_loader_ = class_loader; 40e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_files_ = &dex_files; 410571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers oat_header_ = NULL; 420571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers executable_offset_padding_length_ = 0; 43e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 44e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t offset = InitOatHeader(); 45e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatDexFiles(offset); 4689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom offset = InitDexFiles(offset); 47389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom offset = InitOatClasses(offset); 48e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCode(offset); 49e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCodeDexFiles(offset); 50e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 51e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK_EQ(dex_files_->size(), oat_dex_files_.size()); 52e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 53e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 540571d357843c53e042f370f5f2c2e9aa3fe803a9Ian RogersOatWriter::~OatWriter() { 550571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers delete oat_header_; 560571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers STLDeleteElements(&oat_dex_files_); 57389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom STLDeleteElements(&oat_classes_); 580571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers} 590571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 60e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatHeader() { 61e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // create the OatHeader 62e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header_ = new OatHeader(dex_files_); 63e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t offset = sizeof(*oat_header_); 64e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 65e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 66e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 67e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatDexFiles(size_t offset) { 68e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // create the OatDexFiles 69e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 70e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 71e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 72e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom OatDexFile* oat_dex_file = new OatDexFile(*dex_file); 73e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_dex_files_.push_back(oat_dex_file); 74e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset += oat_dex_file->SizeOf(); 75e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 76e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 77e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 78e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 7989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstromsize_t OatWriter::InitDexFiles(size_t offset) { 8089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // calculate the offsets within OatDexFiles to the DexFiles 8189521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 8289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // dex files are required to be 4 byte aligned 8389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom offset = RoundUp(offset, 4); 8489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 8589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // set offset in OatDexFile to DexFile 8689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom oat_dex_files_[i]->dex_file_offset_ = offset; 8789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 8889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 8989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom offset += dex_file->GetHeader().file_size_; 9089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 9189521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return offset; 9289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom} 9389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 94389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstromsize_t OatWriter::InitOatClasses(size_t offset) { 95389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom // create the OatClasses 96389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom // calculate the offsets within OatDexFiles to OatClasses 97e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 98e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 99e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t class_def_index = 0; 100e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index < dex_file->NumClassDefs(); 101c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers class_def_index++) { 1026e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom oat_dex_files_[i]->methods_offsets_[class_def_index] = offset; 103e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); 104e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file->GetClassData(class_def); 1050571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers uint32_t num_methods = 0; 1060571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (class_data != NULL) { // ie not an empty class, such as a marker interface 1070571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassDataItemIterator it(*dex_file, class_data); 1080571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t num_direct_methods = it.NumDirectMethods(); 1090571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t num_virtual_methods = it.NumVirtualMethods(); 1100571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers num_methods = num_direct_methods + num_virtual_methods; 1110571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 1120755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 1130755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom CompiledClass* compiled_class = 11411d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index)); 1150755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom Class::Status status = 1160755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady; 1170755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 1180755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom OatClass* oat_class = new OatClass(status, num_methods); 119389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom oat_classes_.push_back(oat_class); 120389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom offset += oat_class->SizeOf(); 121e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 1226e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom oat_dex_files_[i]->UpdateChecksum(*oat_header_); 123e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 124e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 125e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 126e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 127e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCode(size_t offset) { 128e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // calculate the offsets within OatHeader to executable code 129e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t old_offset = offset; 130e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // required to be on a new page boundary 131e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = RoundUp(offset, kPageSize); 132e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header_->SetExecutableOffset(offset); 133e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom executable_offset_padding_length_ = offset - old_offset; 134e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 135e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 136e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 137e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeDexFiles(size_t offset) { 138e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t oat_class_index = 0; 139e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 140e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 141e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 142e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCodeDexFile(offset, oat_class_index, *dex_file); 143e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 144e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 145e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 146e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 147e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeDexFile(size_t offset, 148e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t& oat_class_index, 149e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file) { 150ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes for (size_t class_def_index = 0; 151e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index < dex_file.NumClassDefs(); 152e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index++, oat_class_index++) { 153e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); 154c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers offset = InitOatCodeClassDef(offset, oat_class_index, class_def_index, dex_file, class_def); 155389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom oat_classes_[oat_class_index]->UpdateChecksum(*oat_header_); 156e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 157e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 158e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 159e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 160e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeClassDef(size_t offset, 161c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers size_t oat_class_index, size_t class_def_index, 162e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file, 163e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def) { 164e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file.GetClassData(class_def); 1650571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (class_data == NULL) { 1660571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // empty class, such as a marker interface 167387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers return offset; 168387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers } 1690571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassDataItemIterator it(dex_file, class_data); 170389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom CHECK_EQ(oat_classes_[oat_class_index]->method_offsets_.size(), 1710571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.NumDirectMethods() + it.NumVirtualMethods()); 1720571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Skip fields 1730571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextStaticField()) { 1740571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 175e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 1760571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextInstanceField()) { 1770571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 178e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 1790571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Process methods 1800571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t class_def_method_index = 0; 1810571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextDirectMethod()) { 1820571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0; 183c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0; 184c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers offset = InitOatCodeMethod(offset, oat_class_index, class_def_index, class_def_method_index, is_native, 185c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers is_static, true, it.GetMemberIndex(), &dex_file); 1860571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 1870571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 1880571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 1890571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextVirtualMethod()) { 1900571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers CHECK_EQ(it.GetMemberAccessFlags() & kAccStatic, 0U); 191c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0; 192c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers offset = InitOatCodeMethod(offset, oat_class_index, class_def_index, class_def_method_index, is_native, 193c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers false, false, it.GetMemberIndex(), &dex_file); 1940571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 1950571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 1960571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 1970571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK(!it.HasNext()); 198e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 199e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 200e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 201c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogerssize_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, size_t class_def_index, 202c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers size_t class_def_method_index, bool is_native, bool is_static, 203c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers bool is_direct, uint32_t method_idx, const DexFile* dex_file) { 2043320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // derived from CompiledMethod if available 2053320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t code_offset = 0; 2063320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t frame_size_in_bytes = kStackAlignment; 2073320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t core_spill_mask = 0; 2083320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t fp_spill_mask = 0; 2093320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t mapping_table_offset = 0; 2103320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t vmap_table_offset = 0; 211e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom uint32_t gc_map_offset = 0; 2123320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // derived from CompiledInvokeStub if available 2133320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t invoke_stub_offset = 0; 2143320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2150571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers CompiledMethod* compiled_method = 21611d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file, method_idx)); 2173320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_method != NULL) { 2183320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset = compiled_method->AlignCode(offset); 21906b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(offset, kArmAlignment); 2203320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& code = compiled_method->GetCode(); 2213320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t code_size = code.size() * sizeof(code[0]); 2223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t thumb_offset = compiled_method->CodeDelta(); 2233320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset = (code_size == 0) ? 0 : offset + thumb_offset; 22455d782146917f9afabc98aedcab4b5874a74e55cjeffhao 22555d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate code arrays 226f479dccf294c256181c7ec2884d215424ff5a900jeffhao std::map<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); 22755d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (code_iter != code_offsets_.end()) { 22855d782146917f9afabc98aedcab4b5874a74e55cjeffhao code_offset = code_iter->second; 22955d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 230f479dccf294c256181c7ec2884d215424ff5a900jeffhao code_offsets_.insert(std::pair<const std::vector<uint8_t>*, uint32_t>(&code, code_offset)); 23155d782146917f9afabc98aedcab4b5874a74e55cjeffhao offset += code_size; 23255d782146917f9afabc98aedcab4b5874a74e55cjeffhao oat_header_->UpdateChecksum(&code[0], code_size); 23355d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 2343320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2353320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); 2363320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom core_spill_mask = compiled_method->GetCoreSpillMask(); 2373320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom fp_spill_mask = compiled_method->GetFpSpillMask(); 238e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 2393320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2403320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += sizeof(frame_size_in_bytes); 2413320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&frame_size_in_bytes, sizeof(frame_size_in_bytes)); 2423320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2433320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += sizeof(core_spill_mask); 2443320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&core_spill_mask, sizeof(core_spill_mask)); 2453320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2463320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += sizeof(fp_spill_mask); 2473320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&fp_spill_mask, sizeof(fp_spill_mask)); 2483320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2493320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_method != NULL) { 2503320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); 2513320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); 2523320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom mapping_table_offset = (mapping_table_size == 0) ? 0 : offset; 25355d782146917f9afabc98aedcab4b5874a74e55cjeffhao 25455d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate mapping tables 255f479dccf294c256181c7ec2884d215424ff5a900jeffhao std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table); 25655d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (mapping_iter != mapping_table_offsets_.end()) { 25755d782146917f9afabc98aedcab4b5874a74e55cjeffhao mapping_table_offset = mapping_iter->second; 25855d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 259f479dccf294c256181c7ec2884d215424ff5a900jeffhao mapping_table_offsets_.insert(std::pair<const std::vector<uint32_t>*, uint32_t>(&mapping_table, mapping_table_offset)); 26055d782146917f9afabc98aedcab4b5874a74e55cjeffhao offset += mapping_table_size; 26155d782146917f9afabc98aedcab4b5874a74e55cjeffhao oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size); 26255d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 2633320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2643320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); 2653320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); 2663320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom vmap_table_offset = (vmap_table_size == 0) ? 0 : offset; 26755d782146917f9afabc98aedcab4b5874a74e55cjeffhao 26855d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate vmap tables 269f479dccf294c256181c7ec2884d215424ff5a900jeffhao std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table); 27055d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (vmap_iter != vmap_table_offsets_.end()) { 27155d782146917f9afabc98aedcab4b5874a74e55cjeffhao vmap_table_offset = vmap_iter->second; 27255d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 273f479dccf294c256181c7ec2884d215424ff5a900jeffhao vmap_table_offsets_.insert(std::pair<const std::vector<uint16_t>*, uint32_t>(&vmap_table, vmap_table_offset)); 27455d782146917f9afabc98aedcab4b5874a74e55cjeffhao offset += vmap_table_size; 27555d782146917f9afabc98aedcab4b5874a74e55cjeffhao oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size); 27655d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 277e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom 278e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap(); 279e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); 280e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom gc_map_offset = (gc_map_size == 0) ? 0 : offset; 281e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom 282c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers#ifndef NDEBUG 283c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers // We expect GC maps except when the class hasn't been verified or the method is native 284c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers CompiledClass* compiled_class = 28511d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index)); 286c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers Class::Status status = 287c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady; 288c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified) 289c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers << PrettyMethod(method_idx, *dex_file); 290c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers#endif 291c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers 292e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom // Deduplicate GC maps 293e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom std::map<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map); 294e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom if (gc_map_iter != gc_map_offsets_.end()) { 295e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom gc_map_offset = gc_map_iter->second; 296e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom } else { 297e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom gc_map_offsets_.insert(std::pair<const std::vector<uint8_t>*, uint32_t>(&gc_map, gc_map_offset)); 298e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom offset += gc_map_size; 299e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom oat_header_->UpdateChecksum(&gc_map[0], gc_map_size); 300e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom } 3013320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 3023320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 3030571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx)); 3040571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty); 3053320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_invoke_stub != NULL) { 3063320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet()); 30706b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(offset, kArmAlignment); 3083320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); 3093320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); 3103320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom invoke_stub_offset = (invoke_stub_size == 0) ? 0 : offset; 31155d782146917f9afabc98aedcab4b5874a74e55cjeffhao 31255d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate invoke stubs 313f479dccf294c256181c7ec2884d215424ff5a900jeffhao std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub); 31455d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (stub_iter != code_offsets_.end()) { 31555d782146917f9afabc98aedcab4b5874a74e55cjeffhao invoke_stub_offset = stub_iter->second; 31655d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 317f479dccf294c256181c7ec2884d215424ff5a900jeffhao code_offsets_.insert(std::pair<const std::vector<uint8_t>*, uint32_t>(&invoke_stub, invoke_stub_offset)); 31855d782146917f9afabc98aedcab4b5874a74e55cjeffhao offset += invoke_stub_size; 31955d782146917f9afabc98aedcab4b5874a74e55cjeffhao oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size); 32055d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 3213320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 3223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 323389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom oat_classes_[oat_class_index]->method_offsets_[class_def_method_index] 3243320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom = OatMethodOffsets(code_offset, 3253320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom frame_size_in_bytes, 3263320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom core_spill_mask, 3273320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom fp_spill_mask, 3283320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom mapping_table_offset, 3293320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom vmap_table_offset, 330e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom gc_map_offset, 3313320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom invoke_stub_offset); 3323320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 3330571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (compiler_->IsImage()) { 3340571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassLinker* linker = Runtime::Current()->GetClassLinker(); 3350571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DexCache* dex_cache = linker->FindDexCache(*dex_file); 3360571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers Method* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader_, 3370571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers is_direct); 3380571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers CHECK(method != NULL); 3390571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetFrameSizeInBytes(frame_size_in_bytes); 3400571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetCoreSpillMask(core_spill_mask); 3410571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetFpSpillMask(fp_spill_mask); 3420571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetOatMappingTableOffset(mapping_table_offset); 3431984651929744dd603fd082e23eacd877b9bc177Ian Rogers // Don't overwrite static method trampoline 3441984651929744dd603fd082e23eacd877b9bc177Ian Rogers if (!method->IsStatic() || method->IsConstructor() || 3451984651929744dd603fd082e23eacd877b9bc177Ian Rogers method->GetDeclaringClass()->IsInitialized()) { 3461984651929744dd603fd082e23eacd877b9bc177Ian Rogers method->SetOatCodeOffset(code_offset); 3471984651929744dd603fd082e23eacd877b9bc177Ian Rogers } else { 3481984651929744dd603fd082e23eacd877b9bc177Ian Rogers method->SetCode(Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()); 3491984651929744dd603fd082e23eacd877b9bc177Ian Rogers } 3500571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetOatVmapTableOffset(vmap_table_offset); 351e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom method->SetOatGcMapOffset(gc_map_offset); 3520571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetOatInvokeStubOffset(invoke_stub_offset); 3530571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 354e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 355e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 356e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 3573320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#define DCHECK_CODE_OFFSET() \ 3582a2ff56f2197b031ced66450e340f656c281c85fElliott Hughes DCHECK_EQ(static_cast<off_t>(code_offset), lseek(file->Fd(), 0, SEEK_CUR)) 3593320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 360234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughesbool OatWriter::Write(File* file) { 361e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(oat_header_, sizeof(*oat_header_))) { 362234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write oat header to " << file->name(); 363e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 364e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 365e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 366234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes if (!WriteTables(file)) { 367234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes LOG(ERROR) << "Failed to write oat tables to " << file->name(); 368e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 369e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 370e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 371234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes size_t code_offset = WriteCode(file); 372e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 373234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes LOG(ERROR) << "Failed to write oat code to " << file->name(); 374e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 375e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 376e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 377234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes code_offset = WriteCodeDexFiles(file, code_offset); 378e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 379234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes LOG(ERROR) << "Failed to write oat code for dex files to " << file->name(); 380e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 381e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 382e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 383e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 384e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 385e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 386e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatWriter::WriteTables(File* file) { 387e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 388e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!oat_dex_files_[i]->Write(file)) { 389234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write oat dex information to " << file->name(); 390e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 391e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 392e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 39389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 39489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom uint32_t expected_offset = oat_dex_files_[i]->dex_file_offset_; 3952a2ff56f2197b031ced66450e340f656c281c85fElliott Hughes off_t actual_offset = lseek(file->Fd(), expected_offset, SEEK_SET); 39689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom if (static_cast<uint32_t>(actual_offset) != expected_offset) { 39789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 39889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset 39989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom << " Expected: " << expected_offset << " File: " << dex_file->GetLocation(); 40089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 40189521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 40289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 40389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom if (!file->WriteFully(&dex_file->GetHeader(), dex_file->GetHeader().file_size_)) { 40489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom PLOG(ERROR) << "Failed to write dex file " << dex_file->GetLocation() << " to " << file->name(); 40589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 40689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 40789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 408389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom for (size_t i = 0; i != oat_classes_.size(); ++i) { 409389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom if (!oat_classes_[i]->Write(file)) { 410234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write oat methods information to " << file->name(); 411e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 412e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 413e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 414e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 415e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 416e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 417e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::WriteCode(File* file) { 418e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom uint32_t code_offset = oat_header_->GetExecutableOffset(); 4192a2ff56f2197b031ced66450e340f656c281c85fElliott Hughes off_t new_offset = lseek(file->Fd(), executable_offset_padding_length_, SEEK_CUR); 420e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (static_cast<uint32_t>(new_offset) != code_offset) { 4213320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset 422234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes << " Expected: " << code_offset << " File: " << file->name(); 423e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 424e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 4253320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 426e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 427e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 428e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 429e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::WriteCodeDexFiles(File* file, size_t code_offset) { 4300571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t oat_class_index = 0; 4316e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 432e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 433e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 4340571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset = WriteCodeDexFile(file, code_offset, oat_class_index, *dex_file); 435e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 436e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 437e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 438e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 439e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 440e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 441e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 4420571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogerssize_t OatWriter::WriteCodeDexFile(File* file, size_t code_offset, size_t& oat_class_index, 4430571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const DexFile& dex_file) { 4440571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); 4450571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_index++, oat_class_index++) { 446e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); 4470571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset = WriteCodeClassDef(file, code_offset, oat_class_index, dex_file, class_def); 448e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 449e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 450e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 451e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 452e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 453e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 454e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 4550571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersvoid OatWriter::ReportWriteFailure(const char* what, uint32_t method_idx, 4560571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const DexFile& dex_file, File* f) const { 4570571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers PLOG(ERROR) << "Failed to write " << what << " for " << PrettyMethod(method_idx, dex_file) 4580571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << " to " << f->name(); 459234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes} 460234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes 461e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::WriteCodeClassDef(File* file, 4620571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t code_offset, size_t oat_class_index, 463e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file, 464e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def) { 465e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file.GetClassData(class_def); 4660571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (class_data == NULL) { 4670571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // ie. an empty class such as a marker interface 468387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers return code_offset; 469387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers } 4700571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassDataItemIterator it(dex_file, class_data); 4710571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Skip fields 4720571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextStaticField()) { 4730571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 4740571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 4750571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextInstanceField()) { 4760571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 4770571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 4780571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Process methods 4790571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t class_def_method_index = 0; 4800571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextDirectMethod()) { 4810571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0; 4820571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index, 4830571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers is_static, it.GetMemberIndex(), dex_file); 484e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 485e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 486e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 4870571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 4880571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 489e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 4900571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextVirtualMethod()) { 4910571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index, 4920571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers false, it.GetMemberIndex(), dex_file); 493e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 494e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 495e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 4960571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 4970571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 498e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 499e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 500e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 501e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 5020571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogerssize_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_class_index, 5030571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t class_def_method_index, bool is_static, 5040571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers uint32_t method_idx, const DexFile& dex_file) { 5050571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const CompiledMethod* compiled_method = 50611d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file, method_idx)); 5070571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 5080571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers uint32_t frame_size_in_bytes = 0; 5090571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers uint32_t core_spill_mask = 0; 5100571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers uint32_t fp_spill_mask = 0; 5110571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 5120571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers OatMethodOffsets method_offsets = 513389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom oat_classes_[oat_class_index]->method_offsets_[class_def_method_index]; 5140571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 5150571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 5160571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (compiled_method != NULL) { // ie. not an abstract method 5173320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset); 518e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom uint32_t aligned_code_delta = aligned_code_offset - code_offset; 519e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (aligned_code_delta != 0) { 5202a2ff56f2197b031ced66450e340f656c281c85fElliott Hughes off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); 521e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { 5223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset 523234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes << " Expected: " << aligned_code_offset << " File: " << file->name(); 524e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 525e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 526e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom code_offset += aligned_code_delta; 5273320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 528e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 52906b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(code_offset, kArmAlignment); 5303320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& code = compiled_method->GetCode(); 5313320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t code_size = code.size() * sizeof(code[0]); 53255d782146917f9afabc98aedcab4b5874a74e55cjeffhao 53355d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate code arrays 53455d782146917f9afabc98aedcab4b5874a74e55cjeffhao size_t offset = code_offset + compiled_method->CodeDelta(); 535f479dccf294c256181c7ec2884d215424ff5a900jeffhao std::map<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); 5360571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) { 5370571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((code_size == 0 && method_offsets.code_offset_ == 0) 5380571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || code_iter->second == method_offsets.code_offset_) 5390571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 54055d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 5410571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((code_size == 0 && method_offsets.code_offset_ == 0) 5420571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || offset == method_offsets.code_offset_) 5430571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 54455d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (!file->WriteFully(&code[0], code_size)) { 5450571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("method code", method_idx, dex_file, file); 54655d782146917f9afabc98aedcab4b5874a74e55cjeffhao return false; 54755d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 54855d782146917f9afabc98aedcab4b5874a74e55cjeffhao code_offset += code_size; 549e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 5503320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 5510571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); 5520571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers core_spill_mask = compiled_method->GetCoreSpillMask(); 5530571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers fp_spill_mask = compiled_method->GetFpSpillMask(); 5543320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5553320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 5563320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&frame_size_in_bytes, sizeof(frame_size_in_bytes))) { 5570571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("method frame size", method_idx, dex_file, file); 5583320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 5593320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5603320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += sizeof(frame_size_in_bytes); 5613320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&core_spill_mask, sizeof(core_spill_mask))) { 5620571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("method core spill mask", method_idx, dex_file, file); 5633320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 5643320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5653320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += sizeof(core_spill_mask); 5663320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&fp_spill_mask, sizeof(fp_spill_mask))) { 5670571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("method fp spill mask", method_idx, dex_file, file); 5683320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 5693320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5703320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += sizeof(fp_spill_mask); 5713320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 5723320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_method != NULL) { 5733320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); 5743320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); 57555d782146917f9afabc98aedcab4b5874a74e55cjeffhao 57655d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate mapping tables 5770571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = 5780571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers mapping_table_offsets_.find(&mapping_table); 5790571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (mapping_iter != mapping_table_offsets_.end() && 5800571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset != method_offsets.mapping_table_offset_) { 5810571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) 5820571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || mapping_iter->second == method_offsets.mapping_table_offset_) 5830571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 58455d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 5850571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) 5860571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || code_offset == method_offsets.mapping_table_offset_) 5870571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 58855d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (!file->WriteFully(&mapping_table[0], mapping_table_size)) { 5890571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("mapping table", method_idx, dex_file, file); 59055d782146917f9afabc98aedcab4b5874a74e55cjeffhao return false; 59155d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 59255d782146917f9afabc98aedcab4b5874a74e55cjeffhao code_offset += mapping_table_size; 5933320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5943320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 5953320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 5963320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); 5973320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); 59855d782146917f9afabc98aedcab4b5874a74e55cjeffhao 59955d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate vmap tables 6000571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = 6010571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers vmap_table_offsets_.find(&vmap_table); 6020571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (vmap_iter != vmap_table_offsets_.end() && 6030571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset != method_offsets.vmap_table_offset_) { 6040571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) 6050571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || vmap_iter->second == method_offsets.vmap_table_offset_) 6060571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 60755d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 6080571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) 6090571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || code_offset == method_offsets.vmap_table_offset_) 6100571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 61155d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (!file->WriteFully(&vmap_table[0], vmap_table_size)) { 6120571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("vmap table", method_idx, dex_file, file); 61355d782146917f9afabc98aedcab4b5874a74e55cjeffhao return false; 61455d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 61555d782146917f9afabc98aedcab4b5874a74e55cjeffhao code_offset += vmap_table_size; 6163320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 6173320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 618e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom 619e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap(); 620e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); 621e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom 622e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom // Deduplicate GC maps 623e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom std::map<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = 624e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom gc_map_offsets_.find(&gc_map); 625e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom if (gc_map_iter != gc_map_offsets_.end() && 626e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom code_offset != method_offsets.gc_map_offset_) { 627e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0) 628e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom || gc_map_iter->second == method_offsets.gc_map_offset_) 629e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom << PrettyMethod(method_idx, dex_file); 630e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom } else { 631e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0) 632e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom || code_offset == method_offsets.gc_map_offset_) 633e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom << PrettyMethod(method_idx, dex_file); 634e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom if (!file->WriteFully(&gc_map[0], gc_map_size)) { 635e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom ReportWriteFailure("GC map", method_idx, dex_file, file); 636e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom return false; 637e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom } 638e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom code_offset += gc_map_size; 639e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom } 640e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom DCHECK_CODE_OFFSET(); 641e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 6420571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx)); 6430571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty); 6443320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_invoke_stub != NULL) { 6453320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset, 6463320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom compiler_->GetInstructionSet()); 6473320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t aligned_code_delta = aligned_code_offset - code_offset; 6483320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (aligned_code_delta != 0) { 6492a2ff56f2197b031ced66450e340f656c281c85fElliott Hughes off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); 6503320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { 6513320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset 6523320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom << " Expected: " << aligned_code_offset; 6533320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 6543320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 6553320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += aligned_code_delta; 6563320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 6573320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 65806b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(code_offset, kArmAlignment); 6593320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); 6603320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); 66155d782146917f9afabc98aedcab4b5874a74e55cjeffhao 66255d782146917f9afabc98aedcab4b5874a74e55cjeffhao // Deduplicate invoke stubs 6630571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = 6640571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offsets_.find(&invoke_stub); 6650571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (stub_iter != code_offsets_.end() && 6660571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers code_offset != method_offsets.invoke_stub_offset_) { 6670571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0) 6680571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || stub_iter->second == method_offsets.invoke_stub_offset_) 6690571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 67055d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 6710571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0) 6720571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers || code_offset == method_offsets.invoke_stub_offset_) 6730571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers << PrettyMethod(method_idx, dex_file); 67455d782146917f9afabc98aedcab4b5874a74e55cjeffhao if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) { 6750571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ReportWriteFailure("invoke stub code", method_idx, dex_file, file); 67655d782146917f9afabc98aedcab4b5874a74e55cjeffhao return false; 67755d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 67855d782146917f9afabc98aedcab4b5874a74e55cjeffhao code_offset += invoke_stub_size; 6793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 6803320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 6813320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 682e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 683e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 684e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 685e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatWriter::OatDexFile::OatDexFile(const DexFile& dex_file) { 686955724179c6c739524f610023287f56b24dc31deElliott Hughes const std::string& location(dex_file.GetLocation()); 687e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_size_ = location.size(); 688e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data()); 6895b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom dex_file_location_checksum_ = dex_file.GetLocationChecksum(); 69089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom dex_file_offset_ = 0; 6916e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom methods_offsets_.resize(dex_file.NumClassDefs()); 692e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 693e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 694e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::OatDexFile::SizeOf() const { 695e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return sizeof(dex_file_location_size_) 696e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom + dex_file_location_size_ 6975b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom + sizeof(dex_file_location_checksum_) 69889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom + sizeof(dex_file_offset_) 6996e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom + (sizeof(methods_offsets_[0]) * methods_offsets_.size()); 700e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 701e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 702e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid OatWriter::OatDexFile::UpdateChecksum(OatHeader& oat_header) const { 703e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header.UpdateChecksum(&dex_file_location_size_, sizeof(dex_file_location_size_)); 704e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header.UpdateChecksum(dex_file_location_data_, dex_file_location_size_); 7055b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom oat_header.UpdateChecksum(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_)); 70689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom oat_header.UpdateChecksum(&dex_file_offset_, sizeof(dex_file_offset_)); 7076e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom oat_header.UpdateChecksum(&methods_offsets_[0], 7086e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom sizeof(methods_offsets_[0]) * methods_offsets_.size()); 709e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 710e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 711e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatWriter::OatDexFile::Write(File* file) const { 712e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) { 713234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write dex file location length to " << file->name(); 714e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 715e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 716e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(dex_file_location_data_, dex_file_location_size_)) { 717234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write dex file location data to " << file->name(); 718e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 719e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 7205b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom if (!file->WriteFully(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_))) { 7215b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom PLOG(ERROR) << "Failed to write dex file location checksum to " << file->name(); 722e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 723e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 72489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom if (!file->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) { 72589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom PLOG(ERROR) << "Failed to write dex file offset to " << file->name(); 72689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 72789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 7286e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom if (!file->WriteFully(&methods_offsets_[0], 7296e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom sizeof(methods_offsets_[0]) * methods_offsets_.size())) { 730234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write methods offsets to " << file->name(); 731e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 732e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 733e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 734e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 735e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 7360755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian CarlstromOatWriter::OatClass::OatClass(Class::Status status, uint32_t methods_count) { 7370755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom status_ = status; 738e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom method_offsets_.resize(methods_count); 739e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 740e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 741389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstromsize_t OatWriter::OatClass::SizeOf() const { 7420755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom return sizeof(status_) 7430755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom + (sizeof(method_offsets_[0]) * method_offsets_.size()); 744e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 745e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 746389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstromvoid OatWriter::OatClass::UpdateChecksum(OatHeader& oat_header) const { 7470755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom oat_header.UpdateChecksum(&status_, sizeof(status_)); 7480755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom oat_header.UpdateChecksum(&method_offsets_[0], 7490755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom sizeof(method_offsets_[0]) * method_offsets_.size()); 750e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 751e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 752389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrombool OatWriter::OatClass::Write(File* file) const { 7530755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom if (!file->WriteFully(&status_, sizeof(status_))) { 7540755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom PLOG(ERROR) << "Failed to write class status to " << file->name(); 7550755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom return false; 7560755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom } 7570755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom if (!file->WriteFully(&method_offsets_[0], 7580755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom sizeof(method_offsets_[0]) * method_offsets_.size())) { 759234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes PLOG(ERROR) << "Failed to write method offsets to " << file->name(); 760e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 761e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 762e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 763e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 764e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 765e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} // namespace art 766