blob: 7d3a48fd88d4b3fd5b17c6af3fa23d89a480bca0 [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_RUNTIME_STACK_MAP_H_
18#define ART_RUNTIME_STACK_MAP_H_
19
20#include "base/bit_vector.h"
21#include "memory_region.h"
22
23namespace art {
24
25/**
26 * Classes in the following file are wrapper on stack map information backed
27 * by a MemoryRegion. As such they read and write to the region, they don't have
28 * their own fields.
29 */
30
31/**
32 * Inline information for a specific PC. The information is of the form:
33 * [inlining_depth, [method_dex reference]+]
34 */
35class InlineInfo {
36 public:
37 explicit InlineInfo(MemoryRegion region) : region_(region) {}
38
39 uint8_t GetDepth() const {
40 return region_.Load<uint8_t>(kDepthOffset);
41 }
42
43 void SetDepth(uint8_t depth) {
44 region_.Store<uint8_t>(kDepthOffset, depth);
45 }
46
47 uint32_t GetMethodReferenceIndexAtDepth(uint8_t depth) const {
48 return region_.Load<uint32_t>(kFixedSize + depth * SingleEntrySize());
49 }
50
51 void SetMethodReferenceIndexAtDepth(uint8_t depth, uint32_t index) {
52 region_.Store<uint32_t>(kFixedSize + depth * SingleEntrySize(), index);
53 }
54
55 static size_t SingleEntrySize() {
56 return sizeof(uint32_t);
57 }
58
59 private:
60 static constexpr int kDepthOffset = 0;
61 static constexpr int kFixedSize = kDepthOffset + sizeof(uint8_t);
62
63 static constexpr uint32_t kNoInlineInfo = -1;
64
65 MemoryRegion region_;
66
67 template<typename T> friend class CodeInfo;
68 template<typename T> friend class StackMap;
69 template<typename T> friend class StackMapStream;
70};
71
72/**
73 * Information on dex register values for a specific PC. The information is
74 * of the form:
75 * [location_kind, register_value]+.
76 *
77 * The location_kind for a Dex register can either be:
78 * - Constant: register_value holds the constant,
79 * - Stack: register_value holds the stack offset,
80 * - Register: register_value holds the register number.
81 */
82class DexRegisterMap {
83 public:
84 explicit DexRegisterMap(MemoryRegion region) : region_(region) {}
85
86 enum LocationKind {
87 kInStack,
88 kInRegister,
89 kConstant
90 };
91
92 LocationKind GetLocationKind(uint16_t register_index) const {
93 return region_.Load<LocationKind>(
94 kFixedSize + register_index * SingleEntrySize());
95 }
96
97 void SetRegisterInfo(uint16_t register_index, LocationKind kind, int32_t value) {
98 size_t entry = kFixedSize + register_index * SingleEntrySize();
99 region_.Store<LocationKind>(entry, kind);
100 region_.Store<int32_t>(entry + sizeof(LocationKind), value);
101 }
102
103 int32_t GetValue(uint16_t register_index) const {
104 return region_.Load<int32_t>(
105 kFixedSize + sizeof(LocationKind) + register_index * SingleEntrySize());
106 }
107
108 static size_t SingleEntrySize() {
109 return sizeof(LocationKind) + sizeof(int32_t);
110 }
111
112 private:
113 static constexpr int kFixedSize = 0;
114
115 MemoryRegion region_;
116
117 template <typename T> friend class CodeInfo;
118 template <typename T> friend class StackMapStream;
119};
120
121/**
122 * A Stack Map holds compilation information for a specific PC necessary for:
123 * - Mapping it to a dex PC,
124 * - Knowing which stack entries are objects,
125 * - Knowing which registers hold objects,
126 * - Knowing the inlining information,
127 * - Knowing the values of dex registers.
128 *
129 * The information is of the form:
130 * [dex_pc, native_pc, dex_register_map_offset, inlining_info_offset, register_mask, stack_mask].
131 *
132 * Note that register_mask is fixed size, but stack_mask is variable size, depending on the
133 * stack size of a method.
134 */
135template <typename T>
136class StackMap {
137 public:
138 explicit StackMap(MemoryRegion region) : region_(region) {}
139
140 uint32_t GetDexPc() const {
141 return region_.Load<uint32_t>(kDexPcOffset);
142 }
143
144 void SetDexPc(uint32_t dex_pc) {
145 region_.Store<uint32_t>(kDexPcOffset, dex_pc);
146 }
147
148 T GetNativePc() const {
149 return region_.Load<T>(kNativePcOffset);
150 }
151
152 void SetNativePc(T native_pc) {
153 return region_.Store<T>(kNativePcOffset, native_pc);
154 }
155
156 uint32_t GetDexRegisterMapOffset() const {
157 return region_.Load<uint32_t>(kDexRegisterMapOffsetOffset);
158 }
159
160 void SetDexRegisterMapOffset(uint32_t offset) {
161 return region_.Store<uint32_t>(kDexRegisterMapOffsetOffset, offset);
162 }
163
164 uint32_t GetInlineDescriptorOffset() const {
165 return region_.Load<uint32_t>(kInlineDescriptorOffsetOffset);
166 }
167
168 void SetInlineDescriptorOffset(uint32_t offset) {
169 return region_.Store<uint32_t>(kInlineDescriptorOffsetOffset, offset);
170 }
171
172 uint32_t GetRegisterMask() const {
173 return region_.Load<uint32_t>(kRegisterMaskOffset);
174 }
175
176 void SetRegisterMask(uint32_t mask) {
177 region_.Store<uint32_t>(kRegisterMaskOffset, mask);
178 }
179
180 MemoryRegion GetStackMask() const {
181 return region_.Subregion(kStackMaskOffset, StackMaskSize());
182 }
183
184 void SetStackMask(const BitVector& sp_map) {
185 MemoryRegion region = GetStackMask();
186 for (size_t i = 0; i < region.size_in_bits(); i++) {
187 region.StoreBit(i, sp_map.IsBitSet(i));
188 }
189 }
190
191 bool HasInlineInfo() const {
192 return GetInlineDescriptorOffset() != InlineInfo::kNoInlineInfo;
193 }
194
195 bool Equals(const StackMap& other) {
196 return region_.pointer() == other.region_.pointer()
197 && region_.size() == other.region_.size();
198 }
199
200 private:
201 static constexpr int kDexPcOffset = 0;
202 static constexpr int kNativePcOffset = kDexPcOffset + sizeof(uint32_t);
203 static constexpr int kDexRegisterMapOffsetOffset = kNativePcOffset + sizeof(T);
204 static constexpr int kInlineDescriptorOffsetOffset =
205 kDexRegisterMapOffsetOffset + sizeof(uint32_t);
206 static constexpr int kRegisterMaskOffset = kInlineDescriptorOffsetOffset + sizeof(uint32_t);
207 static constexpr int kFixedSize = kRegisterMaskOffset + sizeof(uint32_t);
208 static constexpr int kStackMaskOffset = kFixedSize;
209
210 size_t StackMaskSize() const { return region_.size() - kFixedSize; }
211
212 MemoryRegion region_;
213
214 template <typename U> friend class CodeInfo;
215 template <typename U> friend class StackMapStream;
216};
217
218
219/**
220 * Wrapper around all compiler information collected for a method.
221 * The information is of the form:
222 * [number_of_stack_maps, stack_mask_size, StackMap+, DexRegisterInfo+, InlineInfo*].
223 */
224template <typename T>
225class CodeInfo {
226 public:
227 explicit CodeInfo(MemoryRegion region) : region_(region) {}
228
229 StackMap<T> GetStackMapAt(size_t i) const {
230 size_t size = StackMapSize();
231 return StackMap<T>(GetStackMaps().Subregion(i * size, size));
232 }
233
234 uint32_t GetStackMaskSize() const {
235 return region_.Load<uint32_t>(kStackMaskSizeOffset);
236 }
237
238 void SetStackMaskSize(uint32_t size) {
239 region_.Store<uint32_t>(kStackMaskSizeOffset, size);
240 }
241
242 size_t GetNumberOfStackMaps() const {
243 return region_.Load<uint32_t>(kNumberOfStackMapsOffset);
244 }
245
246 void SetNumberOfStackMaps(uint32_t number_of_stack_maps) {
247 region_.Store<uint32_t>(kNumberOfStackMapsOffset, number_of_stack_maps);
248 }
249
250 size_t StackMapSize() const {
251 return StackMap<T>::kFixedSize + GetStackMaskSize();
252 }
253
254 DexRegisterMap GetDexRegisterMapOf(StackMap<T> stack_map, uint32_t number_of_dex_registers) {
255 uint32_t offset = stack_map.GetDexRegisterMapOffset();
256 return DexRegisterMap(region_.Subregion(offset,
257 DexRegisterMap::kFixedSize + number_of_dex_registers * DexRegisterMap::SingleEntrySize()));
258 }
259
260 InlineInfo GetInlineInfoOf(StackMap<T> stack_map) {
261 uint32_t offset = stack_map.GetInlineDescriptorOffset();
262 uint8_t depth = region_.Load<uint8_t>(offset);
263 return InlineInfo(region_.Subregion(offset,
264 InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize()));
265 }
266
267 StackMap<T> GetStackMapForDexPc(uint32_t dex_pc) {
268 for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
269 StackMap<T> stack_map = GetStackMapAt(i);
270 if (stack_map.GetDexPc() == dex_pc) {
271 return stack_map;
272 }
273 }
274 LOG(FATAL) << "Unreachable";
275 return StackMap<T>(MemoryRegion());
276 }
277
278 StackMap<T> GetStackMapForNativePc(T native_pc) {
279 // TODO: stack maps are sorted by native pc, we can do a binary search.
280 for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
281 StackMap<T> stack_map = GetStackMapAt(i);
282 if (stack_map.GetNativePc() == native_pc) {
283 return stack_map;
284 }
285 }
286 LOG(FATAL) << "Unreachable";
287 return StackMap<T>(MemoryRegion());
288 }
289
290 private:
291 static constexpr int kNumberOfStackMapsOffset = 0;
292 static constexpr int kStackMaskSizeOffset = kNumberOfStackMapsOffset + sizeof(uint32_t);
293 static constexpr int kFixedSize = kStackMaskSizeOffset + sizeof(uint32_t);
294
295 MemoryRegion GetStackMaps() const {
296 return region_.size() == 0
297 ? MemoryRegion()
298 : region_.Subregion(kFixedSize, StackMapSize() * GetNumberOfStackMaps());
299 }
300
301 MemoryRegion region_;
302 template<typename U> friend class StackMapStream;
303};
304
305} // namespace art
306
307#endif // ART_RUNTIME_STACK_MAP_H_