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 "compiled_method.h"
     18 #include "driver/compiler_driver.h"
     19 
     20 namespace art {
     21 
     22 CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set,
     23                            const ArrayRef<const uint8_t>& quick_code, bool owns_code_array)
     24     : compiler_driver_(compiler_driver), instruction_set_(instruction_set),
     25       owns_code_array_(owns_code_array), quick_code_(nullptr) {
     26   SetCode(&quick_code);
     27 }
     28 
     29 void CompiledCode::SetCode(const ArrayRef<const uint8_t>* quick_code) {
     30   if (quick_code != nullptr) {
     31     CHECK(!quick_code->empty());
     32     if (owns_code_array_) {
     33       // If we are supposed to own the code, don't deduplicate it.
     34       CHECK(quick_code_ == nullptr);
     35       quick_code_ = new SwapVector<uint8_t>(quick_code->begin(), quick_code->end(),
     36                                             compiler_driver_->GetSwapSpaceAllocator());
     37     } else {
     38       quick_code_ = compiler_driver_->DeduplicateCode(*quick_code);
     39     }
     40   }
     41 }
     42 
     43 CompiledCode::~CompiledCode() {
     44   if (owns_code_array_) {
     45     delete quick_code_;
     46   }
     47 }
     48 
     49 bool CompiledCode::operator==(const CompiledCode& rhs) const {
     50   if (quick_code_ != nullptr) {
     51     if (rhs.quick_code_ == nullptr) {
     52       return false;
     53     } else if (quick_code_->size() != rhs.quick_code_->size()) {
     54       return false;
     55     } else {
     56       return std::equal(quick_code_->begin(), quick_code_->end(), rhs.quick_code_->begin());
     57     }
     58   }
     59   return (rhs.quick_code_ == nullptr);
     60 }
     61 
     62 size_t CompiledCode::AlignCode(size_t offset) const {
     63   return AlignCode(offset, instruction_set_);
     64 }
     65 
     66 size_t CompiledCode::AlignCode(size_t offset, InstructionSet instruction_set) {
     67   return RoundUp(offset, GetInstructionSetAlignment(instruction_set));
     68 }
     69 
     70 size_t CompiledCode::CodeDelta() const {
     71   return CodeDelta(instruction_set_);
     72 }
     73 
     74 size_t CompiledCode::CodeDelta(InstructionSet instruction_set) {
     75   switch (instruction_set) {
     76     case kArm:
     77     case kArm64:
     78     case kMips:
     79     case kMips64:
     80     case kX86:
     81     case kX86_64:
     82       return 0;
     83     case kThumb2: {
     84       // +1 to set the low-order bit so a BLX will switch to Thumb mode
     85       return 1;
     86     }
     87     default:
     88       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
     89       return 0;
     90   }
     91 }
     92 
     93 const void* CompiledCode::CodePointer(const void* code_pointer,
     94                                       InstructionSet instruction_set) {
     95   switch (instruction_set) {
     96     case kArm:
     97     case kArm64:
     98     case kMips:
     99     case kMips64:
    100     case kX86:
    101     case kX86_64:
    102       return code_pointer;
    103     case kThumb2: {
    104       uintptr_t address = reinterpret_cast<uintptr_t>(code_pointer);
    105       // Set the low-order bit so a BLX will switch to Thumb mode
    106       address |= 0x1;
    107       return reinterpret_cast<const void*>(address);
    108     }
    109     default:
    110       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
    111       return nullptr;
    112   }
    113 }
    114 
    115 const std::vector<uint32_t>& CompiledCode::GetOatdataOffsetsToCompliledCodeOffset() const {
    116   CHECK_NE(0U, oatdata_offsets_to_compiled_code_offset_.size());
    117   return oatdata_offsets_to_compiled_code_offset_;
    118 }
    119 
    120 void CompiledCode::AddOatdataOffsetToCompliledCodeOffset(uint32_t offset) {
    121   oatdata_offsets_to_compiled_code_offset_.push_back(offset);
    122 }
    123 
    124 CompiledMethod::CompiledMethod(CompilerDriver* driver,
    125                                InstructionSet instruction_set,
    126                                const ArrayRef<const uint8_t>& quick_code,
    127                                const size_t frame_size_in_bytes,
    128                                const uint32_t core_spill_mask,
    129                                const uint32_t fp_spill_mask,
    130                                DefaultSrcMap* src_mapping_table,
    131                                const ArrayRef<const uint8_t>& mapping_table,
    132                                const ArrayRef<const uint8_t>& vmap_table,
    133                                const ArrayRef<const uint8_t>& native_gc_map,
    134                                const ArrayRef<const uint8_t>& cfi_info,
    135                                const ArrayRef<const LinkerPatch>& patches)
    136     : CompiledCode(driver, instruction_set, quick_code, !driver->DedupeEnabled()),
    137       owns_arrays_(!driver->DedupeEnabled()),
    138       frame_size_in_bytes_(frame_size_in_bytes), core_spill_mask_(core_spill_mask),
    139       fp_spill_mask_(fp_spill_mask),
    140       patches_(patches.begin(), patches.end(), driver->GetSwapSpaceAllocator()) {
    141   if (owns_arrays_) {
    142     if (src_mapping_table == nullptr) {
    143       src_mapping_table_ = new SwapSrcMap(driver->GetSwapSpaceAllocator());
    144     } else {
    145       src_mapping_table_ = new SwapSrcMap(src_mapping_table->begin(), src_mapping_table->end(),
    146                                           driver->GetSwapSpaceAllocator());
    147     }
    148     mapping_table_ = mapping_table.empty() ?
    149         nullptr : new SwapVector<uint8_t>(mapping_table.begin(), mapping_table.end(),
    150                                           driver->GetSwapSpaceAllocator());
    151     vmap_table_ = new SwapVector<uint8_t>(vmap_table.begin(), vmap_table.end(),
    152                                           driver->GetSwapSpaceAllocator());
    153     gc_map_ = native_gc_map.empty() ? nullptr :
    154         new SwapVector<uint8_t>(native_gc_map.begin(), native_gc_map.end(),
    155                                 driver->GetSwapSpaceAllocator());
    156     cfi_info_ = cfi_info.empty() ? nullptr :
    157         new SwapVector<uint8_t>(cfi_info.begin(), cfi_info.end(), driver->GetSwapSpaceAllocator());
    158   } else {
    159     src_mapping_table_ = src_mapping_table == nullptr ?
    160         driver->DeduplicateSrcMappingTable(ArrayRef<SrcMapElem>()) :
    161         driver->DeduplicateSrcMappingTable(ArrayRef<SrcMapElem>(*src_mapping_table));
    162     mapping_table_ = mapping_table.empty() ?
    163         nullptr : driver->DeduplicateMappingTable(mapping_table);
    164     vmap_table_ = driver->DeduplicateVMapTable(vmap_table);
    165     gc_map_ = native_gc_map.empty() ? nullptr : driver->DeduplicateGCMap(native_gc_map);
    166     cfi_info_ = cfi_info.empty() ? nullptr : driver->DeduplicateCFIInfo(cfi_info);
    167   }
    168 }
    169 
    170 CompiledMethod* CompiledMethod::SwapAllocCompiledMethod(
    171     CompilerDriver* driver,
    172     InstructionSet instruction_set,
    173     const ArrayRef<const uint8_t>& quick_code,
    174     const size_t frame_size_in_bytes,
    175     const uint32_t core_spill_mask,
    176     const uint32_t fp_spill_mask,
    177     DefaultSrcMap* src_mapping_table,
    178     const ArrayRef<const uint8_t>& mapping_table,
    179     const ArrayRef<const uint8_t>& vmap_table,
    180     const ArrayRef<const uint8_t>& native_gc_map,
    181     const ArrayRef<const uint8_t>& cfi_info,
    182     const ArrayRef<const LinkerPatch>& patches) {
    183   SwapAllocator<CompiledMethod> alloc(driver->GetSwapSpaceAllocator());
    184   CompiledMethod* ret = alloc.allocate(1);
    185   alloc.construct(ret, driver, instruction_set, quick_code, frame_size_in_bytes, core_spill_mask,
    186                   fp_spill_mask, src_mapping_table, mapping_table, vmap_table, native_gc_map,
    187                   cfi_info, patches);
    188   return ret;
    189 }
    190 
    191 
    192 
    193 void CompiledMethod::ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m) {
    194   SwapAllocator<CompiledMethod> alloc(driver->GetSwapSpaceAllocator());
    195   alloc.destroy(m);
    196   alloc.deallocate(m, 1);
    197 }
    198 
    199 CompiledMethod::~CompiledMethod() {
    200   if (owns_arrays_) {
    201     delete src_mapping_table_;
    202     delete mapping_table_;
    203     delete vmap_table_;
    204     delete gc_map_;
    205     delete cfi_info_;
    206   }
    207 }
    208 
    209 }  // namespace art
    210