blob: 5818a37a46c2c18702ce96d498fc050f9aed1e28 [file] [log] [blame]
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001/*
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
Calin Juravle6ae70962015-03-18 16:31:28 +000020#include "base/arena_containers.h"
21#include "base/bit_vector-inl.h"
Ian Rogers0279ebb2014-10-08 17:27:48 -070022#include "base/value_object.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010023#include "memory_region.h"
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +000024#include "nodes.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010025#include "stack_map.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010026#include "utils/growable_array.h"
27
28namespace art {
29
30/**
Nicolas Geoffray39468442014-09-02 15:17:15 +010031 * Collects and builds stack maps for a method. All the stack maps
32 * for a method are placed in a CodeInfo object.
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010033 */
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010034class StackMapStream : public ValueObject {
35 public:
36 explicit StackMapStream(ArenaAllocator* allocator)
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +000037 : allocator_(allocator),
38 stack_maps_(allocator, 10),
39 dex_register_locations_(allocator, 10 * 4),
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010040 inline_infos_(allocator, 2),
Andreas Gampe8eddd2a2014-07-28 14:53:22 -070041 stack_mask_max_(-1),
Nicolas Geoffray004c2302015-03-20 10:06:38 +000042 dex_pc_max_(0),
43 native_pc_offset_max_(0),
Calin Juravle6ae70962015-03-18 16:31:28 +000044 number_of_stack_maps_with_inline_info_(0),
45 dex_map_hash_to_stack_map_indices_(std::less<uint32_t>(), allocator->Adapter()) {}
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010046
47 // Compute bytes needed to encode a mask with the given maximum element.
48 static uint32_t StackMaskEncodingSize(int max_element) {
49 int number_of_bits = max_element + 1; // Need room for max element too.
50 return RoundUp(number_of_bits, kBitsPerByte) / kBitsPerByte;
51 }
52
53 // See runtime/stack_map.h to know what these fields contain.
54 struct StackMapEntry {
55 uint32_t dex_pc;
Nicolas Geoffray39468442014-09-02 15:17:15 +010056 uint32_t native_pc_offset;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010057 uint32_t register_mask;
58 BitVector* sp_mask;
59 uint32_t num_dex_registers;
60 uint8_t inlining_depth;
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +000061 size_t dex_register_locations_start_index;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010062 size_t inline_infos_start_index;
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +000063 BitVector* live_dex_registers_mask;
Calin Juravle6ae70962015-03-18 16:31:28 +000064 uint32_t dex_register_map_hash;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010065 };
66
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010067 struct InlineInfoEntry {
68 uint32_t method_index;
69 };
70
71 void AddStackMapEntry(uint32_t dex_pc,
Nicolas Geoffray39468442014-09-02 15:17:15 +010072 uint32_t native_pc_offset,
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010073 uint32_t register_mask,
74 BitVector* sp_mask,
75 uint32_t num_dex_registers,
Nicolas Geoffrayeeefa122015-03-13 18:52:59 +000076 uint8_t inlining_depth) {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010077 StackMapEntry entry;
78 entry.dex_pc = dex_pc;
Nicolas Geoffray39468442014-09-02 15:17:15 +010079 entry.native_pc_offset = native_pc_offset;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010080 entry.register_mask = register_mask;
81 entry.sp_mask = sp_mask;
82 entry.num_dex_registers = num_dex_registers;
83 entry.inlining_depth = inlining_depth;
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +000084 entry.dex_register_locations_start_index = dex_register_locations_.Size();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010085 entry.inline_infos_start_index = inline_infos_.Size();
Calin Juravle6ae70962015-03-18 16:31:28 +000086 entry.dex_register_map_hash = 0;
Nicolas Geoffrayeeefa122015-03-13 18:52:59 +000087 if (num_dex_registers != 0) {
88 entry.live_dex_registers_mask =
89 new (allocator_) ArenaBitVector(allocator_, num_dex_registers, true);
90 } else {
91 entry.live_dex_registers_mask = nullptr;
92 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010093 stack_maps_.Add(entry);
94
Nicolas Geoffray39468442014-09-02 15:17:15 +010095 if (sp_mask != nullptr) {
96 stack_mask_max_ = std::max(stack_mask_max_, sp_mask->GetHighestBitSet());
97 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010098 if (inlining_depth > 0) {
99 number_of_stack_maps_with_inline_info_++;
100 }
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000101
102 dex_pc_max_ = std::max(dex_pc_max_, dex_pc);
103 native_pc_offset_max_ = std::max(native_pc_offset_max_, native_pc_offset);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100104 }
105
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100106 void AddInlineInfoEntry(uint32_t method_index) {
107 InlineInfoEntry entry;
108 entry.method_index = method_index;
109 inline_infos_.Add(entry);
110 }
111
Calin Juravle6ae70962015-03-18 16:31:28 +0000112 size_t ComputeNeededSize() {
Roland Levillainede7bf82015-03-13 12:23:04 +0000113 size_t size = CodeInfo::kFixedSize
Roland Levillain29ba1b02015-03-13 11:45:07 +0000114 + ComputeStackMapsSize()
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000115 + ComputeDexRegisterMapsSize()
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100116 + ComputeInlineInfoSize();
Nicolas Geoffrayaec8f932015-03-18 10:42:22 +0000117 // Note: use RoundUp to word-size here if you want CodeInfo objects to be word aligned.
118 return size;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100119 }
120
Roland Levillain29ba1b02015-03-13 11:45:07 +0000121 size_t ComputeStackMaskSize() const {
122 return StackMaskEncodingSize(stack_mask_max_);
123 }
124
Calin Juravle6ae70962015-03-18 16:31:28 +0000125 size_t ComputeStackMapsSize() {
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000126 return stack_maps_.Size() * StackMap::ComputeStackMapSize(
127 ComputeStackMaskSize(),
128 ComputeInlineInfoSize(),
129 ComputeDexRegisterMapsSize(),
130 dex_pc_max_,
131 native_pc_offset_max_);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100132 }
133
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000134 // Compute the size of the Dex register map of `entry`.
135 size_t ComputeDexRegisterMapSize(const StackMapEntry& entry) const {
136 size_t size = DexRegisterMap::kFixedSize;
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000137 // Add the bit mask for the dex register liveness.
138 size += DexRegisterMap::LiveBitMaskSize(entry.num_dex_registers);
139 for (size_t dex_register_number = 0, index_in_dex_register_locations = 0;
140 dex_register_number < entry.num_dex_registers;
141 ++dex_register_number) {
142 if (entry.live_dex_registers_mask->IsBitSet(dex_register_number)) {
143 DexRegisterLocation dex_register_location = dex_register_locations_.Get(
144 entry.dex_register_locations_start_index + index_in_dex_register_locations);
145 size += DexRegisterMap::EntrySize(dex_register_location);
146 index_in_dex_register_locations++;
147 }
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000148 }
149 return size;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100150 }
151
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000152 // Compute the size of all the Dex register maps.
Calin Juravle6ae70962015-03-18 16:31:28 +0000153 size_t ComputeDexRegisterMapsSize() {
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000154 size_t size = 0;
155 for (size_t i = 0; i < stack_maps_.Size(); ++i) {
Calin Juravle6ae70962015-03-18 16:31:28 +0000156 if (FindEntryWithTheSameDexMap(i) == kNoSameDexMapFound) {
157 // Entries with the same dex map will have the same offset.
158 size += ComputeDexRegisterMapSize(stack_maps_.Get(i));
159 }
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000160 }
Roland Levillainede7bf82015-03-13 12:23:04 +0000161 return size;
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000162 }
163
164 // Compute the size of all the inline information pieces.
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100165 size_t ComputeInlineInfoSize() const {
166 return inline_infos_.Size() * InlineInfo::SingleEntrySize()
167 // For encoding the depth.
168 + (number_of_stack_maps_with_inline_info_ * InlineInfo::kFixedSize);
169 }
170
Calin Juravle6ae70962015-03-18 16:31:28 +0000171 size_t ComputeDexRegisterMapsStart() {
Roland Levillain29ba1b02015-03-13 11:45:07 +0000172 return CodeInfo::kFixedSize + ComputeStackMapsSize();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100173 }
174
Calin Juravle6ae70962015-03-18 16:31:28 +0000175 size_t ComputeInlineInfoStart() {
Roland Levillain9ac0e4d2015-03-12 18:33:05 +0000176 return ComputeDexRegisterMapsStart() + ComputeDexRegisterMapsSize();
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000177 }
178
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100179 void FillIn(MemoryRegion region) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100180 CodeInfo code_info(region);
Roland Levillain29ba1b02015-03-13 11:45:07 +0000181 DCHECK_EQ(region.size(), ComputeNeededSize());
Nicolas Geoffray39468442014-09-02 15:17:15 +0100182 code_info.SetOverallSize(region.size());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100183
Roland Levillain29ba1b02015-03-13 11:45:07 +0000184 size_t stack_mask_size = ComputeStackMaskSize();
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000185
186 size_t dex_register_map_size = ComputeDexRegisterMapsSize();
187 size_t inline_info_size = ComputeInlineInfoSize();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100188
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000189 MemoryRegion dex_register_locations_region = region.Subregion(
Roland Levillain9ac0e4d2015-03-12 18:33:05 +0000190 ComputeDexRegisterMapsStart(),
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000191 dex_register_map_size);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100192
193 MemoryRegion inline_infos_region = region.Subregion(
194 ComputeInlineInfoStart(),
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000195 inline_info_size);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100196
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000197 code_info.SetEncoding(
198 inline_info_size, dex_register_map_size, dex_pc_max_, native_pc_offset_max_);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100199 code_info.SetNumberOfStackMaps(stack_maps_.Size());
200 code_info.SetStackMaskSize(stack_mask_size);
Roland Levillain29ba1b02015-03-13 11:45:07 +0000201 DCHECK_EQ(code_info.StackMapsSize(), ComputeStackMapsSize());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100202
203 uintptr_t next_dex_register_map_offset = 0;
204 uintptr_t next_inline_info_offset = 0;
205 for (size_t i = 0, e = stack_maps_.Size(); i < e; ++i) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100206 StackMap stack_map = code_info.GetStackMapAt(i);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100207 StackMapEntry entry = stack_maps_.Get(i);
208
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000209 stack_map.SetDexPc(code_info, entry.dex_pc);
210 stack_map.SetNativePcOffset(code_info, entry.native_pc_offset);
211 stack_map.SetRegisterMask(code_info, entry.register_mask);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100212 if (entry.sp_mask != nullptr) {
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000213 stack_map.SetStackMask(code_info, *entry.sp_mask);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100214 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100215
Calin Juravle6ae70962015-03-18 16:31:28 +0000216 if (entry.num_dex_registers == 0) {
217 // No dex map available.
218 stack_map.SetDexRegisterMapOffset(code_info, StackMap::kNoDexRegisterMap);
219 } else {
220 // Search for an entry with the same dex map.
221 size_t entry_with_same_map = FindEntryWithTheSameDexMap(i);
222 if (entry_with_same_map != kNoSameDexMapFound) {
223 // If we have a hit reuse the offset.
224 stack_map.SetDexRegisterMapOffset(code_info,
225 code_info.GetStackMapAt(entry_with_same_map).GetDexRegisterMapOffset(code_info));
226 } else {
227 // New dex registers maps should be added to the stack map.
228 MemoryRegion register_region =
229 dex_register_locations_region.Subregion(
230 next_dex_register_map_offset,
231 ComputeDexRegisterMapSize(entry));
232 next_dex_register_map_offset += register_region.size();
233 DexRegisterMap dex_register_map(register_region);
234 stack_map.SetDexRegisterMapOffset(
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000235 code_info, register_region.start() - dex_register_locations_region.start());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100236
Calin Juravle6ae70962015-03-18 16:31:28 +0000237 // Offset in `dex_register_map` where to store the next register entry.
238 size_t offset = DexRegisterMap::kFixedSize;
239 dex_register_map.SetLiveBitMask(offset,
240 entry.num_dex_registers,
241 *entry.live_dex_registers_mask);
242 offset += DexRegisterMap::LiveBitMaskSize(entry.num_dex_registers);
243 for (size_t dex_register_number = 0, index_in_dex_register_locations = 0;
244 dex_register_number < entry.num_dex_registers;
245 ++dex_register_number) {
246 if (entry.live_dex_registers_mask->IsBitSet(dex_register_number)) {
247 DexRegisterLocation dex_register_location = dex_register_locations_.Get(
248 entry.dex_register_locations_start_index + index_in_dex_register_locations);
249 dex_register_map.SetRegisterInfo(offset, dex_register_location);
250 offset += DexRegisterMap::EntrySize(dex_register_location);
251 ++index_in_dex_register_locations;
252 }
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000253 }
Calin Juravle6ae70962015-03-18 16:31:28 +0000254 // Ensure we reached the end of the Dex registers region.
255 DCHECK_EQ(offset, register_region.size());
Roland Levillain442b46a2015-02-18 16:54:21 +0000256 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100257 }
258
259 // Set the inlining info.
260 if (entry.inlining_depth != 0) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800261 MemoryRegion inline_region = inline_infos_region.Subregion(
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100262 next_inline_info_offset,
263 InlineInfo::kFixedSize + entry.inlining_depth * InlineInfo::SingleEntrySize());
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800264 next_inline_info_offset += inline_region.size();
265 InlineInfo inline_info(inline_region);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100266
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000267 // Currently relative to the dex register map.
268 stack_map.SetInlineDescriptorOffset(
269 code_info, inline_region.start() - dex_register_locations_region.start());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100270
271 inline_info.SetDepth(entry.inlining_depth);
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800272 for (size_t j = 0; j < entry.inlining_depth; ++j) {
273 InlineInfoEntry inline_entry = inline_infos_.Get(j + entry.inline_infos_start_index);
274 inline_info.SetMethodReferenceIndexAtDepth(j, inline_entry.method_index);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100275 }
276 } else {
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000277 if (inline_info_size != 0) {
278 stack_map.SetInlineDescriptorOffset(code_info, StackMap::kNoInlineInfo);
279 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100280 }
281 }
282 }
283
Nicolas Geoffrayeeefa122015-03-13 18:52:59 +0000284 void AddDexRegisterEntry(uint16_t dex_register, DexRegisterLocation::Kind kind, int32_t value) {
285 if (kind != DexRegisterLocation::Kind::kNone) {
286 // Ensure we only use non-compressed location kind at this stage.
287 DCHECK(DexRegisterLocation::IsShortLocationKind(kind))
288 << DexRegisterLocation::PrettyDescriptor(kind);
289 dex_register_locations_.Add(DexRegisterLocation(kind, value));
Calin Juravle6ae70962015-03-18 16:31:28 +0000290 StackMapEntry entry = stack_maps_.Get(stack_maps_.Size() - 1);
291 entry.live_dex_registers_mask->SetBit(dex_register);
292 entry.dex_register_map_hash += (1 << dex_register);
293 entry.dex_register_map_hash += static_cast<uint32_t>(value);
294 entry.dex_register_map_hash += static_cast<uint32_t>(kind);
295 stack_maps_.Put(stack_maps_.Size() - 1, entry);
Nicolas Geoffrayeeefa122015-03-13 18:52:59 +0000296 }
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000297 }
298
Nicolas Geoffrayeeefa122015-03-13 18:52:59 +0000299 private:
Calin Juravle6ae70962015-03-18 16:31:28 +0000300 // Returns the index of an entry with the same dex register map
301 // or kNoSameDexMapFound if no such entry exists.
302 size_t FindEntryWithTheSameDexMap(size_t entry_index) {
303 StackMapEntry entry = stack_maps_.Get(entry_index);
304 auto entries_it = dex_map_hash_to_stack_map_indices_.find(entry.dex_register_map_hash);
305 if (entries_it == dex_map_hash_to_stack_map_indices_.end()) {
306 // We don't have a perfect hash functions so we need a list to collect all stack maps
307 // which might have the same dex register map.
308 GrowableArray<uint32_t> stack_map_indices(allocator_, 1);
309 stack_map_indices.Add(entry_index);
310 dex_map_hash_to_stack_map_indices_.Put(entry.dex_register_map_hash, stack_map_indices);
311 return kNoSameDexMapFound;
312 }
313
314 // TODO: We don't need to add ourselves to the map if we can guarantee that
315 // FindEntryWithTheSameDexMap is called just once per stack map entry.
316 // A good way to do this is to cache the offset in the stack map entry. This
317 // is easier to do if we add markers when the stack map constructions begins
318 // and when it ends.
319
320 // We might have collisions, so we need to check whether or not we should
321 // add the entry to the map. `needs_to_be_added` keeps track of this.
322 bool needs_to_be_added = true;
323 size_t result = kNoSameDexMapFound;
324 for (size_t i = 0; i < entries_it->second.Size(); i++) {
325 size_t test_entry_index = entries_it->second.Get(i);
326 if (test_entry_index == entry_index) {
327 needs_to_be_added = false;
328 } else if (HaveTheSameDexMaps(stack_maps_.Get(test_entry_index), entry)) {
329 result = test_entry_index;
330 needs_to_be_added = false;
331 break;
332 }
333 }
334 if (needs_to_be_added) {
335 entries_it->second.Add(entry_index);
336 }
337 return result;
338 }
339
340 bool HaveTheSameDexMaps(const StackMapEntry& a, const StackMapEntry& b) const {
341 if (a.live_dex_registers_mask == nullptr && b.live_dex_registers_mask == nullptr) {
342 return true;
343 }
344 if (a.live_dex_registers_mask == nullptr || b.live_dex_registers_mask == nullptr) {
345 return false;
346 }
347 if (a.num_dex_registers != b.num_dex_registers) {
348 return false;
349 }
350
351 int index_in_dex_register_locations = 0;
352 for (uint32_t i = 0; i < a.num_dex_registers; i++) {
353 if (a.live_dex_registers_mask->IsBitSet(i) != b.live_dex_registers_mask->IsBitSet(i)) {
354 return false;
355 }
356 if (a.live_dex_registers_mask->IsBitSet(i)) {
357 DexRegisterLocation a_loc = dex_register_locations_.Get(
358 a.dex_register_locations_start_index + index_in_dex_register_locations);
359 DexRegisterLocation b_loc = dex_register_locations_.Get(
360 b.dex_register_locations_start_index + index_in_dex_register_locations);
361 if (a_loc != b_loc) {
362 return false;
363 }
364 ++index_in_dex_register_locations;
365 }
366 }
367 return true;
368 }
369
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000370 ArenaAllocator* allocator_;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100371 GrowableArray<StackMapEntry> stack_maps_;
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000372 GrowableArray<DexRegisterLocation> dex_register_locations_;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100373 GrowableArray<InlineInfoEntry> inline_infos_;
374 int stack_mask_max_;
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000375 uint32_t dex_pc_max_;
376 uint32_t native_pc_offset_max_;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100377 size_t number_of_stack_maps_with_inline_info_;
378
Calin Juravle6ae70962015-03-18 16:31:28 +0000379 ArenaSafeMap<uint32_t, GrowableArray<uint32_t>> dex_map_hash_to_stack_map_indices_;
380
381 static constexpr uint32_t kNoSameDexMapFound = -1;
382
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000383 ART_FRIEND_TEST(StackMapTest, Test1);
384 ART_FRIEND_TEST(StackMapTest, Test2);
385 ART_FRIEND_TEST(StackMapTest, TestNonLiveDexRegisters);
386
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100387 DISALLOW_COPY_AND_ASSIGN(StackMapStream);
388};
389
390} // namespace art
391
392#endif // ART_COMPILER_OPTIMIZING_STACK_MAP_STREAM_H_