oat_writer.cc revision 661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8
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 19a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes#include <zlib.h> 20a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes 21ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom#include "base/bit_vector.h" 221aa246dec5abe212f699de1413a0c4a191ca364aElliott Hughes#include "base/stl_util.h" 23761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h" 24e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "class_linker.h" 254f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 26c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "dex/verification_results.h" 271d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space.h" 28ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h" 292dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/array.h" 302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h" 314f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h" 32e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "os.h" 33cd60ac736bc7104785dc67671660d70fb434466fBrian Carlstrom#include "output_stream.h" 34a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes#include "safe_map.h" 3500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 36ec0142313a470edecf52b4f034433404b7264358jeffhao#include "verifier/method_verifier.h" 37e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 38e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art { 39e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 403320cf46afd082398aa401b246e6f301cebdf64dBrian CarlstromOatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, 4128db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom uint32_t image_file_location_oat_checksum, 42ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uintptr_t image_file_location_oat_begin, 4381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom const std::string& image_file_location, 44ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers const CompilerDriver* compiler, 45ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers TimingLogger* timings) 460aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao : compiler_driver_(compiler), 470aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao dex_files_(&dex_files), 480aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao image_file_location_oat_checksum_(image_file_location_oat_checksum), 490aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao image_file_location_oat_begin_(image_file_location_oat_begin), 500aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao image_file_location_(image_file_location), 510aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_header_(NULL), 520aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_dex_file_alignment_(0), 530aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_executable_offset_alignment_(0), 540aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_header_(0), 550aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_header_image_file_location_(0), 560aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_dex_file_(0), 57848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_interpreter_to_interpreter_bridge_(0), 58848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_interpreter_to_compiled_code_bridge_(0), 59848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_jni_dlsym_lookup_(0), 6088474b416eb257078e590bf9bc7957cee604a186Jeff Hao size_portable_imt_conflict_trampoline_(0), 610aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_portable_resolution_trampoline_(0), 62848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_portable_to_interpreter_bridge_(0), 632da882315a61072664f7ce3c212307342e907207Andreas Gampe size_quick_generic_jni_trampoline_(0), 6488474b416eb257078e590bf9bc7957cee604a186Jeff Hao size_quick_imt_conflict_trampoline_(0), 650aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_quick_resolution_trampoline_(0), 66848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_quick_to_interpreter_bridge_(0), 67848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_trampoline_alignment_(0), 680aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_code_size_(0), 690aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_code_(0), 700aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_code_alignment_(0), 710aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_mapping_table_(0), 720aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_vmap_table_(0), 730aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_gc_map_(0), 740aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_dex_file_location_size_(0), 750aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_dex_file_location_data_(0), 760aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_dex_file_location_checksum_(0), 770aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_dex_file_offset_(0), 780aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_dex_file_methods_offsets_(0), 79ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_oat_class_type_(0), 800aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_class_status_(0), 81ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_oat_class_method_bitmaps_(0), 820aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_class_method_offsets_(0) { 83ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers size_t offset; 84ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 85ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers TimingLogger::ScopedSplit split("InitOatHeader", timings); 86ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitOatHeader(); 87ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 88ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 89ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers TimingLogger::ScopedSplit split("InitOatDexFiles", timings); 90ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitOatDexFiles(offset); 91ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 92ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 93ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers TimingLogger::ScopedSplit split("InitDexFiles", timings); 94ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitDexFiles(offset); 95ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 96ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 97ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers TimingLogger::ScopedSplit split("InitOatClasses", timings); 98ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitOatClasses(offset); 99ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 100ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 101ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers TimingLogger::ScopedSplit split("InitOatCode", timings); 102ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitOatCode(offset); 103ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 104ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 105ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers TimingLogger::ScopedSplit split("InitOatCodeDexFiles", timings); 106ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitOatCodeDexFiles(offset); 107ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 108c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom size_ = offset; 109e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 110e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK_EQ(dex_files_->size(), oat_dex_files_.size()); 1110aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao CHECK(image_file_location.empty() == compiler->IsImage()); 112e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 113e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1140571d357843c53e042f370f5f2c2e9aa3fe803a9Ian RogersOatWriter::~OatWriter() { 1150571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers delete oat_header_; 1160571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers STLDeleteElements(&oat_dex_files_); 117389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom STLDeleteElements(&oat_classes_); 1180571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers} 1190571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 12081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstromsize_t OatWriter::InitOatHeader() { 121e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // create the OatHeader 1221212a022fa5f8ef9585d765b1809521812af882cIan Rogers oat_header_ = new OatHeader(compiler_driver_->GetInstructionSet(), 1237020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison compiler_driver_->GetInstructionSetFeatures(), 12481f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom dex_files_, 12528db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom image_file_location_oat_checksum_, 12628db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom image_file_location_oat_begin_, 12781f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom image_file_location_); 128e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t offset = sizeof(*oat_header_); 12981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom offset += image_file_location_.size(); 130e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 131e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 132e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 133e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatDexFiles(size_t offset) { 134e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // create the OatDexFiles 135e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 136e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 137e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 138265091e581c9f643b37e7966890911f09e223269Brian Carlstrom OatDexFile* oat_dex_file = new OatDexFile(offset, *dex_file); 139e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_dex_files_.push_back(oat_dex_file); 140e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset += oat_dex_file->SizeOf(); 141e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 142e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 143e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 144e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 14589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstromsize_t OatWriter::InitDexFiles(size_t offset) { 14689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // calculate the offsets within OatDexFiles to the DexFiles 14789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 14889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // dex files are required to be 4 byte aligned 1490aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_t original_offset = offset; 15089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom offset = RoundUp(offset, 4); 1510aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_dex_file_alignment_ += offset - original_offset; 15289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 15389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // set offset in OatDexFile to DexFile 15489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom oat_dex_files_[i]->dex_file_offset_ = offset; 15589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 15689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 15789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom offset += dex_file->GetHeader().file_size_; 15889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 15989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return offset; 16089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom} 16189521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 162389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstromsize_t OatWriter::InitOatClasses(size_t offset) { 163389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom // create the OatClasses 164389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom // calculate the offsets within OatDexFiles to OatClasses 165e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 166e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 167e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t class_def_index = 0; 168e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index < dex_file->NumClassDefs(); 169c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers class_def_index++) { 1706e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom oat_dex_files_[i]->methods_offsets_[class_def_index] = offset; 171e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); 172e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file->GetClassData(class_def); 173ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t num_non_null_compiled_methods = 0; 174ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom UniquePtr<std::vector<CompiledMethod*> > compiled_methods(new std::vector<CompiledMethod*>()); 1750571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (class_data != NULL) { // ie not an empty class, such as a marker interface 1760571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassDataItemIterator it(*dex_file, class_data); 1770571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t num_direct_methods = it.NumDirectMethods(); 1780571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t num_virtual_methods = it.NumVirtualMethods(); 179ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_t num_methods = num_direct_methods + num_virtual_methods; 180ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 181ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // Fill in the compiled_methods_ array for methods that have a 182ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // CompiledMethod. We track the number of non-null entries in 183ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // num_non_null_compiled_methods since we only want to allocate 184ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // OatMethodOffsets for the compiled methods. 185ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom compiled_methods->reserve(num_methods); 186ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom while (it.HasNextStaticField()) { 187ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom it.Next(); 188ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 189ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom while (it.HasNextInstanceField()) { 190ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom it.Next(); 191ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 192ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_t class_def_method_index = 0; 193ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom while (it.HasNextDirectMethod()) { 194ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t method_idx = it.GetMemberIndex(); 195ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CompiledMethod* compiled_method = 196ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom compiler_driver_->GetCompiledMethod(MethodReference(dex_file, method_idx)); 197ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom compiled_methods->push_back(compiled_method); 198ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (compiled_method != NULL) { 199ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom num_non_null_compiled_methods++; 200ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 201ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom class_def_method_index++; 202ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom it.Next(); 203ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 204ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom while (it.HasNextVirtualMethod()) { 205ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t method_idx = it.GetMemberIndex(); 206ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CompiledMethod* compiled_method = 207ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom compiler_driver_->GetCompiledMethod(MethodReference(dex_file, method_idx)); 208ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom compiled_methods->push_back(compiled_method); 209ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (compiled_method != NULL) { 210ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom num_non_null_compiled_methods++; 211ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 212ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom class_def_method_index++; 213ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom it.Next(); 214ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 2150571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 2160755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 21751c2467e8771b56e25ae4f17f66522f979f57a7eBrian Carlstrom ClassReference class_ref(dex_file, class_def_index); 2181212a022fa5f8ef9585d765b1809521812af882cIan Rogers CompiledClass* compiled_class = compiler_driver_->GetCompiledClass(class_ref); 2192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class::Status status; 220ec0142313a470edecf52b4f034433404b7264358jeffhao if (compiled_class != NULL) { 221ec0142313a470edecf52b4f034433404b7264358jeffhao status = compiled_class->GetStatus(); 222c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko } else if (compiler_driver_->GetVerificationResults()->IsClassRejected(class_ref)) { 2232dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers status = mirror::Class::kStatusError; 224ec0142313a470edecf52b4f034433404b7264358jeffhao } else { 2252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers status = mirror::Class::kStatusNotReady; 226ec0142313a470edecf52b4f034433404b7264358jeffhao } 2270755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 228ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom OatClass* oat_class = new OatClass(offset, compiled_methods.release(), 229ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom num_non_null_compiled_methods, status); 230389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom oat_classes_.push_back(oat_class); 231389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom offset += oat_class->SizeOf(); 232e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 2333d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_dex_files_[i]->UpdateChecksum(oat_header_); 234e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 235e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 236e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 237e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 238e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCode(size_t offset) { 239e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // calculate the offsets within OatHeader to executable code 240e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t old_offset = offset; 241e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // required to be on a new page boundary 242e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = RoundUp(offset, kPageSize); 243e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header_->SetExecutableOffset(offset); 2440aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_executable_offset_alignment_ = offset - old_offset; 2450aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao if (compiler_driver_->IsImage()) { 2460aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); 247848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 248848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers #define DO_TRAMPOLINE(field, fn_name) \ 249848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers offset = CompiledCode::AlignCode(offset, instruction_set); \ 250848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_header_->Set ## fn_name ## Offset(offset); \ 251848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers field.reset(compiler_driver_->Create ## fn_name()); \ 252848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers offset += field->size(); 253848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 254848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(interpreter_to_interpreter_bridge_, InterpreterToInterpreterBridge); 255848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(interpreter_to_compiled_code_bridge_, InterpreterToCompiledCodeBridge); 256848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(jni_dlsym_lookup_, JniDlsymLookup); 25788474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_TRAMPOLINE(portable_imt_conflict_trampoline_, PortableImtConflictTrampoline); 258848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(portable_resolution_trampoline_, PortableResolutionTrampoline); 259848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(portable_to_interpreter_bridge_, PortableToInterpreterBridge); 2602da882315a61072664f7ce3c212307342e907207Andreas Gampe DO_TRAMPOLINE(quick_generic_jni_trampoline_, QuickGenericJniTrampoline); 26188474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_TRAMPOLINE(quick_imt_conflict_trampoline_, QuickImtConflictTrampoline); 262848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(quick_resolution_trampoline_, QuickResolutionTrampoline); 263848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(quick_to_interpreter_bridge_, QuickToInterpreterBridge); 264848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 265848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers #undef DO_TRAMPOLINE 2660aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao } else { 267848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_header_->SetInterpreterToInterpreterBridgeOffset(0); 268848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_header_->SetInterpreterToCompiledCodeBridgeOffset(0); 269848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_header_->SetJniDlsymLookupOffset(0); 27088474b416eb257078e590bf9bc7957cee604a186Jeff Hao oat_header_->SetPortableImtConflictTrampolineOffset(0); 2710aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_header_->SetPortableResolutionTrampolineOffset(0); 272848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_header_->SetPortableToInterpreterBridgeOffset(0); 2732da882315a61072664f7ce3c212307342e907207Andreas Gampe oat_header_->SetQuickGenericJniTrampolineOffset(0); 27488474b416eb257078e590bf9bc7957cee604a186Jeff Hao oat_header_->SetQuickImtConflictTrampolineOffset(0); 2750aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_header_->SetQuickResolutionTrampolineOffset(0); 276848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_header_->SetQuickToInterpreterBridgeOffset(0); 2770aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao } 278e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 279e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 280e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 281e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeDexFiles(size_t offset) { 282e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t oat_class_index = 0; 283e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 284e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 285e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 286ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom offset = InitOatCodeDexFile(offset, &oat_class_index, *dex_file); 287e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 288e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 289e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 290e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 291e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeDexFile(size_t offset, 292ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_t* oat_class_index, 293e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file) { 294ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes for (size_t class_def_index = 0; 295e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index < dex_file.NumClassDefs(); 296ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom class_def_index++, (*oat_class_index)++) { 297e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); 298ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom offset = InitOatCodeClassDef(offset, *oat_class_index, class_def_index, dex_file, class_def); 2993d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_classes_[*oat_class_index]->UpdateChecksum(oat_header_); 300e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 301e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 302e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 303e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 304e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeClassDef(size_t offset, 305c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers size_t oat_class_index, size_t class_def_index, 306e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file, 307e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def) { 308e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file.GetClassData(class_def); 3090571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (class_data == NULL) { 3100571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // empty class, such as a marker interface 311387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers return offset; 312387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers } 3130571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassDataItemIterator it(dex_file, class_data); 314ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LE(oat_classes_[oat_class_index]->method_offsets_.size(), 3150571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.NumDirectMethods() + it.NumVirtualMethods()); 3160571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Skip fields 3170571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextStaticField()) { 3180571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 319e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 3200571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextInstanceField()) { 3210571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 322e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 3230571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Process methods 3240571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t class_def_method_index = 0; 325ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_t method_offsets_index = 0; 3260571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextDirectMethod()) { 327c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0; 32808f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers offset = InitOatCodeMethod(offset, oat_class_index, class_def_index, class_def_method_index, 329ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom &method_offsets_index, is_native, 330ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom it.GetMethodInvokeType(class_def), it.GetMemberIndex(), dex_file); 3310571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 3320571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 3330571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 3340571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextVirtualMethod()) { 335c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0; 33608f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers offset = InitOatCodeMethod(offset, oat_class_index, class_def_index, class_def_method_index, 337ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom &method_offsets_index, is_native, 338ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom it.GetMethodInvokeType(class_def), it.GetMemberIndex(), dex_file); 3390571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 3400571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 3410571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 3420571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK(!it.HasNext()); 343ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LE(method_offsets_index, class_def_method_index); 344e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 345e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 346e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 3471bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughessize_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, 3481bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes size_t __attribute__((unused)) class_def_index, 3491bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes size_t class_def_method_index, 350ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_t* method_offsets_index, 3511bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes bool __attribute__((unused)) is_native, 352265091e581c9f643b37e7966890911f09e223269Brian Carlstrom InvokeType invoke_type, 353ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t method_idx, const DexFile& dex_file) { 354ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers // Derived from CompiledMethod if available. 355ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uint32_t quick_code_offset = 0; 3563320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t frame_size_in_bytes = kStackAlignment; 3573320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t core_spill_mask = 0; 3583320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t fp_spill_mask = 0; 3593320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t mapping_table_offset = 0; 3603320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t vmap_table_offset = 0; 361e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom uint32_t gc_map_offset = 0; 3623320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 363265091e581c9f643b37e7966890911f09e223269Brian Carlstrom OatClass* oat_class = oat_classes_[oat_class_index]; 364ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 365ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 3663320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_method != NULL) { 367ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const std::vector<uint8_t>* portable_code = compiled_method->GetPortableCode(); 368ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const std::vector<uint8_t>* quick_code = compiled_method->GetQuickCode(); 369ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (portable_code != nullptr) { 370ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers CHECK(quick_code == nullptr); 371ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers size_t oat_method_offsets_offset = 372ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers oat_class->GetOatMethodOffsetsOffsetFromOatHeader(class_def_method_index); 373ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers compiled_method->AddOatdataOffsetToCompliledCodeOffset( 374ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers oat_method_offsets_offset + OFFSETOF_MEMBER(OatMethodOffsets, code_offset_)); 37555d782146917f9afabc98aedcab4b5874a74e55cjeffhao } else { 376ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers CHECK(quick_code != nullptr); 377ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers offset = compiled_method->AlignCode(offset); 378ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers DCHECK_ALIGNED(offset, kArmAlignment); 379ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uint32_t code_size = quick_code->size() * sizeof(uint8_t); 380ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers CHECK_NE(code_size, 0U); 381ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uint32_t thumb_offset = compiled_method->CodeDelta(); 382ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers quick_code_offset = offset + sizeof(code_size) + thumb_offset; 383ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 384ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell std::vector<uint8_t>* cfi_info = compiler_driver_->GetCallFrameInformation(); 385ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (cfi_info != nullptr) { 386ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Copy in the FDE, if present 387ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell const std::vector<uint8_t>* fde = compiled_method->GetCFIInfo(); 388ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (fde != nullptr) { 389ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Copy the information into cfi_info and then fix the address in the new copy. 390ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell int cur_offset = cfi_info->size(); 391ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->insert(cfi_info->end(), fde->begin(), fde->end()); 392ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 393ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Set the 'initial_location' field to address the start of the method. 394ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t new_value = quick_code_offset - oat_header_->GetExecutableOffset(); 395ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t offset_to_update = cur_offset + 2*sizeof(uint32_t); 396ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[offset_to_update+0] = new_value; 397ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[offset_to_update+1] = new_value >> 8; 398ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[offset_to_update+2] = new_value >> 16; 399ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[offset_to_update+3] = new_value >> 24; 400ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell method_info_.push_back(DebugInfo(PrettyMethod(class_def_method_index, dex_file, false), 401ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell new_value, new_value + code_size)); 402ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 403ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 404ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 405ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers // Deduplicate code arrays 406ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = 407ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers code_offsets_.find(quick_code); 408ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (code_iter != code_offsets_.end()) { 409ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers quick_code_offset = code_iter->second; 410ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } else { 411ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers code_offsets_.Put(quick_code, quick_code_offset); 412ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers offset += sizeof(code_size); // code size is prepended before code 413ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers offset += code_size; 414ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers oat_header_->UpdateChecksum(&(*quick_code)[0], code_size); 415ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 416971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } 417971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); 418971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien core_spill_mask = compiled_method->GetCoreSpillMask(); 419971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien fp_spill_mask = compiled_method->GetFpSpillMask(); 420971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien 4211809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers const std::vector<uint8_t>& mapping_table = compiled_method->GetMappingTable(); 422971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); 423971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien mapping_table_offset = (mapping_table_size == 0) ? 0 : offset; 424971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien 425971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien // Deduplicate mapping tables 4261809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator mapping_iter = 427c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom mapping_table_offsets_.find(&mapping_table); 428971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien if (mapping_iter != mapping_table_offsets_.end()) { 429971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien mapping_table_offset = mapping_iter->second; 430971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } else { 431971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien mapping_table_offsets_.Put(&mapping_table, mapping_table_offset); 432971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien offset += mapping_table_size; 433971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size); 434971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } 435ccb7bf1271560783adccddb2ab74c53d0efd3fd1Logan Chien 4361809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers const std::vector<uint8_t>& vmap_table = compiled_method->GetVmapTable(); 437971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); 438971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien vmap_table_offset = (vmap_table_size == 0) ? 0 : offset; 439e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom 440971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien // Deduplicate vmap tables 4411809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator vmap_iter = 442c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom vmap_table_offsets_.find(&vmap_table); 443971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien if (vmap_iter != vmap_table_offsets_.end()) { 444971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien vmap_table_offset = vmap_iter->second; 445971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } else { 446971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien vmap_table_offsets_.Put(&vmap_table, vmap_table_offset); 447971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien offset += vmap_table_size; 448971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size); 449971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } 450e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom 451fbdc0fa4f5b1a45390a909afa44a61042406dcd4Ian Rogers const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap(); 452971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); 453971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien gc_map_offset = (gc_map_size == 0) ? 0 : offset; 454971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien 455590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (kIsDebugBuild) { 456590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // We expect GC maps except when the class hasn't been verified or the method is native 457590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier ClassReference class_ref(&dex_file, class_def_index); 458590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier CompiledClass* compiled_class = compiler_driver_->GetCompiledClass(class_ref); 459590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier mirror::Class::Status status; 460590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (compiled_class != NULL) { 461590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier status = compiled_class->GetStatus(); 462c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko } else if (compiler_driver_->GetVerificationResults()->IsClassRejected(class_ref)) { 463590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier status = mirror::Class::kStatusError; 464590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } else { 465590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier status = mirror::Class::kStatusNotReady; 466590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 467590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier CHECK(gc_map_size != 0 || is_native || status < mirror::Class::kStatusVerified) 468590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " 469590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier << (status < mirror::Class::kStatusVerified) << " " << status << " " 470590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier << PrettyMethod(method_idx, dex_file); 471ec0142313a470edecf52b4f034433404b7264358jeffhao } 472c20a83e440557924dacaf8ec519e086865aaf5a5Ian Rogers 473971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien // Deduplicate GC maps 474c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = 475c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom gc_map_offsets_.find(&gc_map); 476971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien if (gc_map_iter != gc_map_offsets_.end()) { 477971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien gc_map_offset = gc_map_iter->second; 478971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } else { 479971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien gc_map_offsets_.Put(&gc_map, gc_map_offset); 480971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien offset += gc_map_size; 481971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien oat_header_->UpdateChecksum(&gc_map[0], gc_map_size); 482e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom } 483ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 484ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_class->method_offsets_[*method_offsets_index] = 485ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers OatMethodOffsets(quick_code_offset, 486ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom frame_size_in_bytes, 487ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom core_spill_mask, 488ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom fp_spill_mask, 489ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom mapping_table_offset, 490ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom vmap_table_offset, 491ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom gc_map_offset); 492ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom (*method_offsets_index)++; 4933320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 4943320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 4953320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 4961212a022fa5f8ef9585d765b1809521812af882cIan Rogers if (compiler_driver_->IsImage()) { 4970571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassLinker* linker = Runtime::Current()->GetClassLinker(); 49800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Unchecked as we hold mutator_lock_ on entry. 49900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 500590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier SirtRef<mirror::DexCache> dex_cache(soa.Self(), linker->FindDexCache(dex_file)); 501590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier SirtRef<mirror::ClassLoader> class_loader(soa.Self(), nullptr); 502ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom mirror::ArtMethod* method = linker->ResolveMethod(dex_file, method_idx, dex_cache, 503590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier class_loader, nullptr, invoke_type); 5040571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers CHECK(method != NULL); 5050571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetFrameSizeInBytes(frame_size_in_bytes); 5060571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetCoreSpillMask(core_spill_mask); 5070571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetFpSpillMask(fp_spill_mask); 5080571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetOatMappingTableOffset(mapping_table_offset); 5092ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom // Portable code offsets are set by ElfWriterMclinker::FixupCompiledCodeOffset after linking. 5102ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom method->SetQuickOatCodeOffset(quick_code_offset); 5110571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->SetOatVmapTableOffset(vmap_table_offset); 5120c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers method->SetOatNativeGcMapOffset(gc_map_offset); 5130571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 5148b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien 515e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 516e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 517e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 518265091e581c9f643b37e7966890911f09e223269Brian Carlstrom#define DCHECK_OFFSET() \ 5193d504075f7c1204d581923460754bf6d3714b13fIan Rogers DCHECK_EQ(static_cast<off_t>(file_offset + relative_offset), out->Seek(0, kSeekCurrent)) \ 520c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom << "file_offset=" << file_offset << " relative_offset=" << relative_offset 521265091e581c9f643b37e7966890911f09e223269Brian Carlstrom 522265091e581c9f643b37e7966890911f09e223269Brian Carlstrom#define DCHECK_OFFSET_() \ 5233d504075f7c1204d581923460754bf6d3714b13fIan Rogers DCHECK_EQ(static_cast<off_t>(file_offset + offset_), out->Seek(0, kSeekCurrent)) \ 524c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom << "file_offset=" << file_offset << " offset_=" << offset_ 5253320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 5263d504075f7c1204d581923460754bf6d3714b13fIan Rogersbool OatWriter::Write(OutputStream* out) { 5273d504075f7c1204d581923460754bf6d3714b13fIan Rogers const size_t file_offset = out->Seek(0, kSeekCurrent); 528c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom 5293d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(oat_header_, sizeof(*oat_header_))) { 5303d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write oat header to " << out->GetLocation(); 531e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 532e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 5330aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_header_ += sizeof(*oat_header_); 534e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 5353d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(image_file_location_.data(), image_file_location_.size())) { 5363d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write oat header image file location to " << out->GetLocation(); 53781f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom return false; 53881f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom } 5390aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_header_image_file_location_ += image_file_location_.size(); 54081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom 541c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (!WriteTables(out, file_offset)) { 5423d504075f7c1204d581923460754bf6d3714b13fIan Rogers LOG(ERROR) << "Failed to write oat tables to " << out->GetLocation(); 543e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 544e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 545e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 546c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom size_t relative_offset = WriteCode(out, file_offset); 547c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (relative_offset == 0) { 5483d504075f7c1204d581923460754bf6d3714b13fIan Rogers LOG(ERROR) << "Failed to write oat code to " << out->GetLocation(); 549e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 550e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 551e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 552c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom relative_offset = WriteCodeDexFiles(out, file_offset, relative_offset); 553c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (relative_offset == 0) { 5543d504075f7c1204d581923460754bf6d3714b13fIan Rogers LOG(ERROR) << "Failed to write oat code for dex files to " << out->GetLocation(); 555e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 556e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 557e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 5584bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers if (kIsDebugBuild) { 5594bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers uint32_t size_total = 0; 5604bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers #define DO_STAT(x) \ 56175a43f10f55e2aa550de51e969cc1e60d583b632Anwar Ghuloum VLOG(compiler) << #x "=" << PrettySize(x) << " (" << x << "B)"; \ 5624bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers size_total += x; 5634bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers 5644bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_dex_file_alignment_); 5654bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_executable_offset_alignment_); 5664bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_header_); 5674bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_header_image_file_location_); 5684bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_dex_file_); 569848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_interpreter_to_interpreter_bridge_); 570848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_interpreter_to_compiled_code_bridge_); 571848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_jni_dlsym_lookup_); 57288474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_STAT(size_portable_imt_conflict_trampoline_); 5734bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_portable_resolution_trampoline_); 574848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_portable_to_interpreter_bridge_); 5752da882315a61072664f7ce3c212307342e907207Andreas Gampe DO_STAT(size_quick_generic_jni_trampoline_); 57688474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_STAT(size_quick_imt_conflict_trampoline_); 5774bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_quick_resolution_trampoline_); 578848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_quick_to_interpreter_bridge_); 579848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_trampoline_alignment_); 5804bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_code_size_); 5814bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_code_); 5824bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_code_alignment_); 5834bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_mapping_table_); 5844bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_vmap_table_); 5854bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_gc_map_); 5864bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_dex_file_location_size_); 5874bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_dex_file_location_data_); 5884bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_dex_file_location_checksum_); 5894bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_dex_file_offset_); 5904bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_dex_file_methods_offsets_); 591ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom DO_STAT(size_oat_class_type_); 5924bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_class_status_); 593ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom DO_STAT(size_oat_class_method_bitmaps_); 5944bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_class_method_offsets_); 5954bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers #undef DO_STAT 5964bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers 59775a43f10f55e2aa550de51e969cc1e60d583b632Anwar Ghuloum VLOG(compiler) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)"; \ 5983d504075f7c1204d581923460754bf6d3714b13fIan Rogers CHECK_EQ(file_offset + size_total, static_cast<uint32_t>(out->Seek(0, kSeekCurrent))); 599c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom CHECK_EQ(size_, size_total); 6004bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers } 6010aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao 6023d504075f7c1204d581923460754bf6d3714b13fIan Rogers CHECK_EQ(file_offset + size_, static_cast<uint32_t>(out->Seek(0, kSeekCurrent))); 603c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom CHECK_EQ(size_, relative_offset); 604c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom 605e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 606e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 607e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 6083d504075f7c1204d581923460754bf6d3714b13fIan Rogersbool OatWriter::WriteTables(OutputStream* out, const size_t file_offset) { 609e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 610c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (!oat_dex_files_[i]->Write(this, out, file_offset)) { 6113d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write oat dex information to " << out->GetLocation(); 612e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 613e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 614e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 61589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 616c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom uint32_t expected_offset = file_offset + oat_dex_files_[i]->dex_file_offset_; 6173d504075f7c1204d581923460754bf6d3714b13fIan Rogers off_t actual_offset = out->Seek(expected_offset, kSeekSet); 61889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom if (static_cast<uint32_t>(actual_offset) != expected_offset) { 61989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 62089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset 62189521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom << " Expected: " << expected_offset << " File: " << dex_file->GetLocation(); 62289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 62389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 62489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 6253d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&dex_file->GetHeader(), dex_file->GetHeader().file_size_)) { 626c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom PLOG(ERROR) << "Failed to write dex file " << dex_file->GetLocation() 6273d504075f7c1204d581923460754bf6d3714b13fIan Rogers << " to " << out->GetLocation(); 62889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 62989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 6300aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_dex_file_ += dex_file->GetHeader().file_size_; 63189521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 632389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom for (size_t i = 0; i != oat_classes_.size(); ++i) { 633c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (!oat_classes_[i]->Write(this, out, file_offset)) { 6343d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write oat methods information to " << out->GetLocation(); 635e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 636e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 637e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 638e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 639e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 640e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 6413d504075f7c1204d581923460754bf6d3714b13fIan Rogerssize_t OatWriter::WriteCode(OutputStream* out, const size_t file_offset) { 642c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom size_t relative_offset = oat_header_->GetExecutableOffset(); 6433d504075f7c1204d581923460754bf6d3714b13fIan Rogers off_t new_offset = out->Seek(size_executable_offset_alignment_, kSeekCurrent); 644c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom size_t expected_file_offset = file_offset + relative_offset; 645c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (static_cast<uint32_t>(new_offset) != expected_file_offset) { 6463320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset 6473d504075f7c1204d581923460754bf6d3714b13fIan Rogers << " Expected: " << expected_file_offset << " File: " << out->GetLocation(); 648e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 649e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 650265091e581c9f643b37e7966890911f09e223269Brian Carlstrom DCHECK_OFFSET(); 6510aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao if (compiler_driver_->IsImage()) { 6520aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); 653848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 654848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers #define DO_TRAMPOLINE(field) \ 655848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers do { \ 656848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers uint32_t aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set); \ 657848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers uint32_t alignment_padding = aligned_offset - relative_offset; \ 6583d504075f7c1204d581923460754bf6d3714b13fIan Rogers out->Seek(alignment_padding, kSeekCurrent); \ 659848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_trampoline_alignment_ += alignment_padding; \ 6603d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&(*field)[0], field->size())) { \ 6613d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write " # field " to " << out->GetLocation(); \ 662848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers return false; \ 663848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } \ 664848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_ ## field += field->size(); \ 665848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers relative_offset += alignment_padding + field->size(); \ 666848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DCHECK_OFFSET(); \ 667848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } while (false) 668848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 669848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(interpreter_to_interpreter_bridge_); 670848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(interpreter_to_compiled_code_bridge_); 671848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(jni_dlsym_lookup_); 67288474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_TRAMPOLINE(portable_imt_conflict_trampoline_); 673848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(portable_resolution_trampoline_); 674848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(portable_to_interpreter_bridge_); 6752da882315a61072664f7ce3c212307342e907207Andreas Gampe DO_TRAMPOLINE(quick_generic_jni_trampoline_); 67688474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_TRAMPOLINE(quick_imt_conflict_trampoline_); 677848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(quick_resolution_trampoline_); 678848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(quick_to_interpreter_bridge_); 679848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers #undef DO_TRAMPOLINE 6800aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao } 681c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom return relative_offset; 682e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 683e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 6843d504075f7c1204d581923460754bf6d3714b13fIan Rogerssize_t OatWriter::WriteCodeDexFiles(OutputStream* out, 685c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom const size_t file_offset, 686c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom size_t relative_offset) { 6870571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t oat_class_index = 0; 6886e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 689e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 690e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 691ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom relative_offset = WriteCodeDexFile(out, file_offset, relative_offset, &oat_class_index, 692c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom *dex_file); 693c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (relative_offset == 0) { 694e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 695e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 696e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 697c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom return relative_offset; 698e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 699e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 7003d504075f7c1204d581923460754bf6d3714b13fIan Rogerssize_t OatWriter::WriteCodeDexFile(OutputStream* out, const size_t file_offset, 701ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_t relative_offset, size_t* oat_class_index, 7020571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const DexFile& dex_file) { 7030571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); 704ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom class_def_index++, (*oat_class_index)++) { 705e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); 706ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom relative_offset = WriteCodeClassDef(out, file_offset, relative_offset, *oat_class_index, 707c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom dex_file, class_def); 708c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (relative_offset == 0) { 709e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 710e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 711e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 712c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom return relative_offset; 713e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 714e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 7150571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersvoid OatWriter::ReportWriteFailure(const char* what, uint32_t method_idx, 7163d504075f7c1204d581923460754bf6d3714b13fIan Rogers const DexFile& dex_file, const OutputStream& out) const { 7170571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers PLOG(ERROR) << "Failed to write " << what << " for " << PrettyMethod(method_idx, dex_file) 718cd60ac736bc7104785dc67671660d70fb434466fBrian Carlstrom << " to " << out.GetLocation(); 719234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes} 720234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes 7213d504075f7c1204d581923460754bf6d3714b13fIan Rogerssize_t OatWriter::WriteCodeClassDef(OutputStream* out, 722c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom const size_t file_offset, 723c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom size_t relative_offset, 724c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom size_t oat_class_index, 725e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file, 726e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def) { 727e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file.GetClassData(class_def); 7280571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (class_data == NULL) { 7290571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // ie. an empty class such as a marker interface 730c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom return relative_offset; 731387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers } 7320571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers ClassDataItemIterator it(dex_file, class_data); 7330571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Skip fields 7340571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextStaticField()) { 7350571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 7360571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 7370571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextInstanceField()) { 7380571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 7390571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 7400571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers // Process methods 7410571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers size_t class_def_method_index = 0; 742ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_t method_offsets_index = 0; 7430571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextDirectMethod()) { 7440571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0; 745c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom relative_offset = WriteCodeMethod(out, file_offset, relative_offset, oat_class_index, 746ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom class_def_method_index, &method_offsets_index, is_static, 747ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom it.GetMemberIndex(), dex_file); 748c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (relative_offset == 0) { 749e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 750e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 7510571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 7520571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 753e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 7540571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextVirtualMethod()) { 755c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom relative_offset = WriteCodeMethod(out, file_offset, relative_offset, oat_class_index, 756ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom class_def_method_index, &method_offsets_index, false, 757ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom it.GetMemberIndex(), dex_file); 758c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (relative_offset == 0) { 759e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 760e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 7610571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers class_def_method_index++; 7620571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 763e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 764ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom DCHECK(!it.HasNext()); 765ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LE(method_offsets_index, class_def_method_index); 766c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom return relative_offset; 767e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 768e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 7693d504075f7c1204d581923460754bf6d3714b13fIan Rogerssize_t OatWriter::WriteCodeMethod(OutputStream* out, const size_t file_offset, 770c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom size_t relative_offset, size_t oat_class_index, 771ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_t class_def_method_index, size_t* method_offsets_index, 772ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom bool is_static, uint32_t method_idx, const DexFile& dex_file) { 773ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom OatClass* oat_class = oat_classes_[oat_class_index]; 774ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 7750571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 7760571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers if (compiled_method != NULL) { // ie. not an abstract method 777ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom const OatMethodOffsets method_offsets = oat_class->method_offsets_[*method_offsets_index]; 778ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom (*method_offsets_index)++; 779ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const std::vector<uint8_t>* quick_code = compiled_method->GetQuickCode(); 780ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (quick_code != nullptr) { 781ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers CHECK(compiled_method->GetPortableCode() == nullptr); 782ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uint32_t aligned_offset = compiled_method->AlignCode(relative_offset); 783ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uint32_t aligned_code_delta = aligned_offset - relative_offset; 784ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (aligned_code_delta != 0) { 7853d504075f7c1204d581923460754bf6d3714b13fIan Rogers off_t new_offset = out->Seek(aligned_code_delta, kSeekCurrent); 786ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers size_code_alignment_ += aligned_code_delta; 787ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uint32_t expected_offset = file_offset + aligned_offset; 788ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (static_cast<uint32_t>(new_offset) != expected_offset) { 789ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset 7903d504075f7c1204d581923460754bf6d3714b13fIan Rogers << " Expected: " << expected_offset << " File: " << out->GetLocation(); 791ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return 0; 792ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 793ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers relative_offset += aligned_code_delta; 794ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers DCHECK_OFFSET(); 795f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom } 796ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers DCHECK_ALIGNED(relative_offset, kArmAlignment); 797ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uint32_t code_size = quick_code->size() * sizeof(uint8_t); 798ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers CHECK_NE(code_size, 0U); 799ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 800ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers // Deduplicate code arrays 801ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers size_t code_offset = relative_offset + sizeof(code_size) + compiled_method->CodeDelta(); 802ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = 803ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers code_offsets_.find(quick_code); 804ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (code_iter != code_offsets_.end() && code_offset != method_offsets.code_offset_) { 805ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers DCHECK(code_iter->second == method_offsets.code_offset_) 806ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers << PrettyMethod(method_idx, dex_file); 807ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } else { 808ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers DCHECK(code_offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file); 8093d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&code_size, sizeof(code_size))) { 8103d504075f7c1204d581923460754bf6d3714b13fIan Rogers ReportWriteFailure("method code size", method_idx, dex_file, *out); 811ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return 0; 812ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 813ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers size_code_size_ += sizeof(code_size); 814ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers relative_offset += sizeof(code_size); 815ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers DCHECK_OFFSET(); 8163d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&(*quick_code)[0], code_size)) { 8173d504075f7c1204d581923460754bf6d3714b13fIan Rogers ReportWriteFailure("method code", method_idx, dex_file, *out); 818ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return 0; 819ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 820ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers size_code_ += code_size; 821ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers relative_offset += code_size; 82255d782146917f9afabc98aedcab4b5874a74e55cjeffhao } 823265091e581c9f643b37e7966890911f09e223269Brian Carlstrom DCHECK_OFFSET(); 824971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } 8251809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers const std::vector<uint8_t>& mapping_table = compiled_method->GetMappingTable(); 826971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); 827971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien 828971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien // Deduplicate mapping tables 8291809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator mapping_iter = 830971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien mapping_table_offsets_.find(&mapping_table); 831971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien if (mapping_iter != mapping_table_offsets_.end() && 832c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom relative_offset != method_offsets.mapping_table_offset_) { 833971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) 834971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien || mapping_iter->second == method_offsets.mapping_table_offset_) 835971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien << PrettyMethod(method_idx, dex_file); 836971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } else { 837971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) 838c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom || relative_offset == method_offsets.mapping_table_offset_) 839971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien << PrettyMethod(method_idx, dex_file); 8403d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&mapping_table[0], mapping_table_size)) { 8413d504075f7c1204d581923460754bf6d3714b13fIan Rogers ReportWriteFailure("mapping table", method_idx, dex_file, *out); 842971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien return 0; 843e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom } 8440aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_mapping_table_ += mapping_table_size; 845c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom relative_offset += mapping_table_size; 846971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } 847265091e581c9f643b37e7966890911f09e223269Brian Carlstrom DCHECK_OFFSET(); 848971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien 8491809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers const std::vector<uint8_t>& vmap_table = compiled_method->GetVmapTable(); 850971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); 851971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien 852971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien // Deduplicate vmap tables 8531809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator vmap_iter = 854971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien vmap_table_offsets_.find(&vmap_table); 855971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien if (vmap_iter != vmap_table_offsets_.end() && 856c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom relative_offset != method_offsets.vmap_table_offset_) { 857971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) 858971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien || vmap_iter->second == method_offsets.vmap_table_offset_) 859971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien << PrettyMethod(method_idx, dex_file); 860971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } else { 861971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) 862c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom || relative_offset == method_offsets.vmap_table_offset_) 863971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien << PrettyMethod(method_idx, dex_file); 8643d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&vmap_table[0], vmap_table_size)) { 8653d504075f7c1204d581923460754bf6d3714b13fIan Rogers ReportWriteFailure("vmap table", method_idx, dex_file, *out); 866971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien return 0; 867971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } 8680aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_vmap_table_ += vmap_table_size; 869c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom relative_offset += vmap_table_size; 870e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom } 871265091e581c9f643b37e7966890911f09e223269Brian Carlstrom DCHECK_OFFSET(); 872971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien 873fbdc0fa4f5b1a45390a909afa44a61042406dcd4Ian Rogers const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap(); 874971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); 875971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien 876971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien // Deduplicate GC maps 877971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = 878971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien gc_map_offsets_.find(&gc_map); 879971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien if (gc_map_iter != gc_map_offsets_.end() && 880c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom relative_offset != method_offsets.gc_map_offset_) { 881971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0) 882971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien || gc_map_iter->second == method_offsets.gc_map_offset_) 883971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien << PrettyMethod(method_idx, dex_file); 884971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } else { 885971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0) 886c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom || relative_offset == method_offsets.gc_map_offset_) 887971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien << PrettyMethod(method_idx, dex_file); 8883d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&gc_map[0], gc_map_size)) { 8893d504075f7c1204d581923460754bf6d3714b13fIan Rogers ReportWriteFailure("GC map", method_idx, dex_file, *out); 890971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien return 0; 891971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } 8920aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_gc_map_ += gc_map_size; 893c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom relative_offset += gc_map_size; 894971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien } 895265091e581c9f643b37e7966890911f09e223269Brian Carlstrom DCHECK_OFFSET(); 896e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 897265091e581c9f643b37e7966890911f09e223269Brian Carlstrom 898c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom return relative_offset; 899e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 900e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 901265091e581c9f643b37e7966890911f09e223269Brian CarlstromOatWriter::OatDexFile::OatDexFile(size_t offset, const DexFile& dex_file) { 902265091e581c9f643b37e7966890911f09e223269Brian Carlstrom offset_ = offset; 903955724179c6c739524f610023287f56b24dc31deElliott Hughes const std::string& location(dex_file.GetLocation()); 904e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_size_ = location.size(); 905e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data()); 9065b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom dex_file_location_checksum_ = dex_file.GetLocationChecksum(); 90789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom dex_file_offset_ = 0; 9086e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom methods_offsets_.resize(dex_file.NumClassDefs()); 909e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 910e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 911e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::OatDexFile::SizeOf() const { 912e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return sizeof(dex_file_location_size_) 913e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom + dex_file_location_size_ 9145b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom + sizeof(dex_file_location_checksum_) 91589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom + sizeof(dex_file_offset_) 9166e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom + (sizeof(methods_offsets_[0]) * methods_offsets_.size()); 917e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 918e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 9193d504075f7c1204d581923460754bf6d3714b13fIan Rogersvoid OatWriter::OatDexFile::UpdateChecksum(OatHeader* oat_header) const { 9203d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&dex_file_location_size_, sizeof(dex_file_location_size_)); 9213d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(dex_file_location_data_, dex_file_location_size_); 9223d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_)); 9233d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&dex_file_offset_, sizeof(dex_file_offset_)); 9243d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&methods_offsets_[0], 9256e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom sizeof(methods_offsets_[0]) * methods_offsets_.size()); 926e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 927e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 928c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrombool OatWriter::OatDexFile::Write(OatWriter* oat_writer, 9293d504075f7c1204d581923460754bf6d3714b13fIan Rogers OutputStream* out, 930c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom const size_t file_offset) const { 931265091e581c9f643b37e7966890911f09e223269Brian Carlstrom DCHECK_OFFSET_(); 9323d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) { 9333d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write dex file location length to " << out->GetLocation(); 934e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 935e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 9360aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_dex_file_location_size_ += sizeof(dex_file_location_size_); 9373d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(dex_file_location_data_, dex_file_location_size_)) { 9383d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write dex file location data to " << out->GetLocation(); 939e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 940e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 9410aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_dex_file_location_data_ += dex_file_location_size_; 9423d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_))) { 9433d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write dex file location checksum to " << out->GetLocation(); 944e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 945e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 9460aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_dex_file_location_checksum_ += sizeof(dex_file_location_checksum_); 9473d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) { 9483d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write dex file offset to " << out->GetLocation(); 94989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 95089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 9510aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_dex_file_offset_ += sizeof(dex_file_offset_); 9523d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&methods_offsets_[0], 953cd60ac736bc7104785dc67671660d70fb434466fBrian Carlstrom sizeof(methods_offsets_[0]) * methods_offsets_.size())) { 9543d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write methods offsets to " << out->GetLocation(); 955e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 956e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 9570aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_dex_file_methods_offsets_ += 9580aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao sizeof(methods_offsets_[0]) * methods_offsets_.size(); 959e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 960e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 961e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 962ba150c37d582eeeb8c11ba5245edc281cf31793cBrian CarlstromOatWriter::OatClass::OatClass(size_t offset, 963ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom std::vector<CompiledMethod*>* compiled_methods, 964ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t num_non_null_compiled_methods, 965ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom mirror::Class::Status status) { 966ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK(compiled_methods != NULL); 967ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t num_methods = compiled_methods->size(); 968ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LE(num_non_null_compiled_methods, num_methods); 969ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 970265091e581c9f643b37e7966890911f09e223269Brian Carlstrom offset_ = offset; 971ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom compiled_methods_ = compiled_methods; 972ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offsets_from_oat_class_.resize(num_methods); 973ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 974ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // Since both kOatClassNoneCompiled and kOatClassAllCompiled could 975ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // apply when there are 0 methods, we just arbitrarily say that 0 976ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // methods means kOatClassNoneCompiled and that we won't use 977ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // kOatClassAllCompiled unless there is at least one compiled 978ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // method. This means in an interpretter only system, we can assert 979ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // that all classes are kOatClassNoneCompiled. 980ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (num_non_null_compiled_methods == 0) { 981ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom type_ = kOatClassNoneCompiled; 982ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } else if (num_non_null_compiled_methods == num_methods) { 983ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom type_ = kOatClassAllCompiled; 984ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } else { 985ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom type_ = kOatClassSomeCompiled; 986ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 987ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 9880755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom status_ = status; 989ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_offsets_.resize(num_non_null_compiled_methods); 990ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 991ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t oat_method_offsets_offset_from_oat_class = sizeof(type_) + sizeof(status_); 992ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (type_ == kOatClassSomeCompiled) { 993ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_bitmap_ = new BitVector(num_methods, false, Allocator::GetMallocAllocator()); 994ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_bitmap_size_ = method_bitmap_->GetSizeOf(); 995ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offset_from_oat_class += sizeof(method_bitmap_size_); 996ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offset_from_oat_class += method_bitmap_size_; 997ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } else { 998ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_bitmap_ = NULL; 999ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_bitmap_size_ = 0; 1000ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1001ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 1002ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom for (size_t i = 0; i < num_methods; i++) { 1003ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CompiledMethod* compiled_method = (*compiled_methods_)[i]; 1004ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (compiled_method == NULL) { 1005ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offsets_from_oat_class_[i] = 0; 1006ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } else { 1007ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offsets_from_oat_class_[i] = oat_method_offsets_offset_from_oat_class; 1008ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offset_from_oat_class += sizeof(OatMethodOffsets); 1009ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (type_ == kOatClassSomeCompiled) { 1010ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_bitmap_->SetBit(i); 1011ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1012ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1013ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1014e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1015e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1016ba150c37d582eeeb8c11ba5245edc281cf31793cBrian CarlstromOatWriter::OatClass::~OatClass() { 1017661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier delete method_bitmap_; 1018ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom delete compiled_methods_; 1019ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom} 1020ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 1021265091e581c9f643b37e7966890911f09e223269Brian Carlstromsize_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatHeader( 1022265091e581c9f643b37e7966890911f09e223269Brian Carlstrom size_t class_def_method_index_) const { 1023ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t method_offset = GetOatMethodOffsetsOffsetFromOatClass(class_def_method_index_); 1024ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (method_offset == 0) { 1025ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return 0; 1026ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1027ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return offset_ + method_offset; 1028265091e581c9f643b37e7966890911f09e223269Brian Carlstrom} 1029265091e581c9f643b37e7966890911f09e223269Brian Carlstrom 1030265091e581c9f643b37e7966890911f09e223269Brian Carlstromsize_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatClass( 1031265091e581c9f643b37e7966890911f09e223269Brian Carlstrom size_t class_def_method_index_) const { 1032ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return oat_method_offsets_offsets_from_oat_class_[class_def_method_index_]; 1033265091e581c9f643b37e7966890911f09e223269Brian Carlstrom} 1034265091e581c9f643b37e7966890911f09e223269Brian Carlstrom 1035265091e581c9f643b37e7966890911f09e223269Brian Carlstromsize_t OatWriter::OatClass::SizeOf() const { 1036ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return sizeof(status_) 1037ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom + sizeof(type_) 1038ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom + ((method_bitmap_size_ == 0) ? 0 : sizeof(method_bitmap_size_)) 1039ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom + method_bitmap_size_ 1040ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom + (sizeof(method_offsets_[0]) * method_offsets_.size()); 1041e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1042e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 10433d504075f7c1204d581923460754bf6d3714b13fIan Rogersvoid OatWriter::OatClass::UpdateChecksum(OatHeader* oat_header) const { 10443d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&status_, sizeof(status_)); 10453d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&type_, sizeof(type_)); 1046ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (method_bitmap_size_ != 0) { 1047ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(kOatClassSomeCompiled, type_); 10483d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&method_bitmap_size_, sizeof(method_bitmap_size_)); 10493d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(method_bitmap_->GetRawStorage(), method_bitmap_size_); 1050ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 10513d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&method_offsets_[0], 10523d504075f7c1204d581923460754bf6d3714b13fIan Rogers sizeof(method_offsets_[0]) * method_offsets_.size()); 1053e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1054e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1055c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrombool OatWriter::OatClass::Write(OatWriter* oat_writer, 10563d504075f7c1204d581923460754bf6d3714b13fIan Rogers OutputStream* out, 1057c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom const size_t file_offset) const { 1058265091e581c9f643b37e7966890911f09e223269Brian Carlstrom DCHECK_OFFSET_(); 10593d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&status_, sizeof(status_))) { 10603d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write class status to " << out->GetLocation(); 10610755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom return false; 10620755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom } 10630aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_class_status_ += sizeof(status_); 10643d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&type_, sizeof(type_))) { 10653d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write oat class type to " << out->GetLocation(); 1066ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return false; 1067ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1068ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_writer->size_oat_class_type_ += sizeof(type_); 1069ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (method_bitmap_size_ != 0) { 1070ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(kOatClassSomeCompiled, type_); 10713d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&method_bitmap_size_, sizeof(method_bitmap_size_))) { 10723d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write method bitmap size to " << out->GetLocation(); 1073ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return false; 1074ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1075ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_writer->size_oat_class_method_bitmaps_ += sizeof(method_bitmap_size_); 10763d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(method_bitmap_->GetRawStorage(), method_bitmap_size_)) { 10773d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write method bitmap to " << out->GetLocation(); 1078ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return false; 1079ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1080ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_writer->size_oat_class_method_bitmaps_ += method_bitmap_size_; 1081ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 10823d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&method_offsets_[0], 1083cd60ac736bc7104785dc67671660d70fb434466fBrian Carlstrom sizeof(method_offsets_[0]) * method_offsets_.size())) { 10843d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write method offsets to " << out->GetLocation(); 1085e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 1086e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 10870aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_class_method_offsets_ += sizeof(method_offsets_[0]) * method_offsets_.size(); 1088e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 1089e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1090e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1091e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} // namespace art 1092