blob: 0d3816b97e46faf52cd76d0af9b8d003febc5201 [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"
Vladimir Marko80afd022015-05-19 18:08:00 +010021#include "base/bit_utils.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010022#include "memory_region.h"
23
24namespace art {
25
Roland Levillain1c1da432015-07-16 11:54:44 +010026#define ELEMENT_BYTE_OFFSET_AFTER(PreviousElement) \
27 k ## PreviousElement ## Offset + sizeof(PreviousElement ## Type)
28
29#define ELEMENT_BIT_OFFSET_AFTER(PreviousElement) \
30 k ## PreviousElement ## BitOffset + PreviousElement ## BitSize
31
Vladimir Marko8f1e08a2015-06-26 12:06:30 +010032class VariableIndentationOutputStream;
33
Roland Levillaina2d8ec62015-03-12 15:25:29 +000034// Size of a frame slot, in bytes. This constant is a signed value,
35// to please the compiler in arithmetic operations involving int32_t
36// (signed) values.
Roland Levillaina552e1c2015-03-26 15:01:03 +000037static constexpr ssize_t kFrameSlotSize = 4;
Roland Levillaina2d8ec62015-03-12 15:25:29 +000038
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +000039// Size of Dex virtual registers.
Roland Levillaina552e1c2015-03-26 15:01:03 +000040static constexpr size_t kVRegSize = 4;
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +000041
Roland Levillaind780c002015-07-15 14:30:26 +010042// We encode the number of bytes needed for writing a value on 3 bits
43// (i.e. up to 8 values), for values that we know are maximum 32-bit
44// long.
45static constexpr size_t kNumberOfBitForNumberOfBytesForEncoding = 3;
46
Nicolas Geoffray004c2302015-03-20 10:06:38 +000047class CodeInfo;
David Brazdilf677ebf2015-05-29 16:29:43 +010048class StackMapEncoding;
Nicolas Geoffray004c2302015-03-20 10:06:38 +000049
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010050/**
51 * Classes in the following file are wrapper on stack map information backed
52 * by a MemoryRegion. As such they read and write to the region, they don't have
53 * their own fields.
54 */
55
Roland Levillaina2d8ec62015-03-12 15:25:29 +000056// Dex register location container used by DexRegisterMap and StackMapStream.
57class DexRegisterLocation {
58 public:
59 /*
60 * The location kind used to populate the Dex register information in a
61 * StackMapStream can either be:
62 * - kNone: the register has no location yet, meaning it has not been set;
63 * - kConstant: value holds the constant;
64 * - kStack: value holds the stack offset;
65 * - kRegister: value holds the physical register number;
66 * - kFpuRegister: value holds the physical register number.
67 *
68 * In addition, DexRegisterMap also uses these values:
69 * - kInStackLargeOffset: value holds a "large" stack offset (greater than
Roland Levillaina552e1c2015-03-26 15:01:03 +000070 * or equal to 128 bytes);
71 * - kConstantLargeValue: value holds a "large" constant (lower than 0, or
72 * or greater than or equal to 32).
Roland Levillaina2d8ec62015-03-12 15:25:29 +000073 */
74 enum class Kind : uint8_t {
75 // Short location kinds, for entries fitting on one byte (3 bits
76 // for the kind, 5 bits for the value) in a DexRegisterMap.
77 kNone = 0, // 0b000
78 kInStack = 1, // 0b001
79 kInRegister = 2, // 0b010
80 kInFpuRegister = 3, // 0b011
81 kConstant = 4, // 0b100
82
83 // Large location kinds, requiring a 5-byte encoding (1 byte for the
84 // kind, 4 bytes for the value).
85
86 // Stack location at a large offset, meaning that the offset value
87 // divided by the stack frame slot size (4 bytes) cannot fit on a
88 // 5-bit unsigned integer (i.e., this offset value is greater than
89 // or equal to 2^5 * 4 = 128 bytes).
90 kInStackLargeOffset = 5, // 0b101
91
92 // Large constant, that cannot fit on a 5-bit signed integer (i.e.,
Roland Levillaina552e1c2015-03-26 15:01:03 +000093 // lower than 0, or greater than or equal to 2^5 = 32).
Roland Levillaina2d8ec62015-03-12 15:25:29 +000094 kConstantLargeValue = 6, // 0b110
95
96 kLastLocationKind = kConstantLargeValue
97 };
98
99 static_assert(
100 sizeof(Kind) == 1u,
101 "art::DexRegisterLocation::Kind has a size different from one byte.");
102
103 static const char* PrettyDescriptor(Kind kind) {
104 switch (kind) {
105 case Kind::kNone:
106 return "none";
107 case Kind::kInStack:
108 return "in stack";
109 case Kind::kInRegister:
110 return "in register";
111 case Kind::kInFpuRegister:
112 return "in fpu register";
113 case Kind::kConstant:
114 return "as constant";
115 case Kind::kInStackLargeOffset:
116 return "in stack (large offset)";
117 case Kind::kConstantLargeValue:
118 return "as constant (large value)";
119 default:
120 UNREACHABLE();
121 }
122 }
123
124 static bool IsShortLocationKind(Kind kind) {
125 switch (kind) {
126 case Kind::kNone:
127 case Kind::kInStack:
128 case Kind::kInRegister:
129 case Kind::kInFpuRegister:
130 case Kind::kConstant:
131 return true;
132
133 case Kind::kInStackLargeOffset:
134 case Kind::kConstantLargeValue:
135 return false;
136
137 default:
138 UNREACHABLE();
139 }
140 }
141
142 // Convert `kind` to a "surface" kind, i.e. one that doesn't include
143 // any value with a "large" qualifier.
144 // TODO: Introduce another enum type for the surface kind?
145 static Kind ConvertToSurfaceKind(Kind kind) {
146 switch (kind) {
147 case Kind::kNone:
148 case Kind::kInStack:
149 case Kind::kInRegister:
150 case Kind::kInFpuRegister:
151 case Kind::kConstant:
152 return kind;
153
154 case Kind::kInStackLargeOffset:
155 return Kind::kInStack;
156
157 case Kind::kConstantLargeValue:
158 return Kind::kConstant;
159
160 default:
161 UNREACHABLE();
162 }
163 }
164
Roland Levillaina552e1c2015-03-26 15:01:03 +0000165 // Required by art::StackMapStream::LocationCatalogEntriesIndices.
166 DexRegisterLocation() : kind_(Kind::kNone), value_(0) {}
167
168 DexRegisterLocation(Kind kind, int32_t value) : kind_(kind), value_(value) {}
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000169
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000170 static DexRegisterLocation None() {
171 return DexRegisterLocation(Kind::kNone, 0);
172 }
173
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000174 // Get the "surface" kind of the location, i.e., the one that doesn't
175 // include any value with a "large" qualifier.
176 Kind GetKind() const {
177 return ConvertToSurfaceKind(kind_);
178 }
179
180 // Get the value of the location.
181 int32_t GetValue() const { return value_; }
182
183 // Get the actual kind of the location.
184 Kind GetInternalKind() const { return kind_; }
185
Calin Juravle6ae70962015-03-18 16:31:28 +0000186 bool operator==(DexRegisterLocation other) const {
187 return kind_ == other.kind_ && value_ == other.value_;
188 }
189
190 bool operator!=(DexRegisterLocation other) const {
191 return !(*this == other);
192 }
193
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000194 private:
195 Kind kind_;
196 int32_t value_;
Roland Levillaina552e1c2015-03-26 15:01:03 +0000197
198 friend class DexRegisterLocationHashFn;
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000199};
200
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100201/**
Roland Levillaina552e1c2015-03-26 15:01:03 +0000202 * Store information on unique Dex register locations used in a method.
203 * The information is of the form:
Roland Levillain1c1da432015-07-16 11:54:44 +0100204 *
205 * [DexRegisterLocation+].
206 *
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000207 * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind).
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100208 */
Roland Levillaina552e1c2015-03-26 15:01:03 +0000209class DexRegisterLocationCatalog {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100210 public:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000211 explicit DexRegisterLocationCatalog(MemoryRegion region) : region_(region) {}
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100212
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000213 // Short (compressed) location, fitting on one byte.
214 typedef uint8_t ShortLocation;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100215
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000216 void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) {
217 DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location);
218 int32_t value = dex_register_location.GetValue();
219 if (DexRegisterLocation::IsShortLocationKind(kind)) {
220 // Short location. Compress the kind and the value as a single byte.
221 if (kind == DexRegisterLocation::Kind::kInStack) {
222 // Instead of storing stack offsets expressed in bytes for
223 // short stack locations, store slot offsets. A stack offset
224 // is a multiple of 4 (kFrameSlotSize). This means that by
225 // dividing it by 4, we can fit values from the [0, 128)
226 // interval in a short stack location, and not just values
227 // from the [0, 32) interval.
228 DCHECK_EQ(value % kFrameSlotSize, 0);
229 value /= kFrameSlotSize;
230 }
Roland Levillaina552e1c2015-03-26 15:01:03 +0000231 DCHECK(IsShortValue(value)) << value;
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000232 region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value));
233 } else {
234 // Large location. Write the location on one byte and the value
235 // on 4 bytes.
Roland Levillaina552e1c2015-03-26 15:01:03 +0000236 DCHECK(!IsShortValue(value)) << value;
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000237 if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
238 // Also divide large stack offsets by 4 for the sake of consistency.
239 DCHECK_EQ(value % kFrameSlotSize, 0);
240 value /= kFrameSlotSize;
241 }
242 // Data can be unaligned as the written Dex register locations can
243 // either be 1-byte or 5-byte wide. Use
244 // art::MemoryRegion::StoreUnaligned instead of
245 // art::MemoryRegion::Store to prevent unligned word accesses on ARM.
246 region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind);
247 region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value);
Roland Levillain442b46a2015-02-18 16:54:21 +0000248 }
249 }
250
Roland Levillaina552e1c2015-03-26 15:01:03 +0000251 // Find the offset of the location catalog entry number `location_catalog_entry_index`.
252 size_t FindLocationOffset(size_t location_catalog_entry_index) const {
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000253 size_t offset = kFixedSize;
Roland Levillaina552e1c2015-03-26 15:01:03 +0000254 // Skip the first `location_catalog_entry_index - 1` entries.
255 for (uint16_t i = 0; i < location_catalog_entry_index; ++i) {
256 // Read the first next byte and inspect its first 3 bits to decide
257 // whether it is a short or a large location.
258 DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
259 if (DexRegisterLocation::IsShortLocationKind(kind)) {
260 // Short location. Skip the current byte.
261 offset += SingleShortEntrySize();
262 } else {
263 // Large location. Skip the 5 next bytes.
264 offset += SingleLargeEntrySize();
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000265 }
266 }
267 return offset;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100268 }
269
Roland Levillaina552e1c2015-03-26 15:01:03 +0000270 // Get the internal kind of entry at `location_catalog_entry_index`.
271 DexRegisterLocation::Kind GetLocationInternalKind(size_t location_catalog_entry_index) const {
272 if (location_catalog_entry_index == kNoLocationEntryIndex) {
273 return DexRegisterLocation::Kind::kNone;
274 }
275 return ExtractKindAtOffset(FindLocationOffset(location_catalog_entry_index));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100276 }
277
Roland Levillaina552e1c2015-03-26 15:01:03 +0000278 // Get the (surface) kind and value of entry at `location_catalog_entry_index`.
279 DexRegisterLocation GetDexRegisterLocation(size_t location_catalog_entry_index) const {
280 if (location_catalog_entry_index == kNoLocationEntryIndex) {
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000281 return DexRegisterLocation::None();
282 }
Roland Levillaina552e1c2015-03-26 15:01:03 +0000283 size_t offset = FindLocationOffset(location_catalog_entry_index);
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000284 // Read the first byte and inspect its first 3 bits to get the location.
285 ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
286 DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte);
287 if (DexRegisterLocation::IsShortLocationKind(kind)) {
288 // Short location. Extract the value from the remaining 5 bits.
289 int32_t value = ExtractValueFromShortLocation(first_byte);
290 if (kind == DexRegisterLocation::Kind::kInStack) {
291 // Convert the stack slot (short) offset to a byte offset value.
292 value *= kFrameSlotSize;
293 }
294 return DexRegisterLocation(kind, value);
295 } else {
296 // Large location. Read the four next bytes to get the value.
297 int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind));
298 if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
299 // Convert the stack slot (large) offset to a byte offset value.
300 value *= kFrameSlotSize;
301 }
302 return DexRegisterLocation(kind, value);
303 }
Sebastien Hertz7cde48c2015-01-20 16:06:43 +0100304 }
305
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000306 // Compute the compressed kind of `location`.
307 static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) {
308 switch (location.GetInternalKind()) {
309 case DexRegisterLocation::Kind::kNone:
310 DCHECK_EQ(location.GetValue(), 0);
311 return DexRegisterLocation::Kind::kNone;
312
313 case DexRegisterLocation::Kind::kInRegister:
314 DCHECK_GE(location.GetValue(), 0);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000315 DCHECK_LT(location.GetValue(), 1 << kValueBits);
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000316 return DexRegisterLocation::Kind::kInRegister;
317
318 case DexRegisterLocation::Kind::kInFpuRegister:
319 DCHECK_GE(location.GetValue(), 0);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000320 DCHECK_LT(location.GetValue(), 1 << kValueBits);
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000321 return DexRegisterLocation::Kind::kInFpuRegister;
322
323 case DexRegisterLocation::Kind::kInStack:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000324 return IsShortStackOffsetValue(location.GetValue())
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000325 ? DexRegisterLocation::Kind::kInStack
326 : DexRegisterLocation::Kind::kInStackLargeOffset;
327
328 case DexRegisterLocation::Kind::kConstant:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000329 return IsShortConstantValue(location.GetValue())
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000330 ? DexRegisterLocation::Kind::kConstant
331 : DexRegisterLocation::Kind::kConstantLargeValue;
332
333 default:
334 LOG(FATAL) << "Unexpected location kind"
335 << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
336 UNREACHABLE();
337 }
338 }
339
340 // Can `location` be turned into a short location?
341 static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) {
342 switch (location.GetInternalKind()) {
343 case DexRegisterLocation::Kind::kNone:
344 case DexRegisterLocation::Kind::kInRegister:
345 case DexRegisterLocation::Kind::kInFpuRegister:
346 return true;
347
348 case DexRegisterLocation::Kind::kInStack:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000349 return IsShortStackOffsetValue(location.GetValue());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000350
351 case DexRegisterLocation::Kind::kConstant:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000352 return IsShortConstantValue(location.GetValue());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000353
354 default:
355 UNREACHABLE();
356 }
357 }
358
359 static size_t EntrySize(const DexRegisterLocation& location) {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000360 return CanBeEncodedAsShortLocation(location) ? SingleShortEntrySize() : SingleLargeEntrySize();
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000361 }
362
363 static size_t SingleShortEntrySize() {
364 return sizeof(ShortLocation);
365 }
366
367 static size_t SingleLargeEntrySize() {
368 return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100369 }
370
Roland Levillain12baf472015-03-05 12:41:42 +0000371 size_t Size() const {
372 return region_.size();
373 }
374
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100375 void Dump(VariableIndentationOutputStream* vios, const CodeInfo& code_info);
Roland Levillain0396ed72015-05-27 15:12:19 +0100376
Roland Levillaina552e1c2015-03-26 15:01:03 +0000377 // Special (invalid) Dex register location catalog entry index meaning
378 // that there is no location for a given Dex register (i.e., it is
379 // mapped to a DexRegisterLocation::Kind::kNone location).
380 static constexpr size_t kNoLocationEntryIndex = -1;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100381
Roland Levillain12baf472015-03-05 12:41:42 +0000382 private:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000383 static constexpr int kFixedSize = 0;
384
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000385 // Width of the kind "field" in a short location, in bits.
386 static constexpr size_t kKindBits = 3;
387 // Width of the value "field" in a short location, in bits.
388 static constexpr size_t kValueBits = 5;
389
390 static constexpr uint8_t kKindMask = (1 << kKindBits) - 1;
391 static constexpr int32_t kValueMask = (1 << kValueBits) - 1;
392 static constexpr size_t kKindOffset = 0;
393 static constexpr size_t kValueOffset = kKindBits;
394
Roland Levillaina552e1c2015-03-26 15:01:03 +0000395 static bool IsShortStackOffsetValue(int32_t value) {
396 DCHECK_EQ(value % kFrameSlotSize, 0);
397 return IsShortValue(value / kFrameSlotSize);
398 }
399
400 static bool IsShortConstantValue(int32_t value) {
401 return IsShortValue(value);
402 }
403
404 static bool IsShortValue(int32_t value) {
405 return IsUint<kValueBits>(value);
406 }
407
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000408 static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000409 uint8_t kind_integer_value = static_cast<uint8_t>(kind);
410 DCHECK(IsUint<kKindBits>(kind_integer_value)) << kind_integer_value;
411 DCHECK(IsShortValue(value)) << value;
412 return (kind_integer_value & kKindMask) << kKindOffset
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000413 | (value & kValueMask) << kValueOffset;
414 }
415
416 static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) {
417 uint8_t kind = (location >> kKindOffset) & kKindMask;
418 DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind));
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000419 // We do not encode kNone locations in the stack map.
420 DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone));
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000421 return static_cast<DexRegisterLocation::Kind>(kind);
422 }
423
424 static int32_t ExtractValueFromShortLocation(ShortLocation location) {
425 return (location >> kValueOffset) & kValueMask;
426 }
427
428 // Extract a location kind from the byte at position `offset`.
429 DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const {
430 ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
431 return ExtractKindFromShortLocation(first_byte);
432 }
433
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100434 MemoryRegion region_;
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000435
436 friend class CodeInfo;
437 friend class StackMapStream;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100438};
439
Roland Levillaina552e1c2015-03-26 15:01:03 +0000440/* Information on Dex register locations for a specific PC, mapping a
441 * stack map's Dex register to a location entry in a DexRegisterLocationCatalog.
442 * The information is of the form:
Roland Levillain1c1da432015-07-16 11:54:44 +0100443 *
444 * [live_bit_mask, entries*]
445 *
Roland Levillaina552e1c2015-03-26 15:01:03 +0000446 * where entries are concatenated unsigned integer values encoded on a number
447 * of bits (fixed per DexRegisterMap instances of a CodeInfo object) depending
448 * on the number of entries in the Dex register location catalog
449 * (see DexRegisterMap::SingleEntrySizeInBits). The map is 1-byte aligned.
450 */
451class DexRegisterMap {
452 public:
453 explicit DexRegisterMap(MemoryRegion region) : region_(region) {}
454
455 // Get the surface kind of Dex register `dex_register_number`.
456 DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number,
457 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100458 const CodeInfo& code_info,
459 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000460 return DexRegisterLocation::ConvertToSurfaceKind(
David Brazdilf677ebf2015-05-29 16:29:43 +0100461 GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info, enc));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000462 }
463
464 // Get the internal kind of Dex register `dex_register_number`.
465 DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number,
466 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100467 const CodeInfo& code_info,
468 const StackMapEncoding& enc) const;
Roland Levillaina552e1c2015-03-26 15:01:03 +0000469
470 // Get the Dex register location `dex_register_number`.
471 DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number,
472 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100473 const CodeInfo& code_info,
474 const StackMapEncoding& enc) const;
Roland Levillaina552e1c2015-03-26 15:01:03 +0000475
476 int32_t GetStackOffsetInBytes(uint16_t dex_register_number,
477 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100478 const CodeInfo& code_info,
479 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000480 DexRegisterLocation location =
David Brazdilf677ebf2015-05-29 16:29:43 +0100481 GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000482 DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
483 // GetDexRegisterLocation returns the offset in bytes.
484 return location.GetValue();
485 }
486
487 int32_t GetConstant(uint16_t dex_register_number,
488 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100489 const CodeInfo& code_info,
490 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000491 DexRegisterLocation location =
David Brazdilf677ebf2015-05-29 16:29:43 +0100492 GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100493 DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant)
494 << DexRegisterLocation::PrettyDescriptor(location.GetKind());
Roland Levillaina552e1c2015-03-26 15:01:03 +0000495 return location.GetValue();
496 }
497
498 int32_t GetMachineRegister(uint16_t dex_register_number,
499 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100500 const CodeInfo& code_info,
501 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000502 DexRegisterLocation location =
David Brazdilf677ebf2015-05-29 16:29:43 +0100503 GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000504 DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister
505 || location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister)
506 << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
507 return location.GetValue();
508 }
509
510 // Get the index of the entry in the Dex register location catalog
511 // corresponding to `dex_register_number`.
512 size_t GetLocationCatalogEntryIndex(uint16_t dex_register_number,
513 uint16_t number_of_dex_registers,
514 size_t number_of_location_catalog_entries) const {
515 if (!IsDexRegisterLive(dex_register_number)) {
516 return DexRegisterLocationCatalog::kNoLocationEntryIndex;
517 }
518
519 if (number_of_location_catalog_entries == 1) {
520 // We do not allocate space for location maps in the case of a
521 // single-entry location catalog, as it is useless. The only valid
522 // entry index is 0;
523 return 0;
524 }
525
526 // The bit offset of the beginning of the map locations.
527 size_t map_locations_offset_in_bits =
528 GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
529 size_t index_in_dex_register_map = GetIndexInDexRegisterMap(dex_register_number);
530 DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
531 // The bit size of an entry.
532 size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
533 // The bit offset where `index_in_dex_register_map` is located.
534 size_t entry_offset_in_bits =
535 map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
536 size_t location_catalog_entry_index =
537 region_.LoadBits(entry_offset_in_bits, map_entry_size_in_bits);
538 DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
539 return location_catalog_entry_index;
540 }
541
542 // Map entry at `index_in_dex_register_map` to `location_catalog_entry_index`.
543 void SetLocationCatalogEntryIndex(size_t index_in_dex_register_map,
544 size_t location_catalog_entry_index,
545 uint16_t number_of_dex_registers,
546 size_t number_of_location_catalog_entries) {
547 DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
548 DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
549
550 if (number_of_location_catalog_entries == 1) {
551 // We do not allocate space for location maps in the case of a
552 // single-entry location catalog, as it is useless.
553 return;
554 }
555
556 // The bit offset of the beginning of the map locations.
557 size_t map_locations_offset_in_bits =
558 GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
559 // The bit size of an entry.
560 size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
561 // The bit offset where `index_in_dex_register_map` is located.
562 size_t entry_offset_in_bits =
563 map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
564 region_.StoreBits(entry_offset_in_bits, location_catalog_entry_index, map_entry_size_in_bits);
565 }
566
567 void SetLiveBitMask(uint16_t number_of_dex_registers,
568 const BitVector& live_dex_registers_mask) {
569 size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
570 for (uint16_t i = 0; i < number_of_dex_registers; ++i) {
571 region_.StoreBit(live_bit_mask_offset_in_bits + i, live_dex_registers_mask.IsBitSet(i));
572 }
573 }
574
575 bool IsDexRegisterLive(uint16_t dex_register_number) const {
576 size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
577 return region_.LoadBit(live_bit_mask_offset_in_bits + dex_register_number);
578 }
579
580 size_t GetNumberOfLiveDexRegisters(uint16_t number_of_dex_registers) const {
581 size_t number_of_live_dex_registers = 0;
582 for (size_t i = 0; i < number_of_dex_registers; ++i) {
583 if (IsDexRegisterLive(i)) {
584 ++number_of_live_dex_registers;
585 }
586 }
587 return number_of_live_dex_registers;
588 }
589
590 static size_t GetLiveBitMaskOffset() {
591 return kFixedSize;
592 }
593
594 // Compute the size of the live register bit mask (in bytes), for a
595 // method having `number_of_dex_registers` Dex registers.
596 static size_t GetLiveBitMaskSize(uint16_t number_of_dex_registers) {
597 return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte;
598 }
599
600 static size_t GetLocationMappingDataOffset(uint16_t number_of_dex_registers) {
601 return GetLiveBitMaskOffset() + GetLiveBitMaskSize(number_of_dex_registers);
602 }
603
604 size_t GetLocationMappingDataSize(uint16_t number_of_dex_registers,
605 size_t number_of_location_catalog_entries) const {
606 size_t location_mapping_data_size_in_bits =
607 GetNumberOfLiveDexRegisters(number_of_dex_registers)
608 * SingleEntrySizeInBits(number_of_location_catalog_entries);
609 return RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
610 }
611
612 // Return the size of a map entry in bits. Note that if
613 // `number_of_location_catalog_entries` equals 1, this function returns 0,
614 // which is fine, as there is no need to allocate a map for a
615 // single-entry location catalog; the only valid location catalog entry index
616 // for a live register in this case is 0 and there is no need to
617 // store it.
618 static size_t SingleEntrySizeInBits(size_t number_of_location_catalog_entries) {
619 // Handle the case of 0, as we cannot pass 0 to art::WhichPowerOf2.
620 return number_of_location_catalog_entries == 0
621 ? 0u
622 : WhichPowerOf2(RoundUpToPowerOfTwo(number_of_location_catalog_entries));
623 }
624
625 // Return the size of the DexRegisterMap object, in bytes.
626 size_t Size() const {
627 return region_.size();
628 }
629
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100630 void Dump(VariableIndentationOutputStream* vios,
631 const CodeInfo& code_info, uint16_t number_of_dex_registers) const;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100632
Roland Levillaina552e1c2015-03-26 15:01:03 +0000633 private:
634 // Return the index in the Dex register map corresponding to the Dex
635 // register number `dex_register_number`.
636 size_t GetIndexInDexRegisterMap(uint16_t dex_register_number) const {
637 if (!IsDexRegisterLive(dex_register_number)) {
638 return kInvalidIndexInDexRegisterMap;
639 }
640 return GetNumberOfLiveDexRegisters(dex_register_number);
641 }
642
643 // Special (invalid) Dex register map entry index meaning that there
644 // is no index in the map for a given Dex register (i.e., it must
645 // have been mapped to a DexRegisterLocation::Kind::kNone location).
646 static constexpr size_t kInvalidIndexInDexRegisterMap = -1;
647
648 static constexpr int kFixedSize = 0;
649
650 MemoryRegion region_;
651
652 friend class CodeInfo;
653 friend class StackMapStream;
654};
655
David Brazdilf677ebf2015-05-29 16:29:43 +0100656class StackMapEncoding {
657 public:
658 StackMapEncoding() {}
659
660 StackMapEncoding(size_t stack_mask_size,
661 size_t bytes_for_inline_info,
662 size_t bytes_for_dex_register_map,
663 size_t bytes_for_dex_pc,
664 size_t bytes_for_native_pc,
665 size_t bytes_for_register_mask)
666 : bytes_for_stack_mask_(stack_mask_size),
667 bytes_for_inline_info_(bytes_for_inline_info),
668 bytes_for_dex_register_map_(bytes_for_dex_register_map),
669 bytes_for_dex_pc_(bytes_for_dex_pc),
670 bytes_for_native_pc_(bytes_for_native_pc),
671 bytes_for_register_mask_(bytes_for_register_mask) {}
672
673 static StackMapEncoding CreateFromSizes(size_t stack_mask_size,
674 size_t inline_info_size,
675 size_t dex_register_map_size,
676 size_t dex_pc_max,
677 size_t native_pc_max,
678 size_t register_mask_max) {
679 return StackMapEncoding(
680 stack_mask_size,
681 // + 1 to also encode kNoInlineInfo: if an inline info offset
682 // is at 0xFF, we want to overflow to a larger encoding, because it will
683 // conflict with kNoInlineInfo.
684 // The offset is relative to the dex register map. TODO: Change this.
685 inline_info_size == 0
686 ? 0
687 : EncodingSizeInBytes(dex_register_map_size + inline_info_size + 1),
688 // + 1 to also encode kNoDexRegisterMap: if a dex register map offset
689 // is at 0xFF, we want to overflow to a larger encoding, because it will
690 // conflict with kNoDexRegisterMap.
691 EncodingSizeInBytes(dex_register_map_size + 1),
692 EncodingSizeInBytes(dex_pc_max),
693 EncodingSizeInBytes(native_pc_max),
694 EncodingSizeInBytes(register_mask_max));
695 }
696
697 // Get the size of one stack map of this CodeInfo object, in bytes.
698 // All stack maps of a CodeInfo have the same size.
699 size_t ComputeStackMapSize() const {
700 return bytes_for_register_mask_
701 + bytes_for_stack_mask_
702 + bytes_for_inline_info_
703 + bytes_for_dex_register_map_
704 + bytes_for_dex_pc_
705 + bytes_for_native_pc_;
706 }
707
708 bool HasInlineInfo() const { return bytes_for_inline_info_ > 0; }
709
710 size_t NumberOfBytesForStackMask() const { return bytes_for_stack_mask_; }
711 size_t NumberOfBytesForInlineInfo() const { return bytes_for_inline_info_; }
712 size_t NumberOfBytesForDexRegisterMap() const { return bytes_for_dex_register_map_; }
713 size_t NumberOfBytesForDexPc() const { return bytes_for_dex_pc_; }
714 size_t NumberOfBytesForNativePc() const { return bytes_for_native_pc_; }
715 size_t NumberOfBytesForRegisterMask() const { return bytes_for_register_mask_; }
716
717 size_t ComputeStackMapRegisterMaskOffset() const {
718 return kRegisterMaskOffset;
719 }
720
721 size_t ComputeStackMapStackMaskOffset() const {
722 return ComputeStackMapRegisterMaskOffset() + bytes_for_register_mask_;
723 }
724
725 size_t ComputeStackMapDexPcOffset() const {
726 return ComputeStackMapStackMaskOffset() + bytes_for_stack_mask_;
727 }
728
729 size_t ComputeStackMapNativePcOffset() const {
730 return ComputeStackMapDexPcOffset() + bytes_for_dex_pc_;
731 }
732
733 size_t ComputeStackMapDexRegisterMapOffset() const {
734 return ComputeStackMapNativePcOffset() + bytes_for_native_pc_;
735 }
736
737 size_t ComputeStackMapInlineInfoOffset() const {
738 return ComputeStackMapDexRegisterMapOffset() + bytes_for_dex_register_map_;
739 }
740
741 private:
742 static size_t EncodingSizeInBytes(size_t max_element) {
743 DCHECK(IsUint<32>(max_element));
744 return (max_element == 0) ? 0
745 : IsUint<8>(max_element) ? 1
746 : IsUint<16>(max_element) ? 2
747 : IsUint<24>(max_element) ? 3
748 : 4;
749 }
750
751 static constexpr int kRegisterMaskOffset = 0;
752
753 size_t bytes_for_stack_mask_;
754 size_t bytes_for_inline_info_;
755 size_t bytes_for_dex_register_map_;
756 size_t bytes_for_dex_pc_;
757 size_t bytes_for_native_pc_;
758 size_t bytes_for_register_mask_;
759};
760
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100761/**
762 * A Stack Map holds compilation information for a specific PC necessary for:
763 * - Mapping it to a dex PC,
764 * - Knowing which stack entries are objects,
765 * - Knowing which registers hold objects,
766 * - Knowing the inlining information,
767 * - Knowing the values of dex registers.
768 *
769 * The information is of the form:
Roland Levillain1c1da432015-07-16 11:54:44 +0100770 *
771 * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask,
772 * stack_mask].
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100773 */
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100774class StackMap {
775 public:
Nicolas Geoffraye12997f2015-05-22 14:01:33 +0100776 StackMap() {}
David Brazdilf677ebf2015-05-29 16:29:43 +0100777 explicit StackMap(MemoryRegion region) : region_(region) {}
Nicolas Geoffraye12997f2015-05-22 14:01:33 +0100778
779 bool IsValid() const { return region_.pointer() != nullptr; }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100780
David Brazdilf677ebf2015-05-29 16:29:43 +0100781 uint32_t GetDexPc(const StackMapEncoding& encoding) const {
782 return LoadAt(encoding.NumberOfBytesForDexPc(), encoding.ComputeStackMapDexPcOffset());
783 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100784
David Brazdilf677ebf2015-05-29 16:29:43 +0100785 void SetDexPc(const StackMapEncoding& encoding, uint32_t dex_pc) {
786 StoreAt(encoding.NumberOfBytesForDexPc(), encoding.ComputeStackMapDexPcOffset(), dex_pc);
787 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100788
David Brazdilf677ebf2015-05-29 16:29:43 +0100789 uint32_t GetNativePcOffset(const StackMapEncoding& encoding) const {
790 return LoadAt(encoding.NumberOfBytesForNativePc(), encoding.ComputeStackMapNativePcOffset());
791 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100792
David Brazdilf677ebf2015-05-29 16:29:43 +0100793 void SetNativePcOffset(const StackMapEncoding& encoding, uint32_t native_pc_offset) {
794 StoreAt(encoding.NumberOfBytesForNativePc(),
795 encoding.ComputeStackMapNativePcOffset(),
796 native_pc_offset);
797 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100798
David Brazdilf677ebf2015-05-29 16:29:43 +0100799 uint32_t GetDexRegisterMapOffset(const StackMapEncoding& encoding) const {
800 return LoadAt(encoding.NumberOfBytesForDexRegisterMap(),
801 encoding.ComputeStackMapDexRegisterMapOffset(),
802 /* check_max */ true);
803 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100804
David Brazdilf677ebf2015-05-29 16:29:43 +0100805 void SetDexRegisterMapOffset(const StackMapEncoding& encoding, uint32_t offset) {
806 StoreAt(encoding.NumberOfBytesForDexRegisterMap(),
807 encoding.ComputeStackMapDexRegisterMapOffset(),
808 offset);
809 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100810
David Brazdilf677ebf2015-05-29 16:29:43 +0100811 uint32_t GetInlineDescriptorOffset(const StackMapEncoding& encoding) const {
812 if (!encoding.HasInlineInfo()) return kNoInlineInfo;
813 return LoadAt(encoding.NumberOfBytesForInlineInfo(),
814 encoding.ComputeStackMapInlineInfoOffset(),
815 /* check_max */ true);
816 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100817
David Brazdilf677ebf2015-05-29 16:29:43 +0100818 void SetInlineDescriptorOffset(const StackMapEncoding& encoding, uint32_t offset) {
819 DCHECK(encoding.HasInlineInfo());
820 StoreAt(encoding.NumberOfBytesForInlineInfo(),
821 encoding.ComputeStackMapInlineInfoOffset(),
822 offset);
823 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100824
David Brazdilf677ebf2015-05-29 16:29:43 +0100825 uint32_t GetRegisterMask(const StackMapEncoding& encoding) const {
826 return LoadAt(encoding.NumberOfBytesForRegisterMask(),
827 encoding.ComputeStackMapRegisterMaskOffset());
828 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100829
David Brazdilf677ebf2015-05-29 16:29:43 +0100830 void SetRegisterMask(const StackMapEncoding& encoding, uint32_t mask) {
831 StoreAt(encoding.NumberOfBytesForRegisterMask(),
832 encoding.ComputeStackMapRegisterMaskOffset(),
833 mask);
834 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100835
David Brazdilf677ebf2015-05-29 16:29:43 +0100836 MemoryRegion GetStackMask(const StackMapEncoding& encoding) const {
837 return region_.Subregion(encoding.ComputeStackMapStackMaskOffset(),
838 encoding.NumberOfBytesForStackMask());
839 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100840
David Brazdilf677ebf2015-05-29 16:29:43 +0100841 void SetStackMask(const StackMapEncoding& encoding, const BitVector& sp_map) {
842 MemoryRegion region = GetStackMask(encoding);
David Brazdilf10a25f2015-06-02 14:29:52 +0100843 sp_map.CopyTo(region.start(), region.size());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100844 }
845
David Brazdilf677ebf2015-05-29 16:29:43 +0100846 bool HasDexRegisterMap(const StackMapEncoding& encoding) const {
847 return GetDexRegisterMapOffset(encoding) != kNoDexRegisterMap;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100848 }
849
David Brazdilf677ebf2015-05-29 16:29:43 +0100850 bool HasInlineInfo(const StackMapEncoding& encoding) const {
851 return GetInlineDescriptorOffset(encoding) != kNoInlineInfo;
Roland Levillain442b46a2015-02-18 16:54:21 +0000852 }
853
854 bool Equals(const StackMap& other) const {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100855 return region_.pointer() == other.region_.pointer()
856 && region_.size() == other.region_.size();
857 }
858
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100859 void Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +0100860 const CodeInfo& code_info,
David Brazdilf677ebf2015-05-29 16:29:43 +0100861 const StackMapEncoding& encoding,
Roland Levillainf2650d12015-05-28 14:53:28 +0100862 uint32_t code_offset,
863 uint16_t number_of_dex_registers,
864 const std::string& header_suffix = "") const;
865
Roland Levillain442b46a2015-02-18 16:54:21 +0000866 // Special (invalid) offset for the DexRegisterMapOffset field meaning
867 // that there is no Dex register map for this stack map.
868 static constexpr uint32_t kNoDexRegisterMap = -1;
869
870 // Special (invalid) offset for the InlineDescriptorOffset field meaning
871 // that there is no inline info for this stack map.
872 static constexpr uint32_t kNoInlineInfo = -1;
873
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100874 private:
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100875 static constexpr int kFixedSize = 0;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100876
David Brazdilf677ebf2015-05-29 16:29:43 +0100877 // Loads `number_of_bytes` at the given `offset` and assemble a uint32_t. If `check_max` is true,
878 // this method converts a maximum value of size `number_of_bytes` into a uint32_t 0xFFFFFFFF.
879 uint32_t LoadAt(size_t number_of_bytes, size_t offset, bool check_max = false) const;
880 void StoreAt(size_t number_of_bytes, size_t offset, uint32_t value) const;
881
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100882 MemoryRegion region_;
883
Nicolas Geoffray39468442014-09-02 15:17:15 +0100884 friend class StackMapStream;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100885};
886
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100887/**
888 * Inline information for a specific PC. The information is of the form:
Roland Levillain1c1da432015-07-16 11:54:44 +0100889 *
890 * [inlining_depth, entry+]
891 *
892 * where `entry` is of the form:
893 *
894 * [dex_pc, method_index, dex_register_map_offset].
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100895 */
896class InlineInfo {
897 public:
Roland Levillain1c1da432015-07-16 11:54:44 +0100898 // Memory layout: fixed contents.
899 typedef uint8_t DepthType;
900 // Memory layout: single entry contents.
901 typedef uint32_t MethodIndexType;
902 typedef uint32_t DexPcType;
903 typedef uint8_t InvokeTypeType;
904 typedef uint32_t DexRegisterMapType;
905
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100906 explicit InlineInfo(MemoryRegion region) : region_(region) {}
907
Roland Levillain1c1da432015-07-16 11:54:44 +0100908 DepthType GetDepth() const {
909 return region_.LoadUnaligned<DepthType>(kDepthOffset);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100910 }
911
Roland Levillain1c1da432015-07-16 11:54:44 +0100912 void SetDepth(DepthType depth) {
913 region_.StoreUnaligned<DepthType>(kDepthOffset, depth);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100914 }
915
Roland Levillain1c1da432015-07-16 11:54:44 +0100916 MethodIndexType GetMethodIndexAtDepth(DepthType depth) const {
917 return region_.LoadUnaligned<MethodIndexType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100918 kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100919 }
920
Roland Levillain1c1da432015-07-16 11:54:44 +0100921 void SetMethodIndexAtDepth(DepthType depth, MethodIndexType index) {
922 region_.StoreUnaligned<MethodIndexType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100923 kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset, index);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100924 }
925
Roland Levillain1c1da432015-07-16 11:54:44 +0100926 DexPcType GetDexPcAtDepth(DepthType depth) const {
927 return region_.LoadUnaligned<DexPcType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100928 kFixedSize + depth * SingleEntrySize() + kDexPcOffset);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100929 }
930
Roland Levillain1c1da432015-07-16 11:54:44 +0100931 void SetDexPcAtDepth(DepthType depth, DexPcType dex_pc) {
932 region_.StoreUnaligned<DexPcType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100933 kFixedSize + depth * SingleEntrySize() + kDexPcOffset, dex_pc);
934 }
935
Roland Levillain1c1da432015-07-16 11:54:44 +0100936 InvokeTypeType GetInvokeTypeAtDepth(DepthType depth) const {
937 return region_.LoadUnaligned<InvokeTypeType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100938 kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset);
939 }
940
Roland Levillain1c1da432015-07-16 11:54:44 +0100941 void SetInvokeTypeAtDepth(DepthType depth, InvokeTypeType invoke_type) {
942 region_.StoreUnaligned<InvokeTypeType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100943 kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset, invoke_type);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100944 }
945
Roland Levillain1c1da432015-07-16 11:54:44 +0100946 DexRegisterMapType GetDexRegisterMapOffsetAtDepth(DepthType depth) const {
947 return region_.LoadUnaligned<DexRegisterMapType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100948 kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100949 }
950
Roland Levillain1c1da432015-07-16 11:54:44 +0100951 void SetDexRegisterMapOffsetAtDepth(DepthType depth, DexRegisterMapType offset) {
952 region_.StoreUnaligned<DexRegisterMapType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100953 kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset, offset);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100954 }
955
Roland Levillain1c1da432015-07-16 11:54:44 +0100956 bool HasDexRegisterMapAtDepth(DepthType depth) const {
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100957 return GetDexRegisterMapOffsetAtDepth(depth) != StackMap::kNoDexRegisterMap;
958 }
959
960 static size_t SingleEntrySize() {
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100961 return kFixedEntrySize;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100962 }
963
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100964 void Dump(VariableIndentationOutputStream* vios,
965 const CodeInfo& info, uint16_t* number_of_dex_registers) const;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100966
Roland Levillain1c1da432015-07-16 11:54:44 +0100967
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100968 private:
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100969 static constexpr int kDepthOffset = 0;
Roland Levillain1c1da432015-07-16 11:54:44 +0100970 static constexpr int kFixedSize = ELEMENT_BYTE_OFFSET_AFTER(Depth);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100971
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100972 static constexpr int kMethodIndexOffset = 0;
Roland Levillain1c1da432015-07-16 11:54:44 +0100973 static constexpr int kDexPcOffset = ELEMENT_BYTE_OFFSET_AFTER(MethodIndex);
974 static constexpr int kInvokeTypeOffset = ELEMENT_BYTE_OFFSET_AFTER(DexPc);
975 static constexpr int kDexRegisterMapOffset = ELEMENT_BYTE_OFFSET_AFTER(InvokeType);
976 static constexpr int kFixedEntrySize = ELEMENT_BYTE_OFFSET_AFTER(DexRegisterMap);
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100977
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100978 MemoryRegion region_;
979
980 friend class CodeInfo;
981 friend class StackMap;
982 friend class StackMapStream;
983};
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100984
985/**
986 * Wrapper around all compiler information collected for a method.
987 * The information is of the form:
Roland Levillain1c1da432015-07-16 11:54:44 +0100988 *
989 * [overall_size, encoding_info, number_of_location_catalog_entries, number_of_stack_maps,
990 * stack_mask_size, DexRegisterLocationCatalog+, StackMap+, DexRegisterMap+, InlineInfo*]
991 *
992 * where `encoding_info` is of the form:
993 *
994 * [has_inline_info, inline_info_size_in_bytes, dex_register_map_size_in_bytes,
995 * dex_pc_size_in_bytes, native_pc_size_in_bytes, register_mask_size_in_bytes].
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100996 */
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100997class CodeInfo {
998 public:
Roland Levillain1c1da432015-07-16 11:54:44 +0100999 // Memory layout: fixed contents.
1000 typedef uint32_t OverallSizeType;
1001 typedef uint16_t EncodingInfoType;
1002 typedef uint32_t NumberOfLocationCatalogEntriesType;
1003 typedef uint32_t NumberOfStackMapsType;
1004 typedef uint32_t StackMaskSizeType;
1005
1006 // Memory (bit) layout: encoding info.
1007 static constexpr int HasInlineInfoBitSize = 1;
1008 static constexpr int InlineInfoBitSize = kNumberOfBitForNumberOfBytesForEncoding;
1009 static constexpr int DexRegisterMapBitSize = kNumberOfBitForNumberOfBytesForEncoding;
1010 static constexpr int DexPcBitSize = kNumberOfBitForNumberOfBytesForEncoding;
1011 static constexpr int NativePcBitSize = kNumberOfBitForNumberOfBytesForEncoding;
1012 static constexpr int RegisterMaskBitSize = kNumberOfBitForNumberOfBytesForEncoding;
1013
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001014 explicit CodeInfo(MemoryRegion region) : region_(region) {}
1015
Nicolas Geoffray39468442014-09-02 15:17:15 +01001016 explicit CodeInfo(const void* data) {
1017 uint32_t size = reinterpret_cast<const uint32_t*>(data)[0];
1018 region_ = MemoryRegion(const_cast<void*>(data), size);
1019 }
1020
David Brazdilf677ebf2015-05-29 16:29:43 +01001021 StackMapEncoding ExtractEncoding() const {
1022 return StackMapEncoding(region_.LoadUnaligned<uint32_t>(kStackMaskSizeOffset),
1023 GetNumberOfBytesForEncoding(kInlineInfoBitOffset),
1024 GetNumberOfBytesForEncoding(kDexRegisterMapBitOffset),
1025 GetNumberOfBytesForEncoding(kDexPcBitOffset),
1026 GetNumberOfBytesForEncoding(kNativePcBitOffset),
1027 GetNumberOfBytesForEncoding(kRegisterMaskBitOffset));
Nicolas Geoffray896f8f72015-03-30 15:44:25 +01001028 }
1029
David Brazdilf677ebf2015-05-29 16:29:43 +01001030 void SetEncoding(const StackMapEncoding& encoding) {
1031 region_.StoreUnaligned<uint32_t>(kStackMaskSizeOffset, encoding.NumberOfBytesForStackMask());
1032 region_.StoreBit(kHasInlineInfoBitOffset, encoding.NumberOfBytesForInlineInfo() != 0);
1033 SetEncodingAt(kInlineInfoBitOffset, encoding.NumberOfBytesForInlineInfo());
1034 SetEncodingAt(kDexRegisterMapBitOffset, encoding.NumberOfBytesForDexRegisterMap());
1035 SetEncodingAt(kDexPcBitOffset, encoding.NumberOfBytesForDexPc());
1036 SetEncodingAt(kNativePcBitOffset, encoding.NumberOfBytesForNativePc());
1037 SetEncodingAt(kRegisterMaskBitOffset, encoding.NumberOfBytesForRegisterMask());
Nicolas Geoffray896f8f72015-03-30 15:44:25 +01001038 }
1039
1040 void SetEncodingAt(size_t bit_offset, size_t number_of_bytes) {
Roland Levillaind780c002015-07-15 14:30:26 +01001041 region_.StoreBits(bit_offset, number_of_bytes, kNumberOfBitForNumberOfBytesForEncoding);
Nicolas Geoffray896f8f72015-03-30 15:44:25 +01001042 }
1043
1044 size_t GetNumberOfBytesForEncoding(size_t bit_offset) const {
Roland Levillaind780c002015-07-15 14:30:26 +01001045 return region_.LoadBits(bit_offset, kNumberOfBitForNumberOfBytesForEncoding);
Nicolas Geoffray004c2302015-03-20 10:06:38 +00001046 }
1047
1048 bool HasInlineInfo() const {
1049 return region_.LoadBit(kHasInlineInfoBitOffset);
1050 }
1051
David Brazdilf677ebf2015-05-29 16:29:43 +01001052 DexRegisterLocationCatalog GetDexRegisterLocationCatalog(const StackMapEncoding& encoding) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +00001053 return DexRegisterLocationCatalog(region_.Subregion(
David Brazdilf677ebf2015-05-29 16:29:43 +01001054 GetDexRegisterLocationCatalogOffset(encoding),
1055 GetDexRegisterLocationCatalogSize(encoding)));
Roland Levillaina552e1c2015-03-26 15:01:03 +00001056 }
1057
David Brazdilf677ebf2015-05-29 16:29:43 +01001058 StackMap GetStackMapAt(size_t i, const StackMapEncoding& encoding) const {
1059 size_t stack_map_size = encoding.ComputeStackMapSize();
1060 return StackMap(GetStackMaps(encoding).Subregion(i * stack_map_size, stack_map_size));
Nicolas Geoffray39468442014-09-02 15:17:15 +01001061 }
1062
Roland Levillain1c1da432015-07-16 11:54:44 +01001063 OverallSizeType GetOverallSize() const {
1064 return region_.LoadUnaligned<OverallSizeType>(kOverallSizeOffset);
Nicolas Geoffray39468442014-09-02 15:17:15 +01001065 }
1066
Roland Levillain1c1da432015-07-16 11:54:44 +01001067 void SetOverallSize(OverallSizeType size) {
1068 region_.StoreUnaligned<OverallSizeType>(kOverallSizeOffset, size);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001069 }
1070
Roland Levillain1c1da432015-07-16 11:54:44 +01001071 NumberOfLocationCatalogEntriesType GetNumberOfLocationCatalogEntries() const {
1072 return region_.LoadUnaligned<NumberOfLocationCatalogEntriesType>(
1073 kNumberOfLocationCatalogEntriesOffset);
Roland Levillaina552e1c2015-03-26 15:01:03 +00001074 }
1075
Roland Levillain1c1da432015-07-16 11:54:44 +01001076 void SetNumberOfLocationCatalogEntries(NumberOfLocationCatalogEntriesType num_entries) {
1077 region_.StoreUnaligned<NumberOfLocationCatalogEntriesType>(
1078 kNumberOfLocationCatalogEntriesOffset, num_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +00001079 }
1080
David Brazdilf677ebf2015-05-29 16:29:43 +01001081 uint32_t GetDexRegisterLocationCatalogSize(const StackMapEncoding& encoding) const {
1082 return ComputeDexRegisterLocationCatalogSize(GetDexRegisterLocationCatalogOffset(encoding),
Roland Levillain1c1da432015-07-16 11:54:44 +01001083 GetNumberOfLocationCatalogEntries());
Roland Levillaina552e1c2015-03-26 15:01:03 +00001084 }
1085
Roland Levillain1c1da432015-07-16 11:54:44 +01001086 NumberOfStackMapsType GetNumberOfStackMaps() const {
1087 return region_.LoadUnaligned<NumberOfStackMapsType>(kNumberOfStackMapsOffset);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001088 }
1089
Roland Levillain1c1da432015-07-16 11:54:44 +01001090 void SetNumberOfStackMaps(NumberOfStackMapsType number_of_stack_maps) {
1091 region_.StoreUnaligned<NumberOfStackMapsType>(kNumberOfStackMapsOffset, number_of_stack_maps);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001092 }
1093
Roland Levillain29ba1b02015-03-13 11:45:07 +00001094 // Get the size all the stack maps of this CodeInfo object, in bytes.
David Brazdilf677ebf2015-05-29 16:29:43 +01001095 size_t GetStackMapsSize(const StackMapEncoding& encoding) const {
1096 return encoding.ComputeStackMapSize() * GetNumberOfStackMaps();
Roland Levillain29ba1b02015-03-13 11:45:07 +00001097 }
1098
David Brazdilf677ebf2015-05-29 16:29:43 +01001099 uint32_t GetDexRegisterLocationCatalogOffset(const StackMapEncoding& encoding) const {
1100 return GetStackMapsOffset() + GetStackMapsSize(encoding);
Nicolas Geoffray004c2302015-03-20 10:06:38 +00001101 }
1102
David Brazdilf677ebf2015-05-29 16:29:43 +01001103 size_t GetDexRegisterMapsOffset(const StackMapEncoding& encoding) const {
1104 return GetDexRegisterLocationCatalogOffset(encoding)
1105 + GetDexRegisterLocationCatalogSize(encoding);
Roland Levillaina2d8ec62015-03-12 15:25:29 +00001106 }
1107
Nicolas Geoffray6530baf2015-05-26 15:22:58 +01001108 uint32_t GetStackMapsOffset() const {
1109 return kFixedSize;
1110 }
1111
David Brazdilf677ebf2015-05-29 16:29:43 +01001112 DexRegisterMap GetDexRegisterMapOf(StackMap stack_map,
1113 const StackMapEncoding& encoding,
1114 uint32_t number_of_dex_registers) const {
1115 DCHECK(stack_map.HasDexRegisterMap(encoding));
1116 uint32_t offset = GetDexRegisterMapsOffset(encoding)
1117 + stack_map.GetDexRegisterMapOffset(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +00001118 size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
Roland Levillaina2d8ec62015-03-12 15:25:29 +00001119 return DexRegisterMap(region_.Subregion(offset, size));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001120 }
1121
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +01001122 // Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`.
1123 DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth,
1124 InlineInfo inline_info,
David Brazdilf677ebf2015-05-29 16:29:43 +01001125 const StackMapEncoding& encoding,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +01001126 uint32_t number_of_dex_registers) const {
1127 DCHECK(inline_info.HasDexRegisterMapAtDepth(depth));
David Brazdilf677ebf2015-05-29 16:29:43 +01001128 uint32_t offset = GetDexRegisterMapsOffset(encoding)
1129 + inline_info.GetDexRegisterMapOffsetAtDepth(depth);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +01001130 size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
1131 return DexRegisterMap(region_.Subregion(offset, size));
1132 }
1133
David Brazdilf677ebf2015-05-29 16:29:43 +01001134 InlineInfo GetInlineInfoOf(StackMap stack_map, const StackMapEncoding& encoding) const {
1135 DCHECK(stack_map.HasInlineInfo(encoding));
1136 uint32_t offset = stack_map.GetInlineDescriptorOffset(encoding)
1137 + GetDexRegisterMapsOffset(encoding);
Nicolas Geoffray004c2302015-03-20 10:06:38 +00001138 uint8_t depth = region_.LoadUnaligned<uint8_t>(offset);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001139 return InlineInfo(region_.Subregion(offset,
1140 InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize()));
1141 }
1142
David Brazdilf677ebf2015-05-29 16:29:43 +01001143 StackMap GetStackMapForDexPc(uint32_t dex_pc, const StackMapEncoding& encoding) const {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001144 for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
David Brazdilf677ebf2015-05-29 16:29:43 +01001145 StackMap stack_map = GetStackMapAt(i, encoding);
1146 if (stack_map.GetDexPc(encoding) == dex_pc) {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001147 return stack_map;
1148 }
1149 }
Nicolas Geoffraye12997f2015-05-22 14:01:33 +01001150 return StackMap();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001151 }
1152
David Brazdilf677ebf2015-05-29 16:29:43 +01001153 StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset,
1154 const StackMapEncoding& encoding) const {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001155 // TODO: stack maps are sorted by native pc, we can do a binary search.
1156 for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
David Brazdilf677ebf2015-05-29 16:29:43 +01001157 StackMap stack_map = GetStackMapAt(i, encoding);
1158 if (stack_map.GetNativePcOffset(encoding) == native_pc_offset) {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001159 return stack_map;
1160 }
1161 }
Nicolas Geoffraye12997f2015-05-22 14:01:33 +01001162 return StackMap();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001163 }
1164
Roland Levillainf2650d12015-05-28 14:53:28 +01001165 // Dump this CodeInfo object on `os`. `code_offset` is the (absolute)
1166 // native PC of the compiled method and `number_of_dex_registers` the
1167 // number of Dex virtual registers used in this method. If
1168 // `dump_stack_maps` is true, also dump the stack maps and the
1169 // associated Dex register maps.
Vladimir Marko8f1e08a2015-06-26 12:06:30 +01001170 void Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +01001171 uint32_t code_offset,
1172 uint16_t number_of_dex_registers,
1173 bool dump_stack_maps) const;
Nicolas Geoffray004c2302015-03-20 10:06:38 +00001174
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001175 private:
Nicolas Geoffray39468442014-09-02 15:17:15 +01001176 static constexpr int kOverallSizeOffset = 0;
Roland Levillain1c1da432015-07-16 11:54:44 +01001177 static constexpr int kEncodingInfoOffset = ELEMENT_BYTE_OFFSET_AFTER(OverallSize);
1178 static constexpr int kNumberOfLocationCatalogEntriesOffset =
1179 ELEMENT_BYTE_OFFSET_AFTER(EncodingInfo);
Roland Levillaina552e1c2015-03-26 15:01:03 +00001180 static constexpr int kNumberOfStackMapsOffset =
Roland Levillain1c1da432015-07-16 11:54:44 +01001181 ELEMENT_BYTE_OFFSET_AFTER(NumberOfLocationCatalogEntries);
1182 static constexpr int kStackMaskSizeOffset = ELEMENT_BYTE_OFFSET_AFTER(NumberOfStackMaps);
1183 static constexpr int kFixedSize = ELEMENT_BYTE_OFFSET_AFTER(StackMaskSize);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001184
Roland Levillain1c1da432015-07-16 11:54:44 +01001185 static constexpr int kHasInlineInfoBitOffset = kEncodingInfoOffset * kBitsPerByte;
1186 static constexpr int kInlineInfoBitOffset = ELEMENT_BIT_OFFSET_AFTER(HasInlineInfo);
1187 static constexpr int kDexRegisterMapBitOffset = ELEMENT_BIT_OFFSET_AFTER(InlineInfo);
1188 static constexpr int kDexPcBitOffset = ELEMENT_BIT_OFFSET_AFTER(DexRegisterMap);
1189 static constexpr int kNativePcBitOffset = ELEMENT_BIT_OFFSET_AFTER(DexPc);
1190 static constexpr int kRegisterMaskBitOffset = ELEMENT_BIT_OFFSET_AFTER(NativePc);
1191
1192 static constexpr int kEncodingInfoPastTheEndBitOffset = ELEMENT_BIT_OFFSET_AFTER(RegisterMask);
1193 static constexpr int kEncodingInfoOverallBitSize =
1194 kEncodingInfoPastTheEndBitOffset - kHasInlineInfoBitOffset;
1195
1196 static_assert(kEncodingInfoOverallBitSize <= (sizeof(EncodingInfoType) * kBitsPerByte),
1197 "art::CodeInfo::EncodingInfoType is too short to hold all encoding info elements.");
Nicolas Geoffray004c2302015-03-20 10:06:38 +00001198
David Brazdilf677ebf2015-05-29 16:29:43 +01001199 MemoryRegion GetStackMaps(const StackMapEncoding& encoding) const {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001200 return region_.size() == 0
1201 ? MemoryRegion()
David Brazdilf677ebf2015-05-29 16:29:43 +01001202 : region_.Subregion(GetStackMapsOffset(), GetStackMapsSize(encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001203 }
1204
Roland Levillaina552e1c2015-03-26 15:01:03 +00001205 // Compute the size of the Dex register map associated to the stack map at
1206 // `dex_register_map_offset_in_code_info`.
1207 size_t ComputeDexRegisterMapSizeOf(uint32_t dex_register_map_offset_in_code_info,
1208 uint16_t number_of_dex_registers) const {
1209 // Offset where the actual mapping data starts within art::DexRegisterMap.
1210 size_t location_mapping_data_offset_in_dex_register_map =
1211 DexRegisterMap::GetLocationMappingDataOffset(number_of_dex_registers);
1212 // Create a temporary art::DexRegisterMap to be able to call
1213 // art::DexRegisterMap::GetNumberOfLiveDexRegisters and
1214 DexRegisterMap dex_register_map_without_locations(
1215 MemoryRegion(region_.Subregion(dex_register_map_offset_in_code_info,
1216 location_mapping_data_offset_in_dex_register_map)));
1217 size_t number_of_live_dex_registers =
1218 dex_register_map_without_locations.GetNumberOfLiveDexRegisters(number_of_dex_registers);
1219 size_t location_mapping_data_size_in_bits =
Roland Levillain1c1da432015-07-16 11:54:44 +01001220 DexRegisterMap::SingleEntrySizeInBits(GetNumberOfLocationCatalogEntries())
Roland Levillaina552e1c2015-03-26 15:01:03 +00001221 * number_of_live_dex_registers;
1222 size_t location_mapping_data_size_in_bytes =
1223 RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
1224 size_t dex_register_map_size =
1225 location_mapping_data_offset_in_dex_register_map + location_mapping_data_size_in_bytes;
1226 return dex_register_map_size;
1227 }
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +00001228
Roland Levillaina552e1c2015-03-26 15:01:03 +00001229 // Compute the size of a Dex register location catalog starting at offset `origin`
1230 // in `region_` and containing `number_of_dex_locations` entries.
1231 size_t ComputeDexRegisterLocationCatalogSize(uint32_t origin,
1232 uint32_t number_of_dex_locations) const {
1233 // TODO: Ideally, we would like to use art::DexRegisterLocationCatalog::Size or
1234 // art::DexRegisterLocationCatalog::FindLocationOffset, but the
1235 // DexRegisterLocationCatalog is not yet built. Try to factor common code.
1236 size_t offset = origin + DexRegisterLocationCatalog::kFixedSize;
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +00001237
Roland Levillaina552e1c2015-03-26 15:01:03 +00001238 // Skip the first `number_of_dex_locations - 1` entries.
1239 for (uint16_t i = 0; i < number_of_dex_locations; ++i) {
1240 // Read the first next byte and inspect its first 3 bits to decide
1241 // whether it is a short or a large location.
1242 DexRegisterLocationCatalog::ShortLocation first_byte =
1243 region_.LoadUnaligned<DexRegisterLocationCatalog::ShortLocation>(offset);
1244 DexRegisterLocation::Kind kind =
1245 DexRegisterLocationCatalog::ExtractKindFromShortLocation(first_byte);
1246 if (DexRegisterLocation::IsShortLocationKind(kind)) {
1247 // Short location. Skip the current byte.
1248 offset += DexRegisterLocationCatalog::SingleShortEntrySize();
1249 } else {
1250 // Large location. Skip the 5 next bytes.
1251 offset += DexRegisterLocationCatalog::SingleLargeEntrySize();
Roland Levillaina2d8ec62015-03-12 15:25:29 +00001252 }
1253 }
1254 size_t size = offset - origin;
1255 return size;
1256 }
1257
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001258 MemoryRegion region_;
Nicolas Geoffray39468442014-09-02 15:17:15 +01001259 friend class StackMapStream;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001260};
1261
Roland Levillain1c1da432015-07-16 11:54:44 +01001262#undef ELEMENT_BYTE_OFFSET_AFTER
1263#undef ELEMENT_BIT_OFFSET_AFTER
1264
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001265} // namespace art
1266
1267#endif // ART_RUNTIME_STACK_MAP_H_