Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2014 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 #ifndef ART_COMPILER_OPTIMIZING_STACK_MAP_STREAM_H_
     18 #define ART_COMPILER_OPTIMIZING_STACK_MAP_STREAM_H_
     19 
     20 #include "base/bit_vector.h"
     21 #include "memory_region.h"
     22 #include "stack_map.h"
     23 #include "utils/allocation.h"
     24 #include "utils/growable_array.h"
     25 
     26 namespace art {
     27 
     28 /**
     29  * Collects and builds a CodeInfo for a method.
     30  */
     31 template<typename T>
     32 class StackMapStream : public ValueObject {
     33  public:
     34   explicit StackMapStream(ArenaAllocator* allocator)
     35       : stack_maps_(allocator, 10),
     36         dex_register_maps_(allocator, 10 * 4),
     37         inline_infos_(allocator, 2),
     38         stack_mask_max_(-1),
     39         number_of_stack_maps_with_inline_info_(0) {}
     40 
     41   // Compute bytes needed to encode a mask with the given maximum element.
     42   static uint32_t StackMaskEncodingSize(int max_element) {
     43     int number_of_bits = max_element + 1;  // Need room for max element too.
     44     return RoundUp(number_of_bits, kBitsPerByte) / kBitsPerByte;
     45   }
     46 
     47   // See runtime/stack_map.h to know what these fields contain.
     48   struct StackMapEntry {
     49     uint32_t dex_pc;
     50     T native_pc;
     51     uint32_t register_mask;
     52     BitVector* sp_mask;
     53     uint32_t num_dex_registers;
     54     uint8_t inlining_depth;
     55     size_t dex_register_maps_start_index;
     56     size_t inline_infos_start_index;
     57   };
     58 
     59   struct DexRegisterEntry {
     60     DexRegisterMap::LocationKind kind;
     61     int32_t value;
     62   };
     63 
     64   struct InlineInfoEntry {
     65     uint32_t method_index;
     66   };
     67 
     68   void AddStackMapEntry(uint32_t dex_pc,
     69                         T native_pc,
     70                         uint32_t register_mask,
     71                         BitVector* sp_mask,
     72                         uint32_t num_dex_registers,
     73                         uint8_t inlining_depth) {
     74     StackMapEntry entry;
     75     entry.dex_pc = dex_pc;
     76     entry.native_pc = native_pc;
     77     entry.register_mask = register_mask;
     78     entry.sp_mask = sp_mask;
     79     entry.num_dex_registers = num_dex_registers;
     80     entry.inlining_depth = inlining_depth;
     81     entry.dex_register_maps_start_index = dex_register_maps_.Size();
     82     entry.inline_infos_start_index = inline_infos_.Size();
     83     stack_maps_.Add(entry);
     84 
     85     stack_mask_max_ = std::max(stack_mask_max_, sp_mask->GetHighestBitSet());
     86     if (inlining_depth > 0) {
     87       number_of_stack_maps_with_inline_info_++;
     88     }
     89   }
     90 
     91   void AddDexRegisterEntry(DexRegisterMap::LocationKind kind, int32_t value) {
     92     DexRegisterEntry entry;
     93     entry.kind = kind;
     94     entry.value = value;
     95     dex_register_maps_.Add(entry);
     96   }
     97 
     98   void AddInlineInfoEntry(uint32_t method_index) {
     99     InlineInfoEntry entry;
    100     entry.method_index = method_index;
    101     inline_infos_.Add(entry);
    102   }
    103 
    104   size_t ComputeNeededSize() const {
    105     return CodeInfo<T>::kFixedSize
    106         + ComputeStackMapSize()
    107         + ComputeDexRegisterMapSize()
    108         + ComputeInlineInfoSize();
    109   }
    110 
    111   size_t ComputeStackMapSize() const {
    112     return stack_maps_.Size() * (StackMap<T>::kFixedSize + StackMaskEncodingSize(stack_mask_max_));
    113   }
    114 
    115   size_t ComputeDexRegisterMapSize() const {
    116     // We currently encode all dex register information per stack map.
    117     return stack_maps_.Size() * DexRegisterMap::kFixedSize
    118       // For each dex register entry.
    119       + (dex_register_maps_.Size() * DexRegisterMap::SingleEntrySize());
    120   }
    121 
    122   size_t ComputeInlineInfoSize() const {
    123     return inline_infos_.Size() * InlineInfo::SingleEntrySize()
    124       // For encoding the depth.
    125       + (number_of_stack_maps_with_inline_info_ * InlineInfo::kFixedSize);
    126   }
    127 
    128   size_t ComputeInlineInfoStart() const {
    129     return ComputeDexRegisterMapStart() + ComputeDexRegisterMapSize();
    130   }
    131 
    132   size_t ComputeDexRegisterMapStart() const {
    133     return CodeInfo<T>::kFixedSize + ComputeStackMapSize();
    134   }
    135 
    136   void FillIn(MemoryRegion region) {
    137     CodeInfo<T> code_info(region);
    138 
    139     size_t stack_mask_size = StackMaskEncodingSize(stack_mask_max_);
    140     uint8_t* memory_start = region.start();
    141 
    142     MemoryRegion dex_register_maps_region = region.Subregion(
    143       ComputeDexRegisterMapStart(),
    144       ComputeDexRegisterMapSize());
    145 
    146     MemoryRegion inline_infos_region = region.Subregion(
    147       ComputeInlineInfoStart(),
    148       ComputeInlineInfoSize());
    149 
    150     code_info.SetNumberOfStackMaps(stack_maps_.Size());
    151     code_info.SetStackMaskSize(stack_mask_size);
    152 
    153     uintptr_t next_dex_register_map_offset = 0;
    154     uintptr_t next_inline_info_offset = 0;
    155     for (size_t i = 0, e = stack_maps_.Size(); i < e; ++i) {
    156       StackMap<T> stack_map = code_info.GetStackMapAt(i);
    157       StackMapEntry entry = stack_maps_.Get(i);
    158 
    159       stack_map.SetDexPc(entry.dex_pc);
    160       stack_map.SetNativePc(entry.native_pc);
    161       stack_map.SetRegisterMask(entry.register_mask);
    162       stack_map.SetStackMask(*entry.sp_mask);
    163 
    164       // Set the register map.
    165       MemoryRegion region = dex_register_maps_region.Subregion(
    166           next_dex_register_map_offset,
    167           DexRegisterMap::kFixedSize + entry.num_dex_registers * DexRegisterMap::SingleEntrySize());
    168       next_dex_register_map_offset += region.size();
    169       DexRegisterMap dex_register_map(region);
    170       stack_map.SetDexRegisterMapOffset(region.start() - memory_start);
    171 
    172       for (size_t i = 0; i < entry.num_dex_registers; ++i) {
    173         DexRegisterEntry register_entry =
    174             dex_register_maps_.Get(i + entry.dex_register_maps_start_index);
    175         dex_register_map.SetRegisterInfo(i, register_entry.kind, register_entry.value);
    176       }
    177 
    178       // Set the inlining info.
    179       if (entry.inlining_depth != 0) {
    180         MemoryRegion region = inline_infos_region.Subregion(
    181             next_inline_info_offset,
    182             InlineInfo::kFixedSize + entry.inlining_depth * InlineInfo::SingleEntrySize());
    183         next_inline_info_offset += region.size();
    184         InlineInfo inline_info(region);
    185 
    186         stack_map.SetInlineDescriptorOffset(region.start() - memory_start);
    187 
    188         inline_info.SetDepth(entry.inlining_depth);
    189         for (size_t i = 0; i < entry.inlining_depth; ++i) {
    190           InlineInfoEntry inline_entry = inline_infos_.Get(i + entry.inline_infos_start_index);
    191           inline_info.SetMethodReferenceIndexAtDepth(i, inline_entry.method_index);
    192         }
    193       } else {
    194         stack_map.SetInlineDescriptorOffset(InlineInfo::kNoInlineInfo);
    195       }
    196     }
    197   }
    198 
    199  private:
    200   GrowableArray<StackMapEntry> stack_maps_;
    201   GrowableArray<DexRegisterEntry> dex_register_maps_;
    202   GrowableArray<InlineInfoEntry> inline_infos_;
    203   int stack_mask_max_;
    204   size_t number_of_stack_maps_with_inline_info_;
    205 
    206   DISALLOW_COPY_AND_ASSIGN(StackMapStream);
    207 };
    208 
    209 }  // namespace art
    210 
    211 #endif  // ART_COMPILER_OPTIMIZING_STACK_MAP_STREAM_H_
    212