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:
StackMapStream(ArenaAllocator * allocator)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.
StackMaskEncodingSize(int max_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 
AddStackMapEntry(uint32_t dex_pc,T native_pc,uint32_t register_mask,BitVector * sp_mask,uint32_t num_dex_registers,uint8_t inlining_depth)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 
AddDexRegisterEntry(DexRegisterMap::LocationKind kind,int32_t value)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 
AddInlineInfoEntry(uint32_t method_index)98   void AddInlineInfoEntry(uint32_t method_index) {
99     InlineInfoEntry entry;
100     entry.method_index = method_index;
101     inline_infos_.Add(entry);
102   }
103 
ComputeNeededSize()104   size_t ComputeNeededSize() const {
105     return CodeInfo<T>::kFixedSize
106         + ComputeStackMapSize()
107         + ComputeDexRegisterMapSize()
108         + ComputeInlineInfoSize();
109   }
110 
ComputeStackMapSize()111   size_t ComputeStackMapSize() const {
112     return stack_maps_.Size() * (StackMap<T>::kFixedSize + StackMaskEncodingSize(stack_mask_max_));
113   }
114 
ComputeDexRegisterMapSize()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 
ComputeInlineInfoSize()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 
ComputeInlineInfoStart()128   size_t ComputeInlineInfoStart() const {
129     return ComputeDexRegisterMapStart() + ComputeDexRegisterMapSize();
130   }
131 
ComputeDexRegisterMapStart()132   size_t ComputeDexRegisterMapStart() const {
133     return CodeInfo<T>::kFixedSize + ComputeStackMapSize();
134   }
135 
FillIn(MemoryRegion region)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