Home | History | Annotate | Download | only in compiler
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "oat_writer.h"
     18 
     19 #include <zlib.h>
     20 
     21 #include "base/bit_vector.h"
     22 #include "base/stl_util.h"
     23 #include "base/unix_file/fd_file.h"
     24 #include "class_linker.h"
     25 #include "compiled_class.h"
     26 #include "dex_file-inl.h"
     27 #include "dex/verification_results.h"
     28 #include "gc/space/space.h"
     29 #include "mirror/art_method-inl.h"
     30 #include "mirror/array.h"
     31 #include "mirror/class_loader.h"
     32 #include "mirror/object-inl.h"
     33 #include "os.h"
     34 #include "output_stream.h"
     35 #include "safe_map.h"
     36 #include "scoped_thread_state_change.h"
     37 #include "handle_scope-inl.h"
     38 #include "verifier/method_verifier.h"
     39 
     40 namespace art {
     41 
     42 #define DCHECK_OFFSET() \
     43   DCHECK_EQ(static_cast<off_t>(file_offset + relative_offset), out->Seek(0, kSeekCurrent)) \
     44     << "file_offset=" << file_offset << " relative_offset=" << relative_offset
     45 
     46 #define DCHECK_OFFSET_() \
     47   DCHECK_EQ(static_cast<off_t>(file_offset + offset_), out->Seek(0, kSeekCurrent)) \
     48     << "file_offset=" << file_offset << " offset_=" << offset_
     49 
     50 OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
     51                      uint32_t image_file_location_oat_checksum,
     52                      uintptr_t image_file_location_oat_begin,
     53                      int32_t image_patch_delta,
     54                      const CompilerDriver* compiler,
     55                      TimingLogger* timings,
     56                      SafeMap<std::string, std::string>* key_value_store)
     57   : compiler_driver_(compiler),
     58     dex_files_(&dex_files),
     59     image_file_location_oat_checksum_(image_file_location_oat_checksum),
     60     image_file_location_oat_begin_(image_file_location_oat_begin),
     61     image_patch_delta_(image_patch_delta),
     62     key_value_store_(key_value_store),
     63     oat_header_(NULL),
     64     size_dex_file_alignment_(0),
     65     size_executable_offset_alignment_(0),
     66     size_oat_header_(0),
     67     size_oat_header_key_value_store_(0),
     68     size_dex_file_(0),
     69     size_interpreter_to_interpreter_bridge_(0),
     70     size_interpreter_to_compiled_code_bridge_(0),
     71     size_jni_dlsym_lookup_(0),
     72     size_portable_imt_conflict_trampoline_(0),
     73     size_portable_resolution_trampoline_(0),
     74     size_portable_to_interpreter_bridge_(0),
     75     size_quick_generic_jni_trampoline_(0),
     76     size_quick_imt_conflict_trampoline_(0),
     77     size_quick_resolution_trampoline_(0),
     78     size_quick_to_interpreter_bridge_(0),
     79     size_trampoline_alignment_(0),
     80     size_method_header_(0),
     81     size_code_(0),
     82     size_code_alignment_(0),
     83     size_mapping_table_(0),
     84     size_vmap_table_(0),
     85     size_gc_map_(0),
     86     size_oat_dex_file_location_size_(0),
     87     size_oat_dex_file_location_data_(0),
     88     size_oat_dex_file_location_checksum_(0),
     89     size_oat_dex_file_offset_(0),
     90     size_oat_dex_file_methods_offsets_(0),
     91     size_oat_class_type_(0),
     92     size_oat_class_status_(0),
     93     size_oat_class_method_bitmaps_(0),
     94     size_oat_class_method_offsets_(0) {
     95   CHECK(key_value_store != nullptr);
     96 
     97   size_t offset;
     98   {
     99     TimingLogger::ScopedTiming split("InitOatHeader", timings);
    100     offset = InitOatHeader();
    101   }
    102   {
    103     TimingLogger::ScopedTiming split("InitOatDexFiles", timings);
    104     offset = InitOatDexFiles(offset);
    105   }
    106   {
    107     TimingLogger::ScopedTiming split("InitDexFiles", timings);
    108     offset = InitDexFiles(offset);
    109   }
    110   {
    111     TimingLogger::ScopedTiming split("InitOatClasses", timings);
    112     offset = InitOatClasses(offset);
    113   }
    114   {
    115     TimingLogger::ScopedTiming split("InitOatMaps", timings);
    116     offset = InitOatMaps(offset);
    117   }
    118   {
    119     TimingLogger::ScopedTiming split("InitOatCode", timings);
    120     offset = InitOatCode(offset);
    121   }
    122   {
    123     TimingLogger::ScopedTiming split("InitOatCodeDexFiles", timings);
    124     offset = InitOatCodeDexFiles(offset);
    125   }
    126   size_ = offset;
    127 
    128   CHECK_EQ(dex_files_->size(), oat_dex_files_.size());
    129   CHECK_EQ(compiler->IsImage(),
    130            key_value_store_->find(OatHeader::kImageLocationKey) == key_value_store_->end());
    131   CHECK_ALIGNED(image_patch_delta_, kPageSize);
    132 }
    133 
    134 OatWriter::~OatWriter() {
    135   delete oat_header_;
    136   STLDeleteElements(&oat_dex_files_);
    137   STLDeleteElements(&oat_classes_);
    138 }
    139 
    140 struct OatWriter::GcMapDataAccess {
    141   static const SwapVector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
    142     return &compiled_method->GetGcMap();
    143   }
    144 
    145   static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE {
    146     uint32_t offset = oat_class->method_headers_[method_offsets_index].gc_map_offset_;
    147     return offset == 0u ? 0u :
    148         (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
    149   }
    150 
    151   static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset)
    152       ALWAYS_INLINE {
    153     oat_class->method_headers_[method_offsets_index].gc_map_offset_ =
    154         (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
    155   }
    156 
    157   static const char* Name() {
    158     return "GC map";
    159   }
    160 };
    161 
    162 struct OatWriter::MappingTableDataAccess {
    163   static const SwapVector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
    164     return &compiled_method->GetMappingTable();
    165   }
    166 
    167   static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE {
    168     uint32_t offset = oat_class->method_headers_[method_offsets_index].mapping_table_offset_;
    169     return offset == 0u ? 0u :
    170         (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
    171   }
    172 
    173   static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset)
    174       ALWAYS_INLINE {
    175     oat_class->method_headers_[method_offsets_index].mapping_table_offset_ =
    176         (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
    177   }
    178 
    179   static const char* Name() {
    180     return "mapping table";
    181   }
    182 };
    183 
    184 struct OatWriter::VmapTableDataAccess {
    185   static const SwapVector<uint8_t>* GetData(const CompiledMethod* compiled_method) ALWAYS_INLINE {
    186     return &compiled_method->GetVmapTable();
    187   }
    188 
    189   static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE {
    190     uint32_t offset = oat_class->method_headers_[method_offsets_index].vmap_table_offset_;
    191     return offset == 0u ? 0u :
    192         (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
    193   }
    194 
    195   static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset)
    196       ALWAYS_INLINE {
    197     oat_class->method_headers_[method_offsets_index].vmap_table_offset_ =
    198         (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
    199   }
    200 
    201   static const char* Name() {
    202     return "vmap table";
    203   }
    204 };
    205 
    206 class OatWriter::DexMethodVisitor {
    207  public:
    208   DexMethodVisitor(OatWriter* writer, size_t offset)
    209     : writer_(writer),
    210       offset_(offset),
    211       dex_file_(nullptr),
    212       class_def_index_(DexFile::kDexNoIndex) {
    213   }
    214 
    215   virtual bool StartClass(const DexFile* dex_file, size_t class_def_index) {
    216     DCHECK(dex_file_ == nullptr);
    217     DCHECK_EQ(class_def_index_, DexFile::kDexNoIndex);
    218     dex_file_ = dex_file;
    219     class_def_index_ = class_def_index;
    220     return true;
    221   }
    222 
    223   virtual bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) = 0;
    224 
    225   virtual bool EndClass() {
    226     if (kIsDebugBuild) {
    227       dex_file_ = nullptr;
    228       class_def_index_ = DexFile::kDexNoIndex;
    229     }
    230     return true;
    231   }
    232 
    233   size_t GetOffset() const {
    234     return offset_;
    235   }
    236 
    237  protected:
    238   virtual ~DexMethodVisitor() { }
    239 
    240   OatWriter* const writer_;
    241 
    242   // The offset is usually advanced for each visited method by the derived class.
    243   size_t offset_;
    244 
    245   // The dex file and class def index are set in StartClass().
    246   const DexFile* dex_file_;
    247   size_t class_def_index_;
    248 };
    249 
    250 class OatWriter::OatDexMethodVisitor : public DexMethodVisitor {
    251  public:
    252   OatDexMethodVisitor(OatWriter* writer, size_t offset)
    253     : DexMethodVisitor(writer, offset),
    254       oat_class_index_(0u),
    255       method_offsets_index_(0u) {
    256   }
    257 
    258   bool StartClass(const DexFile* dex_file, size_t class_def_index) {
    259     DexMethodVisitor::StartClass(dex_file, class_def_index);
    260     DCHECK_LT(oat_class_index_, writer_->oat_classes_.size());
    261     method_offsets_index_ = 0u;
    262     return true;
    263   }
    264 
    265   bool EndClass() {
    266     ++oat_class_index_;
    267     return DexMethodVisitor::EndClass();
    268   }
    269 
    270  protected:
    271   size_t oat_class_index_;
    272   size_t method_offsets_index_;
    273 };
    274 
    275 class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor {
    276  public:
    277   InitOatClassesMethodVisitor(OatWriter* writer, size_t offset)
    278     : DexMethodVisitor(writer, offset),
    279       compiled_methods_(),
    280       num_non_null_compiled_methods_(0u) {
    281     compiled_methods_.reserve(256u);
    282   }
    283 
    284   bool StartClass(const DexFile* dex_file, size_t class_def_index) {
    285     DexMethodVisitor::StartClass(dex_file, class_def_index);
    286     compiled_methods_.clear();
    287     num_non_null_compiled_methods_ = 0u;
    288     return true;
    289   }
    290 
    291   bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) {
    292     // Fill in the compiled_methods_ array for methods that have a
    293     // CompiledMethod. We track the number of non-null entries in
    294     // num_non_null_compiled_methods_ since we only want to allocate
    295     // OatMethodOffsets for the compiled methods.
    296     uint32_t method_idx = it.GetMemberIndex();
    297     CompiledMethod* compiled_method =
    298         writer_->compiler_driver_->GetCompiledMethod(MethodReference(dex_file_, method_idx));
    299     compiled_methods_.push_back(compiled_method);
    300     if (compiled_method != nullptr) {
    301         ++num_non_null_compiled_methods_;
    302     }
    303     return true;
    304   }
    305 
    306   bool EndClass() {
    307     ClassReference class_ref(dex_file_, class_def_index_);
    308     CompiledClass* compiled_class = writer_->compiler_driver_->GetCompiledClass(class_ref);
    309     mirror::Class::Status status;
    310     if (compiled_class != NULL) {
    311       status = compiled_class->GetStatus();
    312     } else if (writer_->compiler_driver_->GetVerificationResults()->IsClassRejected(class_ref)) {
    313       status = mirror::Class::kStatusError;
    314     } else {
    315       status = mirror::Class::kStatusNotReady;
    316     }
    317 
    318     OatClass* oat_class = new OatClass(offset_, compiled_methods_,
    319                                        num_non_null_compiled_methods_, status);
    320     writer_->oat_classes_.push_back(oat_class);
    321     offset_ += oat_class->SizeOf();
    322     return DexMethodVisitor::EndClass();
    323   }
    324 
    325  private:
    326   std::vector<CompiledMethod*> compiled_methods_;
    327   size_t num_non_null_compiled_methods_;
    328 };
    329 
    330 class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
    331  public:
    332   InitCodeMethodVisitor(OatWriter* writer, size_t offset)
    333     : OatDexMethodVisitor(writer, offset) {
    334   }
    335 
    336   bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it)
    337       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    338     OatClass* oat_class = writer_->oat_classes_[oat_class_index_];
    339     CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
    340 
    341     if (compiled_method != nullptr) {
    342       // Derived from CompiledMethod.
    343       uint32_t quick_code_offset = 0;
    344 
    345       const SwapVector<uint8_t>* portable_code = compiled_method->GetPortableCode();
    346       const SwapVector<uint8_t>* quick_code = compiled_method->GetQuickCode();
    347       if (portable_code != nullptr) {
    348         CHECK(quick_code == nullptr);
    349         size_t oat_method_offsets_offset =
    350             oat_class->GetOatMethodOffsetsOffsetFromOatHeader(class_def_method_index);
    351         compiled_method->AddOatdataOffsetToCompliledCodeOffset(
    352             oat_method_offsets_offset + OFFSETOF_MEMBER(OatMethodOffsets, code_offset_));
    353       } else {
    354         CHECK(quick_code != nullptr);
    355         offset_ = compiled_method->AlignCode(offset_);
    356         DCHECK_ALIGNED_PARAM(offset_,
    357                              GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
    358         uint32_t code_size = quick_code->size() * sizeof(uint8_t);
    359         CHECK_NE(code_size, 0U);
    360         uint32_t thumb_offset = compiled_method->CodeDelta();
    361         quick_code_offset = offset_ + sizeof(OatQuickMethodHeader) + thumb_offset;
    362 
    363         bool force_debug_capture = false;
    364         bool deduped = false;
    365 
    366         // Deduplicate code arrays.
    367         auto lb = dedupe_map_.lower_bound(compiled_method);
    368         if (lb != dedupe_map_.end() && !dedupe_map_.key_comp()(compiled_method, lb->first)) {
    369           quick_code_offset = lb->second;
    370           deduped = true;
    371         } else {
    372           dedupe_map_.PutBefore(lb, compiled_method, quick_code_offset);
    373         }
    374 
    375         // Update quick method header.
    376         DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size());
    377         OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_];
    378         uint32_t mapping_table_offset = method_header->mapping_table_offset_;
    379         uint32_t vmap_table_offset = method_header->vmap_table_offset_;
    380         uint32_t gc_map_offset = method_header->gc_map_offset_;
    381         // The code offset was 0 when the mapping/vmap table offset was set, so it's set
    382         // to 0-offset and we need to adjust it by code_offset.
    383         uint32_t code_offset = quick_code_offset - thumb_offset;
    384         if (mapping_table_offset != 0u) {
    385           mapping_table_offset += code_offset;
    386           DCHECK_LT(mapping_table_offset, code_offset);
    387         }
    388         if (vmap_table_offset != 0u) {
    389           vmap_table_offset += code_offset;
    390           DCHECK_LT(vmap_table_offset, code_offset);
    391         }
    392         if (gc_map_offset != 0u) {
    393           gc_map_offset += code_offset;
    394           DCHECK_LT(gc_map_offset, code_offset);
    395         }
    396         uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
    397         uint32_t core_spill_mask = compiled_method->GetCoreSpillMask();
    398         uint32_t fp_spill_mask = compiled_method->GetFpSpillMask();
    399         *method_header = OatQuickMethodHeader(mapping_table_offset, vmap_table_offset,
    400                                               gc_map_offset, frame_size_in_bytes, core_spill_mask,
    401                                               fp_spill_mask, code_size);
    402 
    403         // Update checksum if this wasn't a duplicate.
    404         if (!deduped) {
    405           writer_->oat_header_->UpdateChecksum(method_header, sizeof(*method_header));
    406           offset_ += sizeof(*method_header);  // Method header is prepended before code.
    407           writer_->oat_header_->UpdateChecksum(&(*quick_code)[0], code_size);
    408           offset_ += code_size;
    409         }
    410 
    411         uint32_t quick_code_start = quick_code_offset - writer_->oat_header_->GetExecutableOffset();
    412         std::vector<uint8_t>* cfi_info = writer_->compiler_driver_->GetCallFrameInformation();
    413         if (cfi_info != nullptr) {
    414           // Copy in the FDE, if present
    415           const SwapVector<uint8_t>* fde = compiled_method->GetCFIInfo();
    416           if (fde != nullptr) {
    417             // Copy the information into cfi_info and then fix the address in the new copy.
    418             int cur_offset = cfi_info->size();
    419             cfi_info->insert(cfi_info->end(), fde->begin(), fde->end());
    420 
    421             // Set the 'CIE_pointer' field to cur_offset+4.
    422             uint32_t CIE_pointer = cur_offset + 4;
    423             uint32_t offset_to_update = cur_offset + sizeof(uint32_t);
    424             (*cfi_info)[offset_to_update+0] = CIE_pointer;
    425             (*cfi_info)[offset_to_update+1] = CIE_pointer >> 8;
    426             (*cfi_info)[offset_to_update+2] = CIE_pointer >> 16;
    427             (*cfi_info)[offset_to_update+3] = CIE_pointer >> 24;
    428 
    429             // Set the 'initial_location' field to address the start of the method.
    430             offset_to_update = cur_offset + 2*sizeof(uint32_t);
    431             (*cfi_info)[offset_to_update+0] = quick_code_start;
    432             (*cfi_info)[offset_to_update+1] = quick_code_start >> 8;
    433             (*cfi_info)[offset_to_update+2] = quick_code_start >> 16;
    434             (*cfi_info)[offset_to_update+3] = quick_code_start >> 24;
    435             force_debug_capture = true;
    436           }
    437         }
    438 
    439 
    440         if (writer_->compiler_driver_->DidIncludeDebugSymbols() || force_debug_capture) {
    441           // Record debug information for this function if we are doing that or
    442           // we have CFI and so need it.
    443           std::string name = PrettyMethod(it.GetMemberIndex(), *dex_file_, true);
    444           if (deduped) {
    445             // TODO We should place the DEDUPED tag on the first instance of a
    446             // deduplicated symbol so that it will show up in a debuggerd crash
    447             // report.
    448             name += " [ DEDUPED ]";
    449           }
    450           writer_->method_info_.push_back(DebugInfo(name, quick_code_start,
    451                                                     quick_code_start + code_size));
    452         }
    453       }
    454 
    455       if (kIsDebugBuild) {
    456         // We expect GC maps except when the class hasn't been verified or the method is native.
    457         const CompilerDriver* compiler_driver = writer_->compiler_driver_;
    458         ClassReference class_ref(dex_file_, class_def_index_);
    459         CompiledClass* compiled_class = compiler_driver->GetCompiledClass(class_ref);
    460         mirror::Class::Status status;
    461         if (compiled_class != NULL) {
    462           status = compiled_class->GetStatus();
    463         } else if (compiler_driver->GetVerificationResults()->IsClassRejected(class_ref)) {
    464           status = mirror::Class::kStatusError;
    465         } else {
    466           status = mirror::Class::kStatusNotReady;
    467         }
    468         const SwapVector<uint8_t>& gc_map = compiled_method->GetGcMap();
    469         size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
    470         bool is_native = it.MemberIsNative();
    471         CHECK(gc_map_size != 0 || is_native || status < mirror::Class::kStatusVerified)
    472             << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " "
    473             << (status < mirror::Class::kStatusVerified) << " " << status << " "
    474             << PrettyMethod(it.GetMemberIndex(), *dex_file_);
    475       }
    476 
    477       DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
    478       OatMethodOffsets* offsets = &oat_class->method_offsets_[method_offsets_index_];
    479       offsets->code_offset_ = quick_code_offset;
    480       ++method_offsets_index_;
    481     }
    482 
    483     return true;
    484   }
    485 
    486  private:
    487   // Deduplication is already done on a pointer basis by the compiler driver,
    488   // so we can simply compare the pointers to find out if things are duplicated.
    489   SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_;
    490 };
    491 
    492 template <typename DataAccess>
    493 class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor {
    494  public:
    495   InitMapMethodVisitor(OatWriter* writer, size_t offset)
    496     : OatDexMethodVisitor(writer, offset) {
    497   }
    498 
    499   bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it)
    500       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    501     OatClass* oat_class = writer_->oat_classes_[oat_class_index_];
    502     CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
    503 
    504     if (compiled_method != nullptr) {
    505       DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
    506       DCHECK_EQ(DataAccess::GetOffset(oat_class, method_offsets_index_), 0u);
    507 
    508       const SwapVector<uint8_t>* map = DataAccess::GetData(compiled_method);
    509       uint32_t map_size = map->size() * sizeof((*map)[0]);
    510       if (map_size != 0u) {
    511         auto lb = dedupe_map_.lower_bound(map);
    512         if (lb != dedupe_map_.end() && !dedupe_map_.key_comp()(map, lb->first)) {
    513           DataAccess::SetOffset(oat_class, method_offsets_index_, lb->second);
    514         } else {
    515           DataAccess::SetOffset(oat_class, method_offsets_index_, offset_);
    516           dedupe_map_.PutBefore(lb, map, offset_);
    517           offset_ += map_size;
    518           writer_->oat_header_->UpdateChecksum(&(*map)[0], map_size);
    519         }
    520       }
    521       ++method_offsets_index_;
    522     }
    523 
    524     return true;
    525   }
    526 
    527  private:
    528   // Deduplication is already done on a pointer basis by the compiler driver,
    529   // so we can simply compare the pointers to find out if things are duplicated.
    530   SafeMap<const SwapVector<uint8_t>*, uint32_t> dedupe_map_;
    531 };
    532 
    533 class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor {
    534  public:
    535   InitImageMethodVisitor(OatWriter* writer, size_t offset)
    536     : OatDexMethodVisitor(writer, offset) {
    537   }
    538 
    539   bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it)
    540       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    541     OatClass* oat_class = writer_->oat_classes_[oat_class_index_];
    542     CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
    543 
    544     OatMethodOffsets offsets(0u);
    545     if (compiled_method != nullptr) {
    546       DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
    547       offsets = oat_class->method_offsets_[method_offsets_index_];
    548       ++method_offsets_index_;
    549     }
    550 
    551     ClassLinker* linker = Runtime::Current()->GetClassLinker();
    552     InvokeType invoke_type = it.GetMethodInvokeType(dex_file_->GetClassDef(class_def_index_));
    553     // Unchecked as we hold mutator_lock_ on entry.
    554     ScopedObjectAccessUnchecked soa(Thread::Current());
    555     StackHandleScope<1> hs(soa.Self());
    556     Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(*dex_file_)));
    557     mirror::ArtMethod* method = linker->ResolveMethod(*dex_file_, it.GetMemberIndex(), dex_cache,
    558                                                       NullHandle<mirror::ClassLoader>(),
    559                                                       NullHandle<mirror::ArtMethod>(),
    560                                                       invoke_type);
    561     CHECK(method != NULL) << PrettyMethod(it.GetMemberIndex(), *dex_file_, true);
    562     // Portable code offsets are set by ElfWriterMclinker::FixupCompiledCodeOffset after linking.
    563     method->SetQuickOatCodeOffset(offsets.code_offset_);
    564 
    565     return true;
    566   }
    567 };
    568 
    569 class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
    570  public:
    571   WriteCodeMethodVisitor(OatWriter* writer, OutputStream* out, const size_t file_offset,
    572                              size_t relative_offset)
    573     : OatDexMethodVisitor(writer, relative_offset),
    574       out_(out),
    575       file_offset_(file_offset) {
    576   }
    577 
    578   bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) {
    579     OatClass* oat_class = writer_->oat_classes_[oat_class_index_];
    580     const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
    581 
    582     if (compiled_method != NULL) {  // ie. not an abstract method
    583       size_t file_offset = file_offset_;
    584       OutputStream* out = out_;
    585 
    586       const SwapVector<uint8_t>* quick_code = compiled_method->GetQuickCode();
    587       if (quick_code != nullptr) {
    588         CHECK(compiled_method->GetPortableCode() == nullptr);
    589         uint32_t aligned_offset = compiled_method->AlignCode(offset_);
    590         uint32_t aligned_code_delta = aligned_offset - offset_;
    591         if (aligned_code_delta != 0) {
    592           static const uint8_t kPadding[] = {
    593               0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u
    594           };
    595           DCHECK_LE(aligned_code_delta, sizeof(kPadding));
    596           if (UNLIKELY(!out->WriteFully(kPadding, aligned_code_delta))) {
    597             ReportWriteFailure("code alignment padding", it);
    598             return false;
    599           }
    600           writer_->size_code_alignment_ += aligned_code_delta;
    601           offset_ += aligned_code_delta;
    602           DCHECK_OFFSET_();
    603         }
    604         DCHECK_ALIGNED_PARAM(offset_,
    605                              GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
    606         uint32_t code_size = quick_code->size() * sizeof(uint8_t);
    607         CHECK_NE(code_size, 0U);
    608 
    609         // Deduplicate code arrays.
    610         const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index_];
    611         DCHECK(method_offsets.code_offset_ < offset_ || method_offsets.code_offset_ ==
    612                    offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta())
    613             << PrettyMethod(it.GetMemberIndex(), *dex_file_);
    614         if (method_offsets.code_offset_ >= offset_) {
    615           const OatQuickMethodHeader& method_header =
    616               oat_class->method_headers_[method_offsets_index_];
    617           if (!out->WriteFully(&method_header, sizeof(method_header))) {
    618             ReportWriteFailure("method header", it);
    619             return false;
    620           }
    621           writer_->size_method_header_ += sizeof(method_header);
    622           offset_ += sizeof(method_header);
    623           DCHECK_OFFSET_();
    624           if (!out->WriteFully(&(*quick_code)[0], code_size)) {
    625             ReportWriteFailure("method code", it);
    626             return false;
    627           }
    628           writer_->size_code_ += code_size;
    629           offset_ += code_size;
    630         }
    631         DCHECK_OFFSET_();
    632       }
    633       ++method_offsets_index_;
    634     }
    635 
    636     return true;
    637   }
    638 
    639  private:
    640   OutputStream* const out_;
    641   size_t const file_offset_;
    642 
    643   void ReportWriteFailure(const char* what, const ClassDataItemIterator& it) {
    644     PLOG(ERROR) << "Failed to write " << what << " for "
    645         << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " to " << out_->GetLocation();
    646   }
    647 };
    648 
    649 template <typename DataAccess>
    650 class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor {
    651  public:
    652   WriteMapMethodVisitor(OatWriter* writer, OutputStream* out, const size_t file_offset,
    653                         size_t relative_offset)
    654     : OatDexMethodVisitor(writer, relative_offset),
    655       out_(out),
    656       file_offset_(file_offset) {
    657   }
    658 
    659   bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) {
    660     OatClass* oat_class = writer_->oat_classes_[oat_class_index_];
    661     const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
    662 
    663     if (compiled_method != NULL) {  // ie. not an abstract method
    664       size_t file_offset = file_offset_;
    665       OutputStream* out = out_;
    666 
    667       uint32_t map_offset = DataAccess::GetOffset(oat_class, method_offsets_index_);
    668       ++method_offsets_index_;
    669 
    670       // Write deduplicated map.
    671       const SwapVector<uint8_t>* map = DataAccess::GetData(compiled_method);
    672       size_t map_size = map->size() * sizeof((*map)[0]);
    673       DCHECK((map_size == 0u && map_offset == 0u) ||
    674             (map_size != 0u && map_offset != 0u && map_offset <= offset_))
    675           << map_size << " " << map_offset << " " << offset_ << " "
    676           << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " for " << DataAccess::Name();
    677       if (map_size != 0u && map_offset == offset_) {
    678         if (UNLIKELY(!out->WriteFully(&(*map)[0], map_size))) {
    679           ReportWriteFailure(it);
    680           return false;
    681         }
    682         offset_ += map_size;
    683       }
    684       DCHECK_OFFSET_();
    685     }
    686 
    687     return true;
    688   }
    689 
    690  private:
    691   OutputStream* const out_;
    692   size_t const file_offset_;
    693 
    694   void ReportWriteFailure(const ClassDataItemIterator& it) {
    695     PLOG(ERROR) << "Failed to write " << DataAccess::Name() << " for "
    696         << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " to " << out_->GetLocation();
    697   }
    698 };
    699 
    700 // Visit all methods from all classes in all dex files with the specified visitor.
    701 bool OatWriter::VisitDexMethods(DexMethodVisitor* visitor) {
    702   for (const DexFile* dex_file : *dex_files_) {
    703     const size_t class_def_count = dex_file->NumClassDefs();
    704     for (size_t class_def_index = 0; class_def_index != class_def_count; ++class_def_index) {
    705       if (UNLIKELY(!visitor->StartClass(dex_file, class_def_index))) {
    706         return false;
    707       }
    708       const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
    709       const byte* class_data = dex_file->GetClassData(class_def);
    710       if (class_data != NULL) {  // ie not an empty class, such as a marker interface
    711         ClassDataItemIterator it(*dex_file, class_data);
    712         while (it.HasNextStaticField()) {
    713           it.Next();
    714         }
    715         while (it.HasNextInstanceField()) {
    716           it.Next();
    717         }
    718         size_t class_def_method_index = 0u;
    719         while (it.HasNextDirectMethod()) {
    720           if (!visitor->VisitMethod(class_def_method_index, it)) {
    721             return false;
    722           }
    723           ++class_def_method_index;
    724           it.Next();
    725         }
    726         while (it.HasNextVirtualMethod()) {
    727           if (UNLIKELY(!visitor->VisitMethod(class_def_method_index, it))) {
    728             return false;
    729           }
    730           ++class_def_method_index;
    731           it.Next();
    732         }
    733       }
    734       if (UNLIKELY(!visitor->EndClass())) {
    735         return false;
    736       }
    737     }
    738   }
    739   return true;
    740 }
    741 
    742 size_t OatWriter::InitOatHeader() {
    743   oat_header_ = OatHeader::Create(compiler_driver_->GetInstructionSet(),
    744                                   compiler_driver_->GetInstructionSetFeatures(),
    745                                   dex_files_,
    746                                   image_file_location_oat_checksum_,
    747                                   image_file_location_oat_begin_,
    748                                   key_value_store_);
    749 
    750   return oat_header_->GetHeaderSize();
    751 }
    752 
    753 size_t OatWriter::InitOatDexFiles(size_t offset) {
    754   // create the OatDexFiles
    755   for (size_t i = 0; i != dex_files_->size(); ++i) {
    756     const DexFile* dex_file = (*dex_files_)[i];
    757     CHECK(dex_file != NULL);
    758     OatDexFile* oat_dex_file = new OatDexFile(offset, *dex_file);
    759     oat_dex_files_.push_back(oat_dex_file);
    760     offset += oat_dex_file->SizeOf();
    761   }
    762   return offset;
    763 }
    764 
    765 size_t OatWriter::InitDexFiles(size_t offset) {
    766   // calculate the offsets within OatDexFiles to the DexFiles
    767   for (size_t i = 0; i != dex_files_->size(); ++i) {
    768     // dex files are required to be 4 byte aligned
    769     size_t original_offset = offset;
    770     offset = RoundUp(offset, 4);
    771     size_dex_file_alignment_ += offset - original_offset;
    772 
    773     // set offset in OatDexFile to DexFile
    774     oat_dex_files_[i]->dex_file_offset_ = offset;
    775 
    776     const DexFile* dex_file = (*dex_files_)[i];
    777     offset += dex_file->GetHeader().file_size_;
    778   }
    779   return offset;
    780 }
    781 
    782 size_t OatWriter::InitOatClasses(size_t offset) {
    783   // calculate the offsets within OatDexFiles to OatClasses
    784   InitOatClassesMethodVisitor visitor(this, offset);
    785   bool success = VisitDexMethods(&visitor);
    786   CHECK(success);
    787   offset = visitor.GetOffset();
    788 
    789   // Update oat_dex_files_.
    790   auto oat_class_it = oat_classes_.begin();
    791   for (OatDexFile* oat_dex_file : oat_dex_files_) {
    792     for (uint32_t& offset : oat_dex_file->methods_offsets_) {
    793       DCHECK(oat_class_it != oat_classes_.end());
    794       offset = (*oat_class_it)->offset_;
    795       ++oat_class_it;
    796     }
    797     oat_dex_file->UpdateChecksum(oat_header_);
    798   }
    799   CHECK(oat_class_it == oat_classes_.end());
    800 
    801   return offset;
    802 }
    803 
    804 size_t OatWriter::InitOatMaps(size_t offset) {
    805   #define VISIT(VisitorType)                          \
    806     do {                                              \
    807       VisitorType visitor(this, offset);              \
    808       bool success = VisitDexMethods(&visitor);       \
    809       DCHECK(success);                                \
    810       offset = visitor.GetOffset();                   \
    811     } while (false)
    812 
    813   VISIT(InitMapMethodVisitor<GcMapDataAccess>);
    814   VISIT(InitMapMethodVisitor<MappingTableDataAccess>);
    815   VISIT(InitMapMethodVisitor<VmapTableDataAccess>);
    816 
    817   #undef VISIT
    818 
    819   return offset;
    820 }
    821 
    822 size_t OatWriter::InitOatCode(size_t offset) {
    823   // calculate the offsets within OatHeader to executable code
    824   size_t old_offset = offset;
    825   size_t adjusted_offset = offset;
    826   // required to be on a new page boundary
    827   offset = RoundUp(offset, kPageSize);
    828   oat_header_->SetExecutableOffset(offset);
    829   size_executable_offset_alignment_ = offset - old_offset;
    830   if (compiler_driver_->IsImage()) {
    831     CHECK_EQ(image_patch_delta_, 0);
    832     InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
    833 
    834     #define DO_TRAMPOLINE(field, fn_name) \
    835       offset = CompiledCode::AlignCode(offset, instruction_set); \
    836       adjusted_offset = offset + CompiledCode::CodeDelta(instruction_set); \
    837       oat_header_->Set ## fn_name ## Offset(adjusted_offset); \
    838       field.reset(compiler_driver_->Create ## fn_name()); \
    839       offset += field->size();
    840 
    841     DO_TRAMPOLINE(interpreter_to_interpreter_bridge_, InterpreterToInterpreterBridge);
    842     DO_TRAMPOLINE(interpreter_to_compiled_code_bridge_, InterpreterToCompiledCodeBridge);
    843     DO_TRAMPOLINE(jni_dlsym_lookup_, JniDlsymLookup);
    844     DO_TRAMPOLINE(portable_imt_conflict_trampoline_, PortableImtConflictTrampoline);
    845     DO_TRAMPOLINE(portable_resolution_trampoline_, PortableResolutionTrampoline);
    846     DO_TRAMPOLINE(portable_to_interpreter_bridge_, PortableToInterpreterBridge);
    847     DO_TRAMPOLINE(quick_generic_jni_trampoline_, QuickGenericJniTrampoline);
    848     DO_TRAMPOLINE(quick_imt_conflict_trampoline_, QuickImtConflictTrampoline);
    849     DO_TRAMPOLINE(quick_resolution_trampoline_, QuickResolutionTrampoline);
    850     DO_TRAMPOLINE(quick_to_interpreter_bridge_, QuickToInterpreterBridge);
    851 
    852     #undef DO_TRAMPOLINE
    853   } else {
    854     oat_header_->SetInterpreterToInterpreterBridgeOffset(0);
    855     oat_header_->SetInterpreterToCompiledCodeBridgeOffset(0);
    856     oat_header_->SetJniDlsymLookupOffset(0);
    857     oat_header_->SetPortableImtConflictTrampolineOffset(0);
    858     oat_header_->SetPortableResolutionTrampolineOffset(0);
    859     oat_header_->SetPortableToInterpreterBridgeOffset(0);
    860     oat_header_->SetQuickGenericJniTrampolineOffset(0);
    861     oat_header_->SetQuickImtConflictTrampolineOffset(0);
    862     oat_header_->SetQuickResolutionTrampolineOffset(0);
    863     oat_header_->SetQuickToInterpreterBridgeOffset(0);
    864     oat_header_->SetImagePatchDelta(image_patch_delta_);
    865   }
    866   return offset;
    867 }
    868 
    869 size_t OatWriter::InitOatCodeDexFiles(size_t offset) {
    870   #define VISIT(VisitorType)                          \
    871     do {                                              \
    872       VisitorType visitor(this, offset);              \
    873       bool success = VisitDexMethods(&visitor);       \
    874       DCHECK(success);                                \
    875       offset = visitor.GetOffset();                   \
    876     } while (false)
    877 
    878   VISIT(InitCodeMethodVisitor);
    879   if (compiler_driver_->IsImage()) {
    880     VISIT(InitImageMethodVisitor);
    881   }
    882 
    883   #undef VISIT
    884 
    885   return offset;
    886 }
    887 
    888 bool OatWriter::Write(OutputStream* out) {
    889   const size_t file_offset = out->Seek(0, kSeekCurrent);
    890 
    891   size_t header_size = oat_header_->GetHeaderSize();
    892   if (!out->WriteFully(oat_header_, header_size)) {
    893     PLOG(ERROR) << "Failed to write oat header to " << out->GetLocation();
    894     return false;
    895   }
    896   size_oat_header_ += sizeof(OatHeader);
    897   size_oat_header_key_value_store_ += oat_header_->GetHeaderSize() - sizeof(OatHeader);
    898 
    899   if (!WriteTables(out, file_offset)) {
    900     LOG(ERROR) << "Failed to write oat tables to " << out->GetLocation();
    901     return false;
    902   }
    903 
    904   size_t relative_offset = out->Seek(0, kSeekCurrent) - file_offset;
    905   relative_offset = WriteMaps(out, file_offset, relative_offset);
    906   if (relative_offset == 0) {
    907     LOG(ERROR) << "Failed to write oat code to " << out->GetLocation();
    908     return false;
    909   }
    910 
    911   relative_offset = WriteCode(out, file_offset, relative_offset);
    912   if (relative_offset == 0) {
    913     LOG(ERROR) << "Failed to write oat code to " << out->GetLocation();
    914     return false;
    915   }
    916 
    917   relative_offset = WriteCodeDexFiles(out, file_offset, relative_offset);
    918   if (relative_offset == 0) {
    919     LOG(ERROR) << "Failed to write oat code for dex files to " << out->GetLocation();
    920     return false;
    921   }
    922 
    923   if (kIsDebugBuild) {
    924     uint32_t size_total = 0;
    925     #define DO_STAT(x) \
    926       VLOG(compiler) << #x "=" << PrettySize(x) << " (" << x << "B)"; \
    927       size_total += x;
    928 
    929     DO_STAT(size_dex_file_alignment_);
    930     DO_STAT(size_executable_offset_alignment_);
    931     DO_STAT(size_oat_header_);
    932     DO_STAT(size_oat_header_key_value_store_);
    933     DO_STAT(size_dex_file_);
    934     DO_STAT(size_interpreter_to_interpreter_bridge_);
    935     DO_STAT(size_interpreter_to_compiled_code_bridge_);
    936     DO_STAT(size_jni_dlsym_lookup_);
    937     DO_STAT(size_portable_imt_conflict_trampoline_);
    938     DO_STAT(size_portable_resolution_trampoline_);
    939     DO_STAT(size_portable_to_interpreter_bridge_);
    940     DO_STAT(size_quick_generic_jni_trampoline_);
    941     DO_STAT(size_quick_imt_conflict_trampoline_);
    942     DO_STAT(size_quick_resolution_trampoline_);
    943     DO_STAT(size_quick_to_interpreter_bridge_);
    944     DO_STAT(size_trampoline_alignment_);
    945     DO_STAT(size_method_header_);
    946     DO_STAT(size_code_);
    947     DO_STAT(size_code_alignment_);
    948     DO_STAT(size_mapping_table_);
    949     DO_STAT(size_vmap_table_);
    950     DO_STAT(size_gc_map_);
    951     DO_STAT(size_oat_dex_file_location_size_);
    952     DO_STAT(size_oat_dex_file_location_data_);
    953     DO_STAT(size_oat_dex_file_location_checksum_);
    954     DO_STAT(size_oat_dex_file_offset_);
    955     DO_STAT(size_oat_dex_file_methods_offsets_);
    956     DO_STAT(size_oat_class_type_);
    957     DO_STAT(size_oat_class_status_);
    958     DO_STAT(size_oat_class_method_bitmaps_);
    959     DO_STAT(size_oat_class_method_offsets_);
    960     #undef DO_STAT
    961 
    962     VLOG(compiler) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)"; \
    963     CHECK_EQ(file_offset + size_total, static_cast<uint32_t>(out->Seek(0, kSeekCurrent)));
    964     CHECK_EQ(size_, size_total);
    965   }
    966 
    967   CHECK_EQ(file_offset + size_, static_cast<uint32_t>(out->Seek(0, kSeekCurrent)));
    968   CHECK_EQ(size_, relative_offset);
    969 
    970   return true;
    971 }
    972 
    973 bool OatWriter::WriteTables(OutputStream* out, const size_t file_offset) {
    974   for (size_t i = 0; i != oat_dex_files_.size(); ++i) {
    975     if (!oat_dex_files_[i]->Write(this, out, file_offset)) {
    976       PLOG(ERROR) << "Failed to write oat dex information to " << out->GetLocation();
    977       return false;
    978     }
    979   }
    980   for (size_t i = 0; i != oat_dex_files_.size(); ++i) {
    981     uint32_t expected_offset = file_offset + oat_dex_files_[i]->dex_file_offset_;
    982     off_t actual_offset = out->Seek(expected_offset, kSeekSet);
    983     if (static_cast<uint32_t>(actual_offset) != expected_offset) {
    984       const DexFile* dex_file = (*dex_files_)[i];
    985       PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset
    986                   << " Expected: " << expected_offset << " File: " << dex_file->GetLocation();
    987       return false;
    988     }
    989     const DexFile* dex_file = (*dex_files_)[i];
    990     if (!out->WriteFully(&dex_file->GetHeader(), dex_file->GetHeader().file_size_)) {
    991       PLOG(ERROR) << "Failed to write dex file " << dex_file->GetLocation()
    992                   << " to " << out->GetLocation();
    993       return false;
    994     }
    995     size_dex_file_ += dex_file->GetHeader().file_size_;
    996   }
    997   for (size_t i = 0; i != oat_classes_.size(); ++i) {
    998     if (!oat_classes_[i]->Write(this, out, file_offset)) {
    999       PLOG(ERROR) << "Failed to write oat methods information to " << out->GetLocation();
   1000       return false;
   1001     }
   1002   }
   1003   return true;
   1004 }
   1005 
   1006 size_t OatWriter::WriteMaps(OutputStream* out, const size_t file_offset, size_t relative_offset) {
   1007   #define VISIT(VisitorType)                                              \
   1008     do {                                                                  \
   1009       VisitorType visitor(this, out, file_offset, relative_offset);       \
   1010       if (UNLIKELY(!VisitDexMethods(&visitor))) {                         \
   1011         return 0;                                                         \
   1012       }                                                                   \
   1013       relative_offset = visitor.GetOffset();                              \
   1014     } while (false)
   1015 
   1016   size_t gc_maps_offset = relative_offset;
   1017   VISIT(WriteMapMethodVisitor<GcMapDataAccess>);
   1018   size_gc_map_ = relative_offset - gc_maps_offset;
   1019 
   1020   size_t mapping_tables_offset = relative_offset;
   1021   VISIT(WriteMapMethodVisitor<MappingTableDataAccess>);
   1022   size_mapping_table_ = relative_offset - mapping_tables_offset;
   1023 
   1024   size_t vmap_tables_offset = relative_offset;
   1025   VISIT(WriteMapMethodVisitor<VmapTableDataAccess>);
   1026   size_vmap_table_ = relative_offset - vmap_tables_offset;
   1027 
   1028   #undef VISIT
   1029 
   1030   return relative_offset;
   1031 }
   1032 
   1033 size_t OatWriter::WriteCode(OutputStream* out, const size_t file_offset, size_t relative_offset) {
   1034   off_t new_offset = out->Seek(size_executable_offset_alignment_, kSeekCurrent);
   1035   relative_offset += size_executable_offset_alignment_;
   1036   DCHECK_EQ(relative_offset, oat_header_->GetExecutableOffset());
   1037   size_t expected_file_offset = file_offset + relative_offset;
   1038   if (static_cast<uint32_t>(new_offset) != expected_file_offset) {
   1039     PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset
   1040                 << " Expected: " << expected_file_offset << " File: " << out->GetLocation();
   1041     return 0;
   1042   }
   1043   DCHECK_OFFSET();
   1044   if (compiler_driver_->IsImage()) {
   1045     InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
   1046 
   1047     #define DO_TRAMPOLINE(field) \
   1048       do { \
   1049         uint32_t aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set); \
   1050         uint32_t alignment_padding = aligned_offset - relative_offset; \
   1051         out->Seek(alignment_padding, kSeekCurrent); \
   1052         size_trampoline_alignment_ += alignment_padding; \
   1053         if (!out->WriteFully(&(*field)[0], field->size())) { \
   1054           PLOG(ERROR) << "Failed to write " # field " to " << out->GetLocation(); \
   1055           return false; \
   1056         } \
   1057         size_ ## field += field->size(); \
   1058         relative_offset += alignment_padding + field->size(); \
   1059         DCHECK_OFFSET(); \
   1060       } while (false)
   1061 
   1062     DO_TRAMPOLINE(interpreter_to_interpreter_bridge_);
   1063     DO_TRAMPOLINE(interpreter_to_compiled_code_bridge_);
   1064     DO_TRAMPOLINE(jni_dlsym_lookup_);
   1065     DO_TRAMPOLINE(portable_imt_conflict_trampoline_);
   1066     DO_TRAMPOLINE(portable_resolution_trampoline_);
   1067     DO_TRAMPOLINE(portable_to_interpreter_bridge_);
   1068     DO_TRAMPOLINE(quick_generic_jni_trampoline_);
   1069     DO_TRAMPOLINE(quick_imt_conflict_trampoline_);
   1070     DO_TRAMPOLINE(quick_resolution_trampoline_);
   1071     DO_TRAMPOLINE(quick_to_interpreter_bridge_);
   1072     #undef DO_TRAMPOLINE
   1073   }
   1074   return relative_offset;
   1075 }
   1076 
   1077 size_t OatWriter::WriteCodeDexFiles(OutputStream* out,
   1078                                     const size_t file_offset,
   1079                                     size_t relative_offset) {
   1080   #define VISIT(VisitorType)                                              \
   1081     do {                                                                  \
   1082       VisitorType visitor(this, out, file_offset, relative_offset);       \
   1083       if (UNLIKELY(!VisitDexMethods(&visitor))) {                         \
   1084         return 0;                                                         \
   1085       }                                                                   \
   1086       relative_offset = visitor.GetOffset();                              \
   1087     } while (false)
   1088 
   1089   VISIT(WriteCodeMethodVisitor);
   1090 
   1091   #undef VISIT
   1092 
   1093   return relative_offset;
   1094 }
   1095 
   1096 OatWriter::OatDexFile::OatDexFile(size_t offset, const DexFile& dex_file) {
   1097   offset_ = offset;
   1098   const std::string& location(dex_file.GetLocation());
   1099   dex_file_location_size_ = location.size();
   1100   dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data());
   1101   dex_file_location_checksum_ = dex_file.GetLocationChecksum();
   1102   dex_file_offset_ = 0;
   1103   methods_offsets_.resize(dex_file.NumClassDefs());
   1104 }
   1105 
   1106 size_t OatWriter::OatDexFile::SizeOf() const {
   1107   return sizeof(dex_file_location_size_)
   1108           + dex_file_location_size_
   1109           + sizeof(dex_file_location_checksum_)
   1110           + sizeof(dex_file_offset_)
   1111           + (sizeof(methods_offsets_[0]) * methods_offsets_.size());
   1112 }
   1113 
   1114 void OatWriter::OatDexFile::UpdateChecksum(OatHeader* oat_header) const {
   1115   oat_header->UpdateChecksum(&dex_file_location_size_, sizeof(dex_file_location_size_));
   1116   oat_header->UpdateChecksum(dex_file_location_data_, dex_file_location_size_);
   1117   oat_header->UpdateChecksum(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_));
   1118   oat_header->UpdateChecksum(&dex_file_offset_, sizeof(dex_file_offset_));
   1119   oat_header->UpdateChecksum(&methods_offsets_[0],
   1120                             sizeof(methods_offsets_[0]) * methods_offsets_.size());
   1121 }
   1122 
   1123 bool OatWriter::OatDexFile::Write(OatWriter* oat_writer,
   1124                                   OutputStream* out,
   1125                                   const size_t file_offset) const {
   1126   DCHECK_OFFSET_();
   1127   if (!out->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) {
   1128     PLOG(ERROR) << "Failed to write dex file location length to " << out->GetLocation();
   1129     return false;
   1130   }
   1131   oat_writer->size_oat_dex_file_location_size_ += sizeof(dex_file_location_size_);
   1132   if (!out->WriteFully(dex_file_location_data_, dex_file_location_size_)) {
   1133     PLOG(ERROR) << "Failed to write dex file location data to " << out->GetLocation();
   1134     return false;
   1135   }
   1136   oat_writer->size_oat_dex_file_location_data_ += dex_file_location_size_;
   1137   if (!out->WriteFully(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_))) {
   1138     PLOG(ERROR) << "Failed to write dex file location checksum to " << out->GetLocation();
   1139     return false;
   1140   }
   1141   oat_writer->size_oat_dex_file_location_checksum_ += sizeof(dex_file_location_checksum_);
   1142   if (!out->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) {
   1143     PLOG(ERROR) << "Failed to write dex file offset to " << out->GetLocation();
   1144     return false;
   1145   }
   1146   oat_writer->size_oat_dex_file_offset_ += sizeof(dex_file_offset_);
   1147   if (!out->WriteFully(&methods_offsets_[0],
   1148                       sizeof(methods_offsets_[0]) * methods_offsets_.size())) {
   1149     PLOG(ERROR) << "Failed to write methods offsets to " << out->GetLocation();
   1150     return false;
   1151   }
   1152   oat_writer->size_oat_dex_file_methods_offsets_ +=
   1153       sizeof(methods_offsets_[0]) * methods_offsets_.size();
   1154   return true;
   1155 }
   1156 
   1157 OatWriter::OatClass::OatClass(size_t offset,
   1158                               const std::vector<CompiledMethod*>& compiled_methods,
   1159                               uint32_t num_non_null_compiled_methods,
   1160                               mirror::Class::Status status)
   1161     : compiled_methods_(compiled_methods) {
   1162   uint32_t num_methods = compiled_methods.size();
   1163   CHECK_LE(num_non_null_compiled_methods, num_methods);
   1164 
   1165   offset_ = offset;
   1166   oat_method_offsets_offsets_from_oat_class_.resize(num_methods);
   1167 
   1168   // Since both kOatClassNoneCompiled and kOatClassAllCompiled could
   1169   // apply when there are 0 methods, we just arbitrarily say that 0
   1170   // methods means kOatClassNoneCompiled and that we won't use
   1171   // kOatClassAllCompiled unless there is at least one compiled
   1172   // method. This means in an interpretter only system, we can assert
   1173   // that all classes are kOatClassNoneCompiled.
   1174   if (num_non_null_compiled_methods == 0) {
   1175     type_ = kOatClassNoneCompiled;
   1176   } else if (num_non_null_compiled_methods == num_methods) {
   1177     type_ = kOatClassAllCompiled;
   1178   } else {
   1179     type_ = kOatClassSomeCompiled;
   1180   }
   1181 
   1182   status_ = status;
   1183   method_offsets_.resize(num_non_null_compiled_methods);
   1184   method_headers_.resize(num_non_null_compiled_methods);
   1185 
   1186   uint32_t oat_method_offsets_offset_from_oat_class = sizeof(type_) + sizeof(status_);
   1187   if (type_ == kOatClassSomeCompiled) {
   1188     method_bitmap_ = new BitVector(num_methods, false, Allocator::GetMallocAllocator());
   1189     method_bitmap_size_ = method_bitmap_->GetSizeOf();
   1190     oat_method_offsets_offset_from_oat_class += sizeof(method_bitmap_size_);
   1191     oat_method_offsets_offset_from_oat_class += method_bitmap_size_;
   1192   } else {
   1193     method_bitmap_ = NULL;
   1194     method_bitmap_size_ = 0;
   1195   }
   1196 
   1197   for (size_t i = 0; i < num_methods; i++) {
   1198     CompiledMethod* compiled_method = compiled_methods_[i];
   1199     if (compiled_method == NULL) {
   1200       oat_method_offsets_offsets_from_oat_class_[i] = 0;
   1201     } else {
   1202       oat_method_offsets_offsets_from_oat_class_[i] = oat_method_offsets_offset_from_oat_class;
   1203       oat_method_offsets_offset_from_oat_class += sizeof(OatMethodOffsets);
   1204       if (type_ == kOatClassSomeCompiled) {
   1205         method_bitmap_->SetBit(i);
   1206       }
   1207     }
   1208   }
   1209 }
   1210 
   1211 OatWriter::OatClass::~OatClass() {
   1212   delete method_bitmap_;
   1213 }
   1214 
   1215 size_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatHeader(
   1216     size_t class_def_method_index_) const {
   1217   uint32_t method_offset = GetOatMethodOffsetsOffsetFromOatClass(class_def_method_index_);
   1218   if (method_offset == 0) {
   1219     return 0;
   1220   }
   1221   return offset_ + method_offset;
   1222 }
   1223 
   1224 size_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatClass(
   1225     size_t class_def_method_index_) const {
   1226   return oat_method_offsets_offsets_from_oat_class_[class_def_method_index_];
   1227 }
   1228 
   1229 size_t OatWriter::OatClass::SizeOf() const {
   1230   return sizeof(status_)
   1231           + sizeof(type_)
   1232           + ((method_bitmap_size_ == 0) ? 0 : sizeof(method_bitmap_size_))
   1233           + method_bitmap_size_
   1234           + (sizeof(method_offsets_[0]) * method_offsets_.size());
   1235 }
   1236 
   1237 void OatWriter::OatClass::UpdateChecksum(OatHeader* oat_header) const {
   1238   oat_header->UpdateChecksum(&status_, sizeof(status_));
   1239   oat_header->UpdateChecksum(&type_, sizeof(type_));
   1240   if (method_bitmap_size_ != 0) {
   1241     CHECK_EQ(kOatClassSomeCompiled, type_);
   1242     oat_header->UpdateChecksum(&method_bitmap_size_, sizeof(method_bitmap_size_));
   1243     oat_header->UpdateChecksum(method_bitmap_->GetRawStorage(), method_bitmap_size_);
   1244   }
   1245   oat_header->UpdateChecksum(&method_offsets_[0],
   1246                              sizeof(method_offsets_[0]) * method_offsets_.size());
   1247 }
   1248 
   1249 bool OatWriter::OatClass::Write(OatWriter* oat_writer,
   1250                                 OutputStream* out,
   1251                                 const size_t file_offset) const {
   1252   DCHECK_OFFSET_();
   1253   if (!out->WriteFully(&status_, sizeof(status_))) {
   1254     PLOG(ERROR) << "Failed to write class status to " << out->GetLocation();
   1255     return false;
   1256   }
   1257   oat_writer->size_oat_class_status_ += sizeof(status_);
   1258   if (!out->WriteFully(&type_, sizeof(type_))) {
   1259     PLOG(ERROR) << "Failed to write oat class type to " << out->GetLocation();
   1260     return false;
   1261   }
   1262   oat_writer->size_oat_class_type_ += sizeof(type_);
   1263   if (method_bitmap_size_ != 0) {
   1264     CHECK_EQ(kOatClassSomeCompiled, type_);
   1265     if (!out->WriteFully(&method_bitmap_size_, sizeof(method_bitmap_size_))) {
   1266       PLOG(ERROR) << "Failed to write method bitmap size to " << out->GetLocation();
   1267       return false;
   1268     }
   1269     oat_writer->size_oat_class_method_bitmaps_ += sizeof(method_bitmap_size_);
   1270     if (!out->WriteFully(method_bitmap_->GetRawStorage(), method_bitmap_size_)) {
   1271       PLOG(ERROR) << "Failed to write method bitmap to " << out->GetLocation();
   1272       return false;
   1273     }
   1274     oat_writer->size_oat_class_method_bitmaps_ += method_bitmap_size_;
   1275   }
   1276   if (!out->WriteFully(&method_offsets_[0],
   1277                       sizeof(method_offsets_[0]) * method_offsets_.size())) {
   1278     PLOG(ERROR) << "Failed to write method offsets to " << out->GetLocation();
   1279     return false;
   1280   }
   1281   oat_writer->size_oat_class_method_offsets_ += sizeof(method_offsets_[0]) * method_offsets_.size();
   1282   return true;
   1283 }
   1284 
   1285 }  // namespace art
   1286