blob: 3974e53e6fe6494bfb68d7b31b17fce1a4119496 [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
20#include "base/bit_vector.h"
Ian Rogers0279ebb2014-10-08 17:27:48 -070021#include "base/value_object.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010022#include "memory_region.h"
23#include "stack_map.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010024#include "utils/growable_array.h"
25
26namespace art {
27
28/**
Nicolas Geoffray39468442014-09-02 15:17:15 +010029 * Collects and builds stack maps for a method. All the stack maps
30 * for a method are placed in a CodeInfo object.
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010031 */
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010032class 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),
Andreas Gampe8eddd2a2014-07-28 14:53:22 -070038 stack_mask_max_(-1),
39 number_of_stack_maps_with_inline_info_(0) {}
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010040
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;
Nicolas Geoffray39468442014-09-02 15:17:15 +010050 uint32_t native_pc_offset;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010051 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,
Nicolas Geoffray39468442014-09-02 15:17:15 +010069 uint32_t native_pc_offset,
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010070 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;
Nicolas Geoffray39468442014-09-02 15:17:15 +010076 entry.native_pc_offset = native_pc_offset;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010077 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
Nicolas Geoffray39468442014-09-02 15:17:15 +010085 if (sp_mask != nullptr) {
86 stack_mask_max_ = std::max(stack_mask_max_, sp_mask->GetHighestBitSet());
87 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010088 if (inlining_depth > 0) {
89 number_of_stack_maps_with_inline_info_++;
90 }
91 }
92
93 void AddDexRegisterEntry(DexRegisterMap::LocationKind kind, int32_t value) {
94 DexRegisterEntry entry;
95 entry.kind = kind;
96 entry.value = value;
97 dex_register_maps_.Add(entry);
98 }
99
100 void AddInlineInfoEntry(uint32_t method_index) {
101 InlineInfoEntry entry;
102 entry.method_index = method_index;
103 inline_infos_.Add(entry);
104 }
105
106 size_t ComputeNeededSize() const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100107 return CodeInfo::kFixedSize
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100108 + ComputeStackMapSize()
109 + ComputeDexRegisterMapSize()
110 + ComputeInlineInfoSize();
111 }
112
113 size_t ComputeStackMapSize() const {
Nicolas Geoffray376b2bb2014-12-09 14:26:32 +0000114 return stack_maps_.Size() * StackMap::ComputeAlignedStackMapSize(stack_mask_max_);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100115 }
116
117 size_t ComputeDexRegisterMapSize() const {
118 // We currently encode all dex register information per stack map.
119 return stack_maps_.Size() * DexRegisterMap::kFixedSize
120 // For each dex register entry.
121 + (dex_register_maps_.Size() * DexRegisterMap::SingleEntrySize());
122 }
123
124 size_t ComputeInlineInfoSize() const {
125 return inline_infos_.Size() * InlineInfo::SingleEntrySize()
126 // For encoding the depth.
127 + (number_of_stack_maps_with_inline_info_ * InlineInfo::kFixedSize);
128 }
129
130 size_t ComputeInlineInfoStart() const {
131 return ComputeDexRegisterMapStart() + ComputeDexRegisterMapSize();
132 }
133
134 size_t ComputeDexRegisterMapStart() const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100135 return CodeInfo::kFixedSize + ComputeStackMapSize();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100136 }
137
138 void FillIn(MemoryRegion region) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100139 CodeInfo code_info(region);
140 code_info.SetOverallSize(region.size());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100141
142 size_t stack_mask_size = StackMaskEncodingSize(stack_mask_max_);
143 uint8_t* memory_start = region.start();
144
145 MemoryRegion dex_register_maps_region = region.Subregion(
146 ComputeDexRegisterMapStart(),
147 ComputeDexRegisterMapSize());
148
149 MemoryRegion inline_infos_region = region.Subregion(
150 ComputeInlineInfoStart(),
151 ComputeInlineInfoSize());
152
153 code_info.SetNumberOfStackMaps(stack_maps_.Size());
154 code_info.SetStackMaskSize(stack_mask_size);
155
156 uintptr_t next_dex_register_map_offset = 0;
157 uintptr_t next_inline_info_offset = 0;
158 for (size_t i = 0, e = stack_maps_.Size(); i < e; ++i) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100159 StackMap stack_map = code_info.GetStackMapAt(i);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100160 StackMapEntry entry = stack_maps_.Get(i);
161
162 stack_map.SetDexPc(entry.dex_pc);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100163 stack_map.SetNativePcOffset(entry.native_pc_offset);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100164 stack_map.SetRegisterMask(entry.register_mask);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100165 if (entry.sp_mask != nullptr) {
166 stack_map.SetStackMask(*entry.sp_mask);
167 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100168
169 // Set the register map.
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800170 MemoryRegion register_region = dex_register_maps_region.Subregion(
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100171 next_dex_register_map_offset,
172 DexRegisterMap::kFixedSize + entry.num_dex_registers * DexRegisterMap::SingleEntrySize());
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800173 next_dex_register_map_offset += register_region.size();
174 DexRegisterMap dex_register_map(register_region);
175 stack_map.SetDexRegisterMapOffset(register_region.start() - memory_start);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100176
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800177 for (size_t j = 0; j < entry.num_dex_registers; ++j) {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100178 DexRegisterEntry register_entry =
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800179 dex_register_maps_.Get(j + entry.dex_register_maps_start_index);
180 dex_register_map.SetRegisterInfo(j, register_entry.kind, register_entry.value);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100181 }
182
183 // Set the inlining info.
184 if (entry.inlining_depth != 0) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800185 MemoryRegion inline_region = inline_infos_region.Subregion(
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100186 next_inline_info_offset,
187 InlineInfo::kFixedSize + entry.inlining_depth * InlineInfo::SingleEntrySize());
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800188 next_inline_info_offset += inline_region.size();
189 InlineInfo inline_info(inline_region);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100190
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800191 stack_map.SetInlineDescriptorOffset(inline_region.start() - memory_start);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100192
193 inline_info.SetDepth(entry.inlining_depth);
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800194 for (size_t j = 0; j < entry.inlining_depth; ++j) {
195 InlineInfoEntry inline_entry = inline_infos_.Get(j + entry.inline_infos_start_index);
196 inline_info.SetMethodReferenceIndexAtDepth(j, inline_entry.method_index);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100197 }
198 } else {
199 stack_map.SetInlineDescriptorOffset(InlineInfo::kNoInlineInfo);
200 }
201 }
202 }
203
204 private:
205 GrowableArray<StackMapEntry> stack_maps_;
206 GrowableArray<DexRegisterEntry> dex_register_maps_;
207 GrowableArray<InlineInfoEntry> inline_infos_;
208 int stack_mask_max_;
209 size_t number_of_stack_maps_with_inline_info_;
210
211 DISALLOW_COPY_AND_ASSIGN(StackMapStream);
212};
213
214} // namespace art
215
216#endif // ART_COMPILER_OPTIMIZING_STACK_MAP_STREAM_H_