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" 2598d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang#include "compiled_class.h" 264f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 27c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "dex/verification_results.h" 281d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space.h" 29ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h" 302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/array.h" 312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h" 324f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h" 33e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "os.h" 34cd60ac736bc7104785dc67671660d70fb434466fBrian Carlstrom#include "output_stream.h" 35a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes#include "safe_map.h" 3600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 37eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope-inl.h" 38ec0142313a470edecf52b4f034433404b7264358jeffhao#include "verifier/method_verifier.h" 39e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 40e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art { 41e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 4296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko#define DCHECK_OFFSET() \ 4396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_EQ(static_cast<off_t>(file_offset + relative_offset), out->Seek(0, kSeekCurrent)) \ 4496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko << "file_offset=" << file_offset << " relative_offset=" << relative_offset 4596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 4696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko#define DCHECK_OFFSET_() \ 4796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_EQ(static_cast<off_t>(file_offset + offset_), out->Seek(0, kSeekCurrent)) \ 4896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko << "file_offset=" << file_offset << " offset_=" << offset_ 4996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 503320cf46afd082398aa401b246e6f301cebdf64dBrian CarlstromOatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, 5128db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom uint32_t image_file_location_oat_checksum, 52ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uintptr_t image_file_location_oat_begin, 53a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light int32_t image_patch_delta, 54ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers const CompilerDriver* compiler, 5522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe TimingLogger* timings, 5622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe SafeMap<std::string, std::string>* key_value_store) 570aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao : compiler_driver_(compiler), 580aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao dex_files_(&dex_files), 590aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao image_file_location_oat_checksum_(image_file_location_oat_checksum), 600aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao image_file_location_oat_begin_(image_file_location_oat_begin), 61a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light image_patch_delta_(image_patch_delta), 6222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe key_value_store_(key_value_store), 630aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_header_(NULL), 640aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_dex_file_alignment_(0), 650aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_executable_offset_alignment_(0), 660aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_header_(0), 6722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe size_oat_header_key_value_store_(0), 680aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_dex_file_(0), 69848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_interpreter_to_interpreter_bridge_(0), 70848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_interpreter_to_compiled_code_bridge_(0), 71848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_jni_dlsym_lookup_(0), 7288474b416eb257078e590bf9bc7957cee604a186Jeff Hao size_portable_imt_conflict_trampoline_(0), 730aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_portable_resolution_trampoline_(0), 74848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_portable_to_interpreter_bridge_(0), 752da882315a61072664f7ce3c212307342e907207Andreas Gampe size_quick_generic_jni_trampoline_(0), 7688474b416eb257078e590bf9bc7957cee604a186Jeff Hao size_quick_imt_conflict_trampoline_(0), 770aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_quick_resolution_trampoline_(0), 78848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_quick_to_interpreter_bridge_(0), 79848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_trampoline_alignment_(0), 8096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_method_header_(0), 810aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_code_(0), 820aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_code_alignment_(0), 830aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_mapping_table_(0), 840aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_vmap_table_(0), 850aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_gc_map_(0), 860aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_dex_file_location_size_(0), 870aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_dex_file_location_data_(0), 880aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_dex_file_location_checksum_(0), 890aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_dex_file_offset_(0), 900aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_dex_file_methods_offsets_(0), 91ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_oat_class_type_(0), 920aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_oat_class_status_(0), 93ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_oat_class_method_bitmaps_(0), 94d6ed642458c8820e1beca72f3d7b5f0be4a4b64bDave Allison size_oat_class_method_offsets_(0) { 9522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe CHECK(key_value_store != nullptr); 9622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe 97ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers size_t offset; 98ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 99f5997b4d3f889569d5a2b724d83d764bfbb8d106Mathieu Chartier TimingLogger::ScopedTiming split("InitOatHeader", timings); 100ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitOatHeader(); 101ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 102ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 103f5997b4d3f889569d5a2b724d83d764bfbb8d106Mathieu Chartier TimingLogger::ScopedTiming split("InitOatDexFiles", timings); 104ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitOatDexFiles(offset); 105ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 106ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 107f5997b4d3f889569d5a2b724d83d764bfbb8d106Mathieu Chartier TimingLogger::ScopedTiming split("InitDexFiles", timings); 108ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitDexFiles(offset); 109ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 110ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 111f5997b4d3f889569d5a2b724d83d764bfbb8d106Mathieu Chartier TimingLogger::ScopedTiming split("InitOatClasses", timings); 112ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitOatClasses(offset); 113ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 114ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 115f5997b4d3f889569d5a2b724d83d764bfbb8d106Mathieu Chartier TimingLogger::ScopedTiming split("InitOatMaps", timings); 11696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset = InitOatMaps(offset); 11796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 11896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko { 119f5997b4d3f889569d5a2b724d83d764bfbb8d106Mathieu Chartier TimingLogger::ScopedTiming split("InitOatCode", timings); 120ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitOatCode(offset); 121ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 122ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers { 123f5997b4d3f889569d5a2b724d83d764bfbb8d106Mathieu Chartier TimingLogger::ScopedTiming split("InitOatCodeDexFiles", timings); 124ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers offset = InitOatCodeDexFiles(offset); 125ca368cb576cf6a436a32c357fca51fbb3082d7a9Ian Rogers } 126c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom size_ = offset; 127e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 128e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK_EQ(dex_files_->size(), oat_dex_files_.size()); 12922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe CHECK_EQ(compiler->IsImage(), 13022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe key_value_store_->find(OatHeader::kImageLocationKey) == key_value_store_->end()); 131a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light CHECK_ALIGNED(image_patch_delta_, kPageSize); 132e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 133e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1340571d357843c53e042f370f5f2c2e9aa3fe803a9Ian RogersOatWriter::~OatWriter() { 1350571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers delete oat_header_; 1360571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers STLDeleteElements(&oat_dex_files_); 137389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom STLDeleteElements(&oat_classes_); 1380571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers} 1390571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers 14096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markostruct OatWriter::GcMapDataAccess { 14162746d8d9c4400e4764f162b22bfb1a32be287a9Andreas Gampe static const SwapVector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE { 14296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return &compiled_method->GetGcMap(); 14396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 14496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 14596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE { 146c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier uint32_t offset = oat_class->method_headers_[method_offsets_index].gc_map_offset_; 147c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier return offset == 0u ? 0u : 148c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset; 14996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 15096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 15196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset) 15296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ALWAYS_INLINE { 153c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier oat_class->method_headers_[method_offsets_index].gc_map_offset_ = 154c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset; 15596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 15696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 157c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier static const char* Name() { 15896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return "GC map"; 15996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 16096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko}; 16196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 16296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markostruct OatWriter::MappingTableDataAccess { 16362746d8d9c4400e4764f162b22bfb1a32be287a9Andreas Gampe static const SwapVector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE { 16496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return &compiled_method->GetMappingTable(); 16596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 16696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 16796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE { 1688a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko uint32_t offset = oat_class->method_headers_[method_offsets_index].mapping_table_offset_; 1698a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko return offset == 0u ? 0u : 1708a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset; 17196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 17296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 17396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset) 17496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ALWAYS_INLINE { 1758a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko oat_class->method_headers_[method_offsets_index].mapping_table_offset_ = 1768a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset; 17796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 17896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 179c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier static const char* Name() { 18096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return "mapping table"; 18196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 18296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko}; 18396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 18496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markostruct OatWriter::VmapTableDataAccess { 18562746d8d9c4400e4764f162b22bfb1a32be287a9Andreas Gampe static const SwapVector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE { 18696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return &compiled_method->GetVmapTable(); 18796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 18896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 18996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE { 1908a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko uint32_t offset = oat_class->method_headers_[method_offsets_index].vmap_table_offset_; 1918a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko return offset == 0u ? 0u : 1928a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset; 19396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 19496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 19596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset) 19696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ALWAYS_INLINE { 1978a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko oat_class->method_headers_[method_offsets_index].vmap_table_offset_ = 1988a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset; 19996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 20096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 201c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier static const char* Name() { 20296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return "vmap table"; 20396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 20496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko}; 20596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 20696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markoclass OatWriter::DexMethodVisitor { 20796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko public: 20896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DexMethodVisitor(OatWriter* writer, size_t offset) 20996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko : writer_(writer), 21096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset_(offset), 21196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko dex_file_(nullptr), 21296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko class_def_index_(DexFile::kDexNoIndex) { 21396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 21496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 21596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko virtual bool StartClass(const DexFile* dex_file, size_t class_def_index) { 21696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK(dex_file_ == nullptr); 21796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_EQ(class_def_index_, DexFile::kDexNoIndex); 21896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko dex_file_ = dex_file; 21996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko class_def_index_ = class_def_index; 22096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return true; 22196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 22296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 22396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko virtual bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) = 0; 22496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 22596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko virtual bool EndClass() { 22696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (kIsDebugBuild) { 22796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko dex_file_ = nullptr; 22896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko class_def_index_ = DexFile::kDexNoIndex; 22996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 23096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return true; 23196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 23296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 23396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t GetOffset() const { 23496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return offset_; 23596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 23696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 23796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko protected: 23896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko virtual ~DexMethodVisitor() { } 23996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 24096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OatWriter* const writer_; 24196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 24296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // The offset is usually advanced for each visited method by the derived class. 24396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t offset_; 24496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 24596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // The dex file and class def index are set in StartClass(). 24696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko const DexFile* dex_file_; 24796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t class_def_index_; 24896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko}; 24996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 25096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markoclass OatWriter::OatDexMethodVisitor : public DexMethodVisitor { 25196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko public: 25296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OatDexMethodVisitor(OatWriter* writer, size_t offset) 25396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko : DexMethodVisitor(writer, offset), 25496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko oat_class_index_(0u), 25596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko method_offsets_index_(0u) { 25696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 25796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 25896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool StartClass(const DexFile* dex_file, size_t class_def_index) { 25996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DexMethodVisitor::StartClass(dex_file, class_def_index); 26096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_LT(oat_class_index_, writer_->oat_classes_.size()); 26196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko method_offsets_index_ = 0u; 26296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return true; 26396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 26496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 26596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool EndClass() { 26696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ++oat_class_index_; 26796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return DexMethodVisitor::EndClass(); 26896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 26996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 27096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko protected: 27196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t oat_class_index_; 27296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t method_offsets_index_; 27396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko}; 27496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 27596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markoclass OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor { 27696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko public: 27796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko InitOatClassesMethodVisitor(OatWriter* writer, size_t offset) 27896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko : DexMethodVisitor(writer, offset), 27996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko compiled_methods_(), 28096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko num_non_null_compiled_methods_(0u) { 28196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko compiled_methods_.reserve(256u); 28296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 28396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 28496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool StartClass(const DexFile* dex_file, size_t class_def_index) { 28596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DexMethodVisitor::StartClass(dex_file, class_def_index); 28696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko compiled_methods_.clear(); 28796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko num_non_null_compiled_methods_ = 0u; 28896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return true; 28996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 29096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 29196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) { 29296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // Fill in the compiled_methods_ array for methods that have a 29396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // CompiledMethod. We track the number of non-null entries in 29496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // num_non_null_compiled_methods_ since we only want to allocate 29596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // OatMethodOffsets for the compiled methods. 29696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko uint32_t method_idx = it.GetMemberIndex(); 29796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CompiledMethod* compiled_method = 29896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko writer_->compiler_driver_->GetCompiledMethod(MethodReference(dex_file_, method_idx)); 29996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko compiled_methods_.push_back(compiled_method); 30096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (compiled_method != nullptr) { 30196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ++num_non_null_compiled_methods_; 30296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 30396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return true; 30496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 30596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 30696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool EndClass() { 30796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ClassReference class_ref(dex_file_, class_def_index_); 30896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CompiledClass* compiled_class = writer_->compiler_driver_->GetCompiledClass(class_ref); 30996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko mirror::Class::Status status; 31096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (compiled_class != NULL) { 31196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko status = compiled_class->GetStatus(); 31296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } else if (writer_->compiler_driver_->GetVerificationResults()->IsClassRejected(class_ref)) { 31396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko status = mirror::Class::kStatusError; 31496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } else { 31596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko status = mirror::Class::kStatusNotReady; 31696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 31796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 31896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OatClass* oat_class = new OatClass(offset_, compiled_methods_, 31996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko num_non_null_compiled_methods_, status); 32096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko writer_->oat_classes_.push_back(oat_class); 32196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset_ += oat_class->SizeOf(); 32296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return DexMethodVisitor::EndClass(); 32396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 32496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 32596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko private: 32696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko std::vector<CompiledMethod*> compiled_methods_; 32796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t num_non_null_compiled_methods_; 32896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko}; 32996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 33096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markoclass OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { 33196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko public: 33296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko InitCodeMethodVisitor(OatWriter* writer, size_t offset) 33396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko : OatDexMethodVisitor(writer, offset) { 33496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 33596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 33696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) 33796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 33896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; 33996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 34096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 34196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (compiled_method != nullptr) { 34296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // Derived from CompiledMethod. 34396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko uint32_t quick_code_offset = 0; 34496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 34562746d8d9c4400e4764f162b22bfb1a32be287a9Andreas Gampe const SwapVector<uint8_t>* portable_code = compiled_method->GetPortableCode(); 34662746d8d9c4400e4764f162b22bfb1a32be287a9Andreas Gampe const SwapVector<uint8_t>* quick_code = compiled_method->GetQuickCode(); 34796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (portable_code != nullptr) { 34896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CHECK(quick_code == nullptr); 34996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t oat_method_offsets_offset = 35096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko oat_class->GetOatMethodOffsetsOffsetFromOatHeader(class_def_method_index); 35196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko compiled_method->AddOatdataOffsetToCompliledCodeOffset( 35296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko oat_method_offsets_offset + OFFSETOF_MEMBER(OatMethodOffsets, code_offset_)); 35396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } else { 35496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CHECK(quick_code != nullptr); 35596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset_ = compiled_method->AlignCode(offset_); 35696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_ALIGNED_PARAM(offset_, 35796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko GetInstructionSetAlignment(compiled_method->GetInstructionSet())); 35896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko uint32_t code_size = quick_code->size() * sizeof(uint8_t); 35996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CHECK_NE(code_size, 0U); 36096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko uint32_t thumb_offset = compiled_method->CodeDelta(); 3617624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko quick_code_offset = offset_ + sizeof(OatQuickMethodHeader) + thumb_offset; 36296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 36378382fa44ee505cf16835e4d22515e7252a90864Alex Light bool force_debug_capture = false; 36478382fa44ee505cf16835e4d22515e7252a90864Alex Light bool deduped = false; 36596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 36696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // Deduplicate code arrays. 367bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko auto lb = dedupe_map_.lower_bound(compiled_method); 368bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko if (lb != dedupe_map_.end() && !dedupe_map_.key_comp()(compiled_method, lb->first)) { 369bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko quick_code_offset = lb->second; 37078382fa44ee505cf16835e4d22515e7252a90864Alex Light deduped = true; 37196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } else { 372bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko dedupe_map_.PutBefore(lb, compiled_method, quick_code_offset); 3737624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko } 3747624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko 3757624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko // Update quick method header. 3767624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size()); 3777624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_]; 3787624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko uint32_t mapping_table_offset = method_header->mapping_table_offset_; 3797624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko uint32_t vmap_table_offset = method_header->vmap_table_offset_; 380c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier uint32_t gc_map_offset = method_header->gc_map_offset_; 3817624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko // The code offset was 0 when the mapping/vmap table offset was set, so it's set 3827624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko // to 0-offset and we need to adjust it by code_offset. 3837624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko uint32_t code_offset = quick_code_offset - thumb_offset; 3847624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko if (mapping_table_offset != 0u) { 3857624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko mapping_table_offset += code_offset; 3867624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko DCHECK_LT(mapping_table_offset, code_offset); 3877624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko } 3887624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko if (vmap_table_offset != 0u) { 3897624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko vmap_table_offset += code_offset; 3907624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko DCHECK_LT(vmap_table_offset, code_offset); 3917624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko } 392c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier if (gc_map_offset != 0u) { 393c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier gc_map_offset += code_offset; 394c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier DCHECK_LT(gc_map_offset, code_offset); 395c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier } 3967624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); 3977624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko uint32_t core_spill_mask = compiled_method->GetCoreSpillMask(); 3987624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko uint32_t fp_spill_mask = compiled_method->GetFpSpillMask(); 3997624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko *method_header = OatQuickMethodHeader(mapping_table_offset, vmap_table_offset, 400c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier gc_map_offset, frame_size_in_bytes, core_spill_mask, 401c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier fp_spill_mask, code_size); 4027624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko 4037624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko // Update checksum if this wasn't a duplicate. 404bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko if (!deduped) { 4058a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko writer_->oat_header_->UpdateChecksum(method_header, sizeof(*method_header)); 4068a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko offset_ += sizeof(*method_header); // Method header is prepended before code. 40796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko writer_->oat_header_->UpdateChecksum(&(*quick_code)[0], code_size); 4088a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko offset_ += code_size; 40996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 41078382fa44ee505cf16835e4d22515e7252a90864Alex Light 41178382fa44ee505cf16835e4d22515e7252a90864Alex Light uint32_t quick_code_start = quick_code_offset - writer_->oat_header_->GetExecutableOffset(); 41278382fa44ee505cf16835e4d22515e7252a90864Alex Light std::vector<uint8_t>* cfi_info = writer_->compiler_driver_->GetCallFrameInformation(); 41378382fa44ee505cf16835e4d22515e7252a90864Alex Light if (cfi_info != nullptr) { 41478382fa44ee505cf16835e4d22515e7252a90864Alex Light // Copy in the FDE, if present 41562746d8d9c4400e4764f162b22bfb1a32be287a9Andreas Gampe const SwapVector<uint8_t>* fde = compiled_method->GetCFIInfo(); 41678382fa44ee505cf16835e4d22515e7252a90864Alex Light if (fde != nullptr) { 41778382fa44ee505cf16835e4d22515e7252a90864Alex Light // Copy the information into cfi_info and then fix the address in the new copy. 41878382fa44ee505cf16835e4d22515e7252a90864Alex Light int cur_offset = cfi_info->size(); 41978382fa44ee505cf16835e4d22515e7252a90864Alex Light cfi_info->insert(cfi_info->end(), fde->begin(), fde->end()); 42078382fa44ee505cf16835e4d22515e7252a90864Alex Light 42135e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // Set the 'CIE_pointer' field to cur_offset+4. 42235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen uint32_t CIE_pointer = cur_offset + 4; 42335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen uint32_t offset_to_update = cur_offset + sizeof(uint32_t); 42435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen (*cfi_info)[offset_to_update+0] = CIE_pointer; 42535e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8; 42635e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16; 42735e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24; 42835e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 42978382fa44ee505cf16835e4d22515e7252a90864Alex Light // Set the 'initial_location' field to address the start of the method. 43035e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen offset_to_update = cur_offset + 2*sizeof(uint32_t); 43178382fa44ee505cf16835e4d22515e7252a90864Alex Light (*cfi_info)[offset_to_update+0] = quick_code_start; 43278382fa44ee505cf16835e4d22515e7252a90864Alex Light (*cfi_info)[offset_to_update+1] = quick_code_start >> 8; 43378382fa44ee505cf16835e4d22515e7252a90864Alex Light (*cfi_info)[offset_to_update+2] = quick_code_start >> 16; 43478382fa44ee505cf16835e4d22515e7252a90864Alex Light (*cfi_info)[offset_to_update+3] = quick_code_start >> 24; 43578382fa44ee505cf16835e4d22515e7252a90864Alex Light force_debug_capture = true; 43678382fa44ee505cf16835e4d22515e7252a90864Alex Light } 43778382fa44ee505cf16835e4d22515e7252a90864Alex Light } 43878382fa44ee505cf16835e4d22515e7252a90864Alex Light 43978382fa44ee505cf16835e4d22515e7252a90864Alex Light 44078382fa44ee505cf16835e4d22515e7252a90864Alex Light if (writer_->compiler_driver_->DidIncludeDebugSymbols() || force_debug_capture) { 44178382fa44ee505cf16835e4d22515e7252a90864Alex Light // Record debug information for this function if we are doing that or 44278382fa44ee505cf16835e4d22515e7252a90864Alex Light // we have CFI and so need it. 44378382fa44ee505cf16835e4d22515e7252a90864Alex Light std::string name = PrettyMethod(it.GetMemberIndex(), *dex_file_, true); 44478382fa44ee505cf16835e4d22515e7252a90864Alex Light if (deduped) { 44578382fa44ee505cf16835e4d22515e7252a90864Alex Light // TODO We should place the DEDUPED tag on the first instance of a 44678382fa44ee505cf16835e4d22515e7252a90864Alex Light // deduplicated symbol so that it will show up in a debuggerd crash 44778382fa44ee505cf16835e4d22515e7252a90864Alex Light // report. 44878382fa44ee505cf16835e4d22515e7252a90864Alex Light name += " [ DEDUPED ]"; 44978382fa44ee505cf16835e4d22515e7252a90864Alex Light } 45078382fa44ee505cf16835e4d22515e7252a90864Alex Light writer_->method_info_.push_back(DebugInfo(name, quick_code_start, 45178382fa44ee505cf16835e4d22515e7252a90864Alex Light quick_code_start + code_size)); 45278382fa44ee505cf16835e4d22515e7252a90864Alex Light } 45396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 45496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 45596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (kIsDebugBuild) { 45696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // We expect GC maps except when the class hasn't been verified or the method is native. 45796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko const CompilerDriver* compiler_driver = writer_->compiler_driver_; 45896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ClassReference class_ref(dex_file_, class_def_index_); 45996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CompiledClass* compiled_class = compiler_driver->GetCompiledClass(class_ref); 46096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko mirror::Class::Status status; 46196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (compiled_class != NULL) { 46296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko status = compiled_class->GetStatus(); 46396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } else if (compiler_driver->GetVerificationResults()->IsClassRejected(class_ref)) { 46496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko status = mirror::Class::kStatusError; 46596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } else { 46696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko status = mirror::Class::kStatusNotReady; 46796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 46862746d8d9c4400e4764f162b22bfb1a32be287a9Andreas Gampe const SwapVector<uint8_t>& gc_map = compiled_method->GetGcMap(); 46996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); 4707fc8f90b7160e879143be5cfd6ea3df866398884Andreas Gampe bool is_native = it.MemberIsNative(); 47196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CHECK(gc_map_size != 0 || is_native || status < mirror::Class::kStatusVerified) 47296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " 47396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko << (status < mirror::Class::kStatusVerified) << " " << status << " " 47496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko << PrettyMethod(it.GetMemberIndex(), *dex_file_); 47596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 47696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 47796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size()); 47896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OatMethodOffsets* offsets = &oat_class->method_offsets_[method_offsets_index_]; 47996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offsets->code_offset_ = quick_code_offset; 48096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ++method_offsets_index_; 48196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 48296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 48396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return true; 48496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 48596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 48696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko private: 48796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // Deduplication is already done on a pointer basis by the compiler driver, 48896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // so we can simply compare the pointers to find out if things are duplicated. 4898a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_; 49096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko}; 49196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 49296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markotemplate <typename DataAccess> 49396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markoclass OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor { 49496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko public: 49596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko InitMapMethodVisitor(OatWriter* writer, size_t offset) 49696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko : OatDexMethodVisitor(writer, offset) { 49796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 49896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 49996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) 50096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 50196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; 50296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 50396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 50496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (compiled_method != nullptr) { 50596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size()); 50696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_EQ(DataAccess::GetOffset(oat_class, method_offsets_index_), 0u); 50796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 50862746d8d9c4400e4764f162b22bfb1a32be287a9Andreas Gampe const SwapVector<uint8_t>* map = DataAccess::GetData(compiled_method); 50996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko uint32_t map_size = map->size() * sizeof((*map)[0]); 51096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (map_size != 0u) { 511bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko auto lb = dedupe_map_.lower_bound(map); 512bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko if (lb != dedupe_map_.end() && !dedupe_map_.key_comp()(map, lb->first)) { 513bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko DataAccess::SetOffset(oat_class, method_offsets_index_, lb->second); 51496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } else { 51596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DataAccess::SetOffset(oat_class, method_offsets_index_, offset_); 516bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko dedupe_map_.PutBefore(lb, map, offset_); 51796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset_ += map_size; 51896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko writer_->oat_header_->UpdateChecksum(&(*map)[0], map_size); 51996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 52096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 52196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ++method_offsets_index_; 52296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 52396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 52496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return true; 52596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 52696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 52796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko private: 52896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // Deduplication is already done on a pointer basis by the compiler driver, 52996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // so we can simply compare the pointers to find out if things are duplicated. 53062746d8d9c4400e4764f162b22bfb1a32be287a9Andreas Gampe SafeMap<const SwapVector<uint8_t>*, uint32_t> dedupe_map_; 53196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko}; 53296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 53396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markoclass OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor { 53496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko public: 53596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko InitImageMethodVisitor(OatWriter* writer, size_t offset) 53696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko : OatDexMethodVisitor(writer, offset) { 53796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 53896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 53996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) 54096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 54196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; 54296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 54396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 544c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier OatMethodOffsets offsets(0u); 54596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (compiled_method != nullptr) { 54696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size()); 54796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offsets = oat_class->method_offsets_[method_offsets_index_]; 54896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ++method_offsets_index_; 54996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 55096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 55196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ClassLinker* linker = Runtime::Current()->GetClassLinker(); 55296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko InvokeType invoke_type = it.GetMethodInvokeType(dex_file_->GetClassDef(class_def_index_)); 55396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // Unchecked as we hold mutator_lock_ on entry. 55496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ScopedObjectAccessUnchecked soa(Thread::Current()); 555c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier StackHandleScope<1> hs(soa.Self()); 556eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(*dex_file_))); 5577624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko mirror::ArtMethod* method = linker->ResolveMethod(*dex_file_, it.GetMemberIndex(), dex_cache, 5580cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier NullHandle<mirror::ClassLoader>(), 5590cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier NullHandle<mirror::ArtMethod>(), 5600cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier invoke_type); 5613c911d68f10e5ee7c7055bac63ac8f523949e37dBrian Carlstrom CHECK(method != NULL) << PrettyMethod(it.GetMemberIndex(), *dex_file_, true); 56296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // Portable code offsets are set by ElfWriterMclinker::FixupCompiledCodeOffset after linking. 56396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko method->SetQuickOatCodeOffset(offsets.code_offset_); 56496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 56596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return true; 56696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 56796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko}; 56896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 56996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markoclass OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { 57096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko public: 57196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko WriteCodeMethodVisitor(OatWriter* writer, OutputStream* out, const size_t file_offset, 57296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t relative_offset) 57396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko : OatDexMethodVisitor(writer, relative_offset), 57496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko out_(out), 57596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko file_offset_(file_offset) { 57696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 57796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 57896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) { 57996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; 58096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 58196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 58296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (compiled_method != NULL) { // ie. not an abstract method 58396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t file_offset = file_offset_; 58496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OutputStream* out = out_; 58596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 58662746d8d9c4400e4764f162b22bfb1a32be287a9Andreas Gampe const SwapVector<uint8_t>* quick_code = compiled_method->GetQuickCode(); 58796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (quick_code != nullptr) { 58896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CHECK(compiled_method->GetPortableCode() == nullptr); 58996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko uint32_t aligned_offset = compiled_method->AlignCode(offset_); 59096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko uint32_t aligned_code_delta = aligned_offset - offset_; 59196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (aligned_code_delta != 0) { 59296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko static const uint8_t kPadding[] = { 59396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u 59496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko }; 59596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_LE(aligned_code_delta, sizeof(kPadding)); 59696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (UNLIKELY(!out->WriteFully(kPadding, aligned_code_delta))) { 59796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ReportWriteFailure("code alignment padding", it); 59896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return false; 59996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 60096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko writer_->size_code_alignment_ += aligned_code_delta; 60196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset_ += aligned_code_delta; 60296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_OFFSET_(); 60396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 60496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_ALIGNED_PARAM(offset_, 60596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko GetInstructionSetAlignment(compiled_method->GetInstructionSet())); 60696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko uint32_t code_size = quick_code->size() * sizeof(uint8_t); 60796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CHECK_NE(code_size, 0U); 60896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 60996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // Deduplicate code arrays. 61096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index_]; 61196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK(method_offsets.code_offset_ < offset_ || method_offsets.code_offset_ == 6127624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta()) 61396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko << PrettyMethod(it.GetMemberIndex(), *dex_file_); 61496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (method_offsets.code_offset_ >= offset_) { 615c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier const OatQuickMethodHeader& method_header = 616c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier oat_class->method_headers_[method_offsets_index_]; 61796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (!out->WriteFully(&method_header, sizeof(method_header))) { 61896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ReportWriteFailure("method header", it); 61996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return false; 62096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 62196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko writer_->size_method_header_ += sizeof(method_header); 62296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset_ += sizeof(method_header); 62396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_OFFSET_(); 62496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (!out->WriteFully(&(*quick_code)[0], code_size)) { 62596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ReportWriteFailure("method code", it); 62696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return false; 62796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 62896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko writer_->size_code_ += code_size; 62996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset_ += code_size; 63096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 63196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_OFFSET_(); 63296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 63396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ++method_offsets_index_; 63496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 63596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 63696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return true; 63796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 63896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 63996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko private: 64096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OutputStream* const out_; 64196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t const file_offset_; 64296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 64396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko void ReportWriteFailure(const char* what, const ClassDataItemIterator& it) { 64496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko PLOG(ERROR) << "Failed to write " << what << " for " 64596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " to " << out_->GetLocation(); 64696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 64796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko}; 64896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 64996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markotemplate <typename DataAccess> 65096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markoclass OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor { 65196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko public: 65296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko WriteMapMethodVisitor(OatWriter* writer, OutputStream* out, const size_t file_offset, 653c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier size_t relative_offset) 65496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko : OatDexMethodVisitor(writer, relative_offset), 65596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko out_(out), 65696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko file_offset_(file_offset) { 65796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 65896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 65996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) { 66096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; 66196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 66296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 66396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (compiled_method != NULL) { // ie. not an abstract method 66496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t file_offset = file_offset_; 66596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OutputStream* out = out_; 66696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 66796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko uint32_t map_offset = DataAccess::GetOffset(oat_class, method_offsets_index_); 66896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ++method_offsets_index_; 66996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 67096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // Write deduplicated map. 67162746d8d9c4400e4764f162b22bfb1a32be287a9Andreas Gampe const SwapVector<uint8_t>* map = DataAccess::GetData(compiled_method); 67296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t map_size = map->size() * sizeof((*map)[0]); 67396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK((map_size == 0u && map_offset == 0u) || 67496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko (map_size != 0u && map_offset != 0u && map_offset <= offset_)) 675c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier << map_size << " " << map_offset << " " << offset_ << " " 676c6fc909c6b42b4c365b1e7f86639ee4b360249faMathieu Chartier << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " for " << DataAccess::Name(); 67796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (map_size != 0u && map_offset == offset_) { 67896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (UNLIKELY(!out->WriteFully(&(*map)[0], map_size))) { 67996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ReportWriteFailure(it); 68096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return false; 68196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 68296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset_ += map_size; 68396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 68496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_OFFSET_(); 68596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 68696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 68796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return true; 68896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 68996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 69096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko private: 69196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko OutputStream* const out_; 69296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t const file_offset_; 69396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 69496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko void ReportWriteFailure(const ClassDataItemIterator& it) { 69596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko PLOG(ERROR) << "Failed to write " << DataAccess::Name() << " for " 69696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " to " << out_->GetLocation(); 69796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 69896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko}; 69996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 70096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko// Visit all methods from all classes in all dex files with the specified visitor. 70196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markobool OatWriter::VisitDexMethods(DexMethodVisitor* visitor) { 70296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko for (const DexFile* dex_file : *dex_files_) { 70396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko const size_t class_def_count = dex_file->NumClassDefs(); 70496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko for (size_t class_def_index = 0; class_def_index != class_def_count; ++class_def_index) { 70596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (UNLIKELY(!visitor->StartClass(dex_file, class_def_index))) { 70696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return false; 70796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 70896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); 70996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko const byte* class_data = dex_file->GetClassData(class_def); 71096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (class_data != NULL) { // ie not an empty class, such as a marker interface 71196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ClassDataItemIterator it(*dex_file, class_data); 71296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko while (it.HasNextStaticField()) { 71396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko it.Next(); 71496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 71596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko while (it.HasNextInstanceField()) { 71696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko it.Next(); 71796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 71896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t class_def_method_index = 0u; 71996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko while (it.HasNextDirectMethod()) { 72096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (!visitor->VisitMethod(class_def_method_index, it)) { 72196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return false; 72296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 72396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ++class_def_method_index; 72496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko it.Next(); 72596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 72696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko while (it.HasNextVirtualMethod()) { 72796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (UNLIKELY(!visitor->VisitMethod(class_def_method_index, it))) { 72896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return false; 72996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 73096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ++class_def_method_index; 73196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko it.Next(); 73296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 73396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 73496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (UNLIKELY(!visitor->EndClass())) { 73596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return false; 73696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 73796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 73896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 73996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return true; 74096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko} 74196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 74281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstromsize_t OatWriter::InitOatHeader() { 74322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe oat_header_ = OatHeader::Create(compiler_driver_->GetInstructionSet(), 74422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe compiler_driver_->GetInstructionSetFeatures(), 74522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe dex_files_, 74622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe image_file_location_oat_checksum_, 74722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe image_file_location_oat_begin_, 74822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe key_value_store_); 74922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe 75022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe return oat_header_->GetHeaderSize(); 751e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 752e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 753e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatDexFiles(size_t offset) { 754e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // create the OatDexFiles 755e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 756e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 757e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 758265091e581c9f643b37e7966890911f09e223269Brian Carlstrom OatDexFile* oat_dex_file = new OatDexFile(offset, *dex_file); 759e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_dex_files_.push_back(oat_dex_file); 760e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset += oat_dex_file->SizeOf(); 761e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 762e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 763e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 764e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 76589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstromsize_t OatWriter::InitDexFiles(size_t offset) { 76689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // calculate the offsets within OatDexFiles to the DexFiles 76789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 76889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // dex files are required to be 4 byte aligned 7690aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_t original_offset = offset; 77089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom offset = RoundUp(offset, 4); 7710aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_dex_file_alignment_ += offset - original_offset; 77289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 77389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom // set offset in OatDexFile to DexFile 77489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom oat_dex_files_[i]->dex_file_offset_ = offset; 77589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 77689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 77789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom offset += dex_file->GetHeader().file_size_; 77889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 77989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return offset; 78089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom} 78189521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 782389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstromsize_t OatWriter::InitOatClasses(size_t offset) { 783389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom // calculate the offsets within OatDexFiles to OatClasses 78496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko InitOatClassesMethodVisitor visitor(this, offset); 78596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool success = VisitDexMethods(&visitor); 78696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CHECK(success); 78796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset = visitor.GetOffset(); 78896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 78996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko // Update oat_dex_files_. 79096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko auto oat_class_it = oat_classes_.begin(); 79196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko for (OatDexFile* oat_dex_file : oat_dex_files_) { 79296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko for (uint32_t& offset : oat_dex_file->methods_offsets_) { 79396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK(oat_class_it != oat_classes_.end()); 79496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset = (*oat_class_it)->offset_; 79596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko ++oat_class_it; 796e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 79796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko oat_dex_file->UpdateChecksum(oat_header_); 798e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 79996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CHECK(oat_class_it == oat_classes_.end()); 80096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 80196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return offset; 80296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko} 80396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 80496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markosize_t OatWriter::InitOatMaps(size_t offset) { 80596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko #define VISIT(VisitorType) \ 80696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko do { \ 80796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VisitorType visitor(this, offset); \ 80896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool success = VisitDexMethods(&visitor); \ 80996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK(success); \ 81096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset = visitor.GetOffset(); \ 81196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } while (false) 81296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 81396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VISIT(InitMapMethodVisitor<GcMapDataAccess>); 81496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VISIT(InitMapMethodVisitor<MappingTableDataAccess>); 81596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VISIT(InitMapMethodVisitor<VmapTableDataAccess>); 81696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 81796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko #undef VISIT 81896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 819e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 820e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 821e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 822e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCode(size_t offset) { 823e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // calculate the offsets within OatHeader to executable code 824e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t old_offset = offset; 82550abf0ad03c2cad0fa7969fc1b0bfadb0ca3bf3aDave Allison size_t adjusted_offset = offset; 826e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // required to be on a new page boundary 827e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = RoundUp(offset, kPageSize); 828e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header_->SetExecutableOffset(offset); 8290aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_executable_offset_alignment_ = offset - old_offset; 8300aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao if (compiler_driver_->IsImage()) { 831a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light CHECK_EQ(image_patch_delta_, 0); 8320aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); 833848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 834848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers #define DO_TRAMPOLINE(field, fn_name) \ 835848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers offset = CompiledCode::AlignCode(offset, instruction_set); \ 83650abf0ad03c2cad0fa7969fc1b0bfadb0ca3bf3aDave Allison adjusted_offset = offset + CompiledCode::CodeDelta(instruction_set); \ 83750abf0ad03c2cad0fa7969fc1b0bfadb0ca3bf3aDave Allison oat_header_->Set ## fn_name ## Offset(adjusted_offset); \ 838848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers field.reset(compiler_driver_->Create ## fn_name()); \ 839848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers offset += field->size(); 840848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 841848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(interpreter_to_interpreter_bridge_, InterpreterToInterpreterBridge); 842848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(interpreter_to_compiled_code_bridge_, InterpreterToCompiledCodeBridge); 843848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(jni_dlsym_lookup_, JniDlsymLookup); 84488474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_TRAMPOLINE(portable_imt_conflict_trampoline_, PortableImtConflictTrampoline); 845848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(portable_resolution_trampoline_, PortableResolutionTrampoline); 846848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(portable_to_interpreter_bridge_, PortableToInterpreterBridge); 8472da882315a61072664f7ce3c212307342e907207Andreas Gampe DO_TRAMPOLINE(quick_generic_jni_trampoline_, QuickGenericJniTrampoline); 84888474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_TRAMPOLINE(quick_imt_conflict_trampoline_, QuickImtConflictTrampoline); 849848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(quick_resolution_trampoline_, QuickResolutionTrampoline); 850848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(quick_to_interpreter_bridge_, QuickToInterpreterBridge); 851848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 852848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers #undef DO_TRAMPOLINE 8530aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao } else { 854848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_header_->SetInterpreterToInterpreterBridgeOffset(0); 855848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_header_->SetInterpreterToCompiledCodeBridgeOffset(0); 856848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_header_->SetJniDlsymLookupOffset(0); 85788474b416eb257078e590bf9bc7957cee604a186Jeff Hao oat_header_->SetPortableImtConflictTrampolineOffset(0); 8580aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_header_->SetPortableResolutionTrampolineOffset(0); 859848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_header_->SetPortableToInterpreterBridgeOffset(0); 8602da882315a61072664f7ce3c212307342e907207Andreas Gampe oat_header_->SetQuickGenericJniTrampolineOffset(0); 86188474b416eb257078e590bf9bc7957cee604a186Jeff Hao oat_header_->SetQuickImtConflictTrampolineOffset(0); 8620aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_header_->SetQuickResolutionTrampolineOffset(0); 863848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_header_->SetQuickToInterpreterBridgeOffset(0); 864a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light oat_header_->SetImagePatchDelta(image_patch_delta_); 8650aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao } 866e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 867e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 868e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 869e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeDexFiles(size_t offset) { 87096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko #define VISIT(VisitorType) \ 87196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko do { \ 87296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VisitorType visitor(this, offset); \ 87396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko bool success = VisitDexMethods(&visitor); \ 87496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK(success); \ 87596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko offset = visitor.GetOffset(); \ 87696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } while (false) 87796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 87896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VISIT(InitCodeMethodVisitor); 8791212a022fa5f8ef9585d765b1809521812af882cIan Rogers if (compiler_driver_->IsImage()) { 88096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VISIT(InitImageMethodVisitor); 8810571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 8828b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien 88396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko #undef VISIT 88496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 885e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 886e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 887e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 8883d504075f7c1204d581923460754bf6d3714b13fIan Rogersbool OatWriter::Write(OutputStream* out) { 8893d504075f7c1204d581923460754bf6d3714b13fIan Rogers const size_t file_offset = out->Seek(0, kSeekCurrent); 890c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom 89122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe size_t header_size = oat_header_->GetHeaderSize(); 89222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe if (!out->WriteFully(oat_header_, header_size)) { 8933d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write oat header to " << out->GetLocation(); 894e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 895e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 89622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe size_oat_header_ += sizeof(OatHeader); 89722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe size_oat_header_key_value_store_ += oat_header_->GetHeaderSize() - sizeof(OatHeader); 89881f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom 899c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (!WriteTables(out, file_offset)) { 9003d504075f7c1204d581923460754bf6d3714b13fIan Rogers LOG(ERROR) << "Failed to write oat tables to " << out->GetLocation(); 901e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 902e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 903e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 90496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t relative_offset = out->Seek(0, kSeekCurrent) - file_offset; 90596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko relative_offset = WriteMaps(out, file_offset, relative_offset); 90696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (relative_offset == 0) { 90796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko LOG(ERROR) << "Failed to write oat code to " << out->GetLocation(); 90896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return false; 90996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } 91096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 91196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko relative_offset = WriteCode(out, file_offset, relative_offset); 912c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (relative_offset == 0) { 9133d504075f7c1204d581923460754bf6d3714b13fIan Rogers LOG(ERROR) << "Failed to write oat code to " << out->GetLocation(); 914e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 915e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 916e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 917c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom relative_offset = WriteCodeDexFiles(out, file_offset, relative_offset); 918c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (relative_offset == 0) { 9193d504075f7c1204d581923460754bf6d3714b13fIan Rogers LOG(ERROR) << "Failed to write oat code for dex files to " << out->GetLocation(); 920e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 921e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 922e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 9234bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers if (kIsDebugBuild) { 9244bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers uint32_t size_total = 0; 9254bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers #define DO_STAT(x) \ 92675a43f10f55e2aa550de51e969cc1e60d583b632Anwar Ghuloum VLOG(compiler) << #x "=" << PrettySize(x) << " (" << x << "B)"; \ 9274bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers size_total += x; 9284bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers 9294bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_dex_file_alignment_); 9304bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_executable_offset_alignment_); 9314bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_header_); 93222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe DO_STAT(size_oat_header_key_value_store_); 9334bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_dex_file_); 934848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_interpreter_to_interpreter_bridge_); 935848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_interpreter_to_compiled_code_bridge_); 936848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_jni_dlsym_lookup_); 93788474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_STAT(size_portable_imt_conflict_trampoline_); 9384bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_portable_resolution_trampoline_); 939848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_portable_to_interpreter_bridge_); 9402da882315a61072664f7ce3c212307342e907207Andreas Gampe DO_STAT(size_quick_generic_jni_trampoline_); 94188474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_STAT(size_quick_imt_conflict_trampoline_); 9424bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_quick_resolution_trampoline_); 943848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_quick_to_interpreter_bridge_); 944848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_STAT(size_trampoline_alignment_); 94596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DO_STAT(size_method_header_); 9464bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_code_); 9474bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_code_alignment_); 9484bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_mapping_table_); 9494bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_vmap_table_); 9504bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_gc_map_); 9514bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_dex_file_location_size_); 9524bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_dex_file_location_data_); 9534bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_dex_file_location_checksum_); 9544bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_dex_file_offset_); 9554bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_dex_file_methods_offsets_); 956ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom DO_STAT(size_oat_class_type_); 9574bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_class_status_); 958ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom DO_STAT(size_oat_class_method_bitmaps_); 9594bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers DO_STAT(size_oat_class_method_offsets_); 9604bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers #undef DO_STAT 9614bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers 96275a43f10f55e2aa550de51e969cc1e60d583b632Anwar Ghuloum VLOG(compiler) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)"; \ 9633d504075f7c1204d581923460754bf6d3714b13fIan Rogers CHECK_EQ(file_offset + size_total, static_cast<uint32_t>(out->Seek(0, kSeekCurrent))); 964c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom CHECK_EQ(size_, size_total); 9654bdbbc86838f3f07bf122b28c8ed5eb28d9b1719Ian Rogers } 9660aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao 9673d504075f7c1204d581923460754bf6d3714b13fIan Rogers CHECK_EQ(file_offset + size_, static_cast<uint32_t>(out->Seek(0, kSeekCurrent))); 968c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom CHECK_EQ(size_, relative_offset); 969c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom 970e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 971e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 972e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 9733d504075f7c1204d581923460754bf6d3714b13fIan Rogersbool OatWriter::WriteTables(OutputStream* out, const size_t file_offset) { 974e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 975c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (!oat_dex_files_[i]->Write(this, out, file_offset)) { 9763d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write oat dex information to " << out->GetLocation(); 977e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 978e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 979e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 98089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 981c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom uint32_t expected_offset = file_offset + oat_dex_files_[i]->dex_file_offset_; 9823d504075f7c1204d581923460754bf6d3714b13fIan Rogers off_t actual_offset = out->Seek(expected_offset, kSeekSet); 98389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom if (static_cast<uint32_t>(actual_offset) != expected_offset) { 98489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 98589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset 98689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom << " Expected: " << expected_offset << " File: " << dex_file->GetLocation(); 98789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 98889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 98989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 9903d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&dex_file->GetHeader(), dex_file->GetHeader().file_size_)) { 991c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom PLOG(ERROR) << "Failed to write dex file " << dex_file->GetLocation() 9923d504075f7c1204d581923460754bf6d3714b13fIan Rogers << " to " << out->GetLocation(); 99389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 99489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 9950aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao size_dex_file_ += dex_file->GetHeader().file_size_; 99689521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 997389efb00642100fa1c50bd47d1b8267541f9710fBrian Carlstrom for (size_t i = 0; i != oat_classes_.size(); ++i) { 998c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (!oat_classes_[i]->Write(this, out, file_offset)) { 9993d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write oat methods information to " << out->GetLocation(); 1000e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 1001e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 1002e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 1003e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 1004e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1005e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 100696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markosize_t OatWriter::WriteMaps(OutputStream* out, const size_t file_offset, size_t relative_offset) { 100796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko #define VISIT(VisitorType) \ 100896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko do { \ 100996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VisitorType visitor(this, out, file_offset, relative_offset); \ 101096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (UNLIKELY(!VisitDexMethods(&visitor))) { \ 101196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return 0; \ 101296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } \ 101396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko relative_offset = visitor.GetOffset(); \ 101496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } while (false) 101596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 101696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t gc_maps_offset = relative_offset; 101796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VISIT(WriteMapMethodVisitor<GcMapDataAccess>); 101896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_gc_map_ = relative_offset - gc_maps_offset; 101996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 102096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t mapping_tables_offset = relative_offset; 102196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VISIT(WriteMapMethodVisitor<MappingTableDataAccess>); 102296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_mapping_table_ = relative_offset - mapping_tables_offset; 102396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 102496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_t vmap_tables_offset = relative_offset; 102596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VISIT(WriteMapMethodVisitor<VmapTableDataAccess>); 102696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko size_vmap_table_ = relative_offset - vmap_tables_offset; 102796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 102896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko #undef VISIT 102996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 103096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return relative_offset; 103196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko} 103296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko 103396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Markosize_t OatWriter::WriteCode(OutputStream* out, const size_t file_offset, size_t relative_offset) { 10343d504075f7c1204d581923460754bf6d3714b13fIan Rogers off_t new_offset = out->Seek(size_executable_offset_alignment_, kSeekCurrent); 103596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko relative_offset += size_executable_offset_alignment_; 103696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko DCHECK_EQ(relative_offset, oat_header_->GetExecutableOffset()); 1037c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom size_t expected_file_offset = file_offset + relative_offset; 1038c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom if (static_cast<uint32_t>(new_offset) != expected_file_offset) { 10393320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset 10403d504075f7c1204d581923460754bf6d3714b13fIan Rogers << " Expected: " << expected_file_offset << " File: " << out->GetLocation(); 1041e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 1042e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 1043265091e581c9f643b37e7966890911f09e223269Brian Carlstrom DCHECK_OFFSET(); 10440aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao if (compiler_driver_->IsImage()) { 10450aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); 1046848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 1047848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers #define DO_TRAMPOLINE(field) \ 1048848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers do { \ 1049848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers uint32_t aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set); \ 1050848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers uint32_t alignment_padding = aligned_offset - relative_offset; \ 10513d504075f7c1204d581923460754bf6d3714b13fIan Rogers out->Seek(alignment_padding, kSeekCurrent); \ 1052848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_trampoline_alignment_ += alignment_padding; \ 10533d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&(*field)[0], field->size())) { \ 10543d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write " # field " to " << out->GetLocation(); \ 1055848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers return false; \ 1056848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } \ 1057848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_ ## field += field->size(); \ 1058848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers relative_offset += alignment_padding + field->size(); \ 1059848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DCHECK_OFFSET(); \ 1060848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } while (false) 1061848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 1062848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(interpreter_to_interpreter_bridge_); 1063848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(interpreter_to_compiled_code_bridge_); 1064848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(jni_dlsym_lookup_); 106588474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_TRAMPOLINE(portable_imt_conflict_trampoline_); 1066848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(portable_resolution_trampoline_); 1067848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(portable_to_interpreter_bridge_); 10682da882315a61072664f7ce3c212307342e907207Andreas Gampe DO_TRAMPOLINE(quick_generic_jni_trampoline_); 106988474b416eb257078e590bf9bc7957cee604a186Jeff Hao DO_TRAMPOLINE(quick_imt_conflict_trampoline_); 1070848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(quick_resolution_trampoline_); 1071848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DO_TRAMPOLINE(quick_to_interpreter_bridge_); 1072848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers #undef DO_TRAMPOLINE 10730aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao } 1074c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom return relative_offset; 1075e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1076e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 10773d504075f7c1204d581923460754bf6d3714b13fIan Rogerssize_t OatWriter::WriteCodeDexFiles(OutputStream* out, 1078c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom const size_t file_offset, 1079c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom size_t relative_offset) { 108096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko #define VISIT(VisitorType) \ 108196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko do { \ 108296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VisitorType visitor(this, out, file_offset, relative_offset); \ 108396c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko if (UNLIKELY(!VisitDexMethods(&visitor))) { \ 108496c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko return 0; \ 108596c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } \ 108696c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko relative_offset = visitor.GetOffset(); \ 108796c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko } while (false) 1088234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes 108996c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko VISIT(WriteCodeMethodVisitor); 1090e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 109196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko #undef VISIT 1092265091e581c9f643b37e7966890911f09e223269Brian Carlstrom 1093c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom return relative_offset; 1094e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1095e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1096265091e581c9f643b37e7966890911f09e223269Brian CarlstromOatWriter::OatDexFile::OatDexFile(size_t offset, const DexFile& dex_file) { 1097265091e581c9f643b37e7966890911f09e223269Brian Carlstrom offset_ = offset; 1098955724179c6c739524f610023287f56b24dc31deElliott Hughes const std::string& location(dex_file.GetLocation()); 1099e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_size_ = location.size(); 1100e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data()); 11015b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom dex_file_location_checksum_ = dex_file.GetLocationChecksum(); 110289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom dex_file_offset_ = 0; 11036e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom methods_offsets_.resize(dex_file.NumClassDefs()); 1104e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1105e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1106e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::OatDexFile::SizeOf() const { 1107e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return sizeof(dex_file_location_size_) 1108e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom + dex_file_location_size_ 11095b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom + sizeof(dex_file_location_checksum_) 111089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom + sizeof(dex_file_offset_) 11116e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom + (sizeof(methods_offsets_[0]) * methods_offsets_.size()); 1112e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1113e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 11143d504075f7c1204d581923460754bf6d3714b13fIan Rogersvoid OatWriter::OatDexFile::UpdateChecksum(OatHeader* oat_header) const { 11153d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&dex_file_location_size_, sizeof(dex_file_location_size_)); 11163d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(dex_file_location_data_, dex_file_location_size_); 11173d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_)); 11183d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&dex_file_offset_, sizeof(dex_file_offset_)); 11193d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&methods_offsets_[0], 11206e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom sizeof(methods_offsets_[0]) * methods_offsets_.size()); 1121e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1122e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1123c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrombool OatWriter::OatDexFile::Write(OatWriter* oat_writer, 11243d504075f7c1204d581923460754bf6d3714b13fIan Rogers OutputStream* out, 1125c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom const size_t file_offset) const { 1126265091e581c9f643b37e7966890911f09e223269Brian Carlstrom DCHECK_OFFSET_(); 11273d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) { 11283d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write dex file location length to " << out->GetLocation(); 1129e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 1130e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 11310aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_dex_file_location_size_ += sizeof(dex_file_location_size_); 11323d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(dex_file_location_data_, dex_file_location_size_)) { 11333d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write dex file location data to " << out->GetLocation(); 1134e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 1135e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 11360aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_dex_file_location_data_ += dex_file_location_size_; 11373d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_))) { 11383d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write dex file location checksum to " << out->GetLocation(); 1139e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 1140e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 11410aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_dex_file_location_checksum_ += sizeof(dex_file_location_checksum_); 11423d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) { 11433d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write dex file offset to " << out->GetLocation(); 114489521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom return false; 114589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom } 11460aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_dex_file_offset_ += sizeof(dex_file_offset_); 11473d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&methods_offsets_[0], 1148cd60ac736bc7104785dc67671660d70fb434466fBrian Carlstrom sizeof(methods_offsets_[0]) * methods_offsets_.size())) { 11493d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write methods offsets to " << out->GetLocation(); 1150e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 1151e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 11520aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_dex_file_methods_offsets_ += 11530aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao sizeof(methods_offsets_[0]) * methods_offsets_.size(); 1154e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 1155e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1156e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1157ba150c37d582eeeb8c11ba5245edc281cf31793cBrian CarlstromOatWriter::OatClass::OatClass(size_t offset, 115896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko const std::vector<CompiledMethod*>& compiled_methods, 1159ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t num_non_null_compiled_methods, 116096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko mirror::Class::Status status) 116196c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko : compiled_methods_(compiled_methods) { 116296c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko uint32_t num_methods = compiled_methods.size(); 1163ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LE(num_non_null_compiled_methods, num_methods); 1164ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 1165265091e581c9f643b37e7966890911f09e223269Brian Carlstrom offset_ = offset; 1166ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offsets_from_oat_class_.resize(num_methods); 1167ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 1168ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // Since both kOatClassNoneCompiled and kOatClassAllCompiled could 1169ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // apply when there are 0 methods, we just arbitrarily say that 0 1170ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // methods means kOatClassNoneCompiled and that we won't use 1171ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // kOatClassAllCompiled unless there is at least one compiled 1172ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // method. This means in an interpretter only system, we can assert 1173ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom // that all classes are kOatClassNoneCompiled. 1174ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (num_non_null_compiled_methods == 0) { 1175ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom type_ = kOatClassNoneCompiled; 1176ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } else if (num_non_null_compiled_methods == num_methods) { 1177ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom type_ = kOatClassAllCompiled; 1178ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } else { 1179ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom type_ = kOatClassSomeCompiled; 1180ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1181ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 11820755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom status_ = status; 1183ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_offsets_.resize(num_non_null_compiled_methods); 11848a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko method_headers_.resize(num_non_null_compiled_methods); 1185ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 1186ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t oat_method_offsets_offset_from_oat_class = sizeof(type_) + sizeof(status_); 1187ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (type_ == kOatClassSomeCompiled) { 1188ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_bitmap_ = new BitVector(num_methods, false, Allocator::GetMallocAllocator()); 1189ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_bitmap_size_ = method_bitmap_->GetSizeOf(); 1190ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offset_from_oat_class += sizeof(method_bitmap_size_); 1191ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offset_from_oat_class += method_bitmap_size_; 1192ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } else { 1193ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_bitmap_ = NULL; 1194ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_bitmap_size_ = 0; 1195ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1196ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 1197ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom for (size_t i = 0; i < num_methods; i++) { 119896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko CompiledMethod* compiled_method = compiled_methods_[i]; 1199ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (compiled_method == NULL) { 1200ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offsets_from_oat_class_[i] = 0; 1201ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } else { 1202ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offsets_from_oat_class_[i] = oat_method_offsets_offset_from_oat_class; 1203ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_method_offsets_offset_from_oat_class += sizeof(OatMethodOffsets); 1204ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (type_ == kOatClassSomeCompiled) { 1205ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom method_bitmap_->SetBit(i); 1206ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1207ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1208ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1209e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1210e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1211ba150c37d582eeeb8c11ba5245edc281cf31793cBrian CarlstromOatWriter::OatClass::~OatClass() { 1212661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier delete method_bitmap_; 1213ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom} 1214ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 1215265091e581c9f643b37e7966890911f09e223269Brian Carlstromsize_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatHeader( 1216265091e581c9f643b37e7966890911f09e223269Brian Carlstrom size_t class_def_method_index_) const { 1217ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t method_offset = GetOatMethodOffsetsOffsetFromOatClass(class_def_method_index_); 1218ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (method_offset == 0) { 1219ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return 0; 1220ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1221ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return offset_ + method_offset; 1222265091e581c9f643b37e7966890911f09e223269Brian Carlstrom} 1223265091e581c9f643b37e7966890911f09e223269Brian Carlstrom 1224265091e581c9f643b37e7966890911f09e223269Brian Carlstromsize_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatClass( 1225265091e581c9f643b37e7966890911f09e223269Brian Carlstrom size_t class_def_method_index_) const { 1226ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return oat_method_offsets_offsets_from_oat_class_[class_def_method_index_]; 1227265091e581c9f643b37e7966890911f09e223269Brian Carlstrom} 1228265091e581c9f643b37e7966890911f09e223269Brian Carlstrom 1229265091e581c9f643b37e7966890911f09e223269Brian Carlstromsize_t OatWriter::OatClass::SizeOf() const { 1230ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return sizeof(status_) 1231ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom + sizeof(type_) 1232ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom + ((method_bitmap_size_ == 0) ? 0 : sizeof(method_bitmap_size_)) 1233ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom + method_bitmap_size_ 1234ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom + (sizeof(method_offsets_[0]) * method_offsets_.size()); 1235e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1236e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 12373d504075f7c1204d581923460754bf6d3714b13fIan Rogersvoid OatWriter::OatClass::UpdateChecksum(OatHeader* oat_header) const { 12383d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&status_, sizeof(status_)); 12393d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&type_, sizeof(type_)); 1240ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (method_bitmap_size_ != 0) { 1241ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(kOatClassSomeCompiled, type_); 12423d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&method_bitmap_size_, sizeof(method_bitmap_size_)); 12433d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(method_bitmap_->GetRawStorage(), method_bitmap_size_); 1244ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 12453d504075f7c1204d581923460754bf6d3714b13fIan Rogers oat_header->UpdateChecksum(&method_offsets_[0], 12463d504075f7c1204d581923460754bf6d3714b13fIan Rogers sizeof(method_offsets_[0]) * method_offsets_.size()); 1247e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1248e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1249c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrombool OatWriter::OatClass::Write(OatWriter* oat_writer, 12503d504075f7c1204d581923460754bf6d3714b13fIan Rogers OutputStream* out, 1251c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom const size_t file_offset) const { 1252265091e581c9f643b37e7966890911f09e223269Brian Carlstrom DCHECK_OFFSET_(); 12533d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&status_, sizeof(status_))) { 12543d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write class status to " << out->GetLocation(); 12550755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom return false; 12560755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom } 12570aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_class_status_ += sizeof(status_); 12583d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&type_, sizeof(type_))) { 12593d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write oat class type to " << out->GetLocation(); 1260ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return false; 1261ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1262ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_writer->size_oat_class_type_ += sizeof(type_); 1263ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (method_bitmap_size_ != 0) { 1264ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(kOatClassSomeCompiled, type_); 12653d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&method_bitmap_size_, sizeof(method_bitmap_size_))) { 12663d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write method bitmap size to " << out->GetLocation(); 1267ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return false; 1268ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1269ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_writer->size_oat_class_method_bitmaps_ += sizeof(method_bitmap_size_); 12703d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(method_bitmap_->GetRawStorage(), method_bitmap_size_)) { 12713d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write method bitmap to " << out->GetLocation(); 1272ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return false; 1273ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1274ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom oat_writer->size_oat_class_method_bitmaps_ += method_bitmap_size_; 1275ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 12763d504075f7c1204d581923460754bf6d3714b13fIan Rogers if (!out->WriteFully(&method_offsets_[0], 1277cd60ac736bc7104785dc67671660d70fb434466fBrian Carlstrom sizeof(method_offsets_[0]) * method_offsets_.size())) { 12783d504075f7c1204d581923460754bf6d3714b13fIan Rogers PLOG(ERROR) << "Failed to write method offsets to " << out->GetLocation(); 1279e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 1280e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 12810aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao oat_writer->size_oat_class_method_offsets_ += sizeof(method_offsets_[0]) * method_offsets_.size(); 1282e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 1283e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1284e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1285e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} // namespace art 1286