blob: 97eb805501f086927f90fa1bfa8032c50506781c [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:
David Brazdild9cb68e2015-08-25 13:52:43 +010062 * - kStack: vreg stored on the stack, value holds the stack offset;
63 * - kInRegister: vreg stored in low 32 bits of a core physical register,
64 * value holds the register number;
65 * - kInRegisterHigh: vreg stored in high 32 bits of a core physical register,
66 * value holds the register number;
67 * - kInFpuRegister: vreg stored in low 32 bits of an FPU register,
68 * value holds the register number;
69 * - kInFpuRegisterHigh: vreg stored in high 32 bits of an FPU register,
70 * value holds the register number;
Roland Levillaina2d8ec62015-03-12 15:25:29 +000071 * - kConstant: value holds the constant;
Roland Levillaina2d8ec62015-03-12 15:25:29 +000072 *
73 * In addition, DexRegisterMap also uses these values:
74 * - kInStackLargeOffset: value holds a "large" stack offset (greater than
Roland Levillaina552e1c2015-03-26 15:01:03 +000075 * or equal to 128 bytes);
76 * - kConstantLargeValue: value holds a "large" constant (lower than 0, or
David Brazdild9cb68e2015-08-25 13:52:43 +010077 * or greater than or equal to 32);
78 * - kNone: the register has no location, meaning it has not been set.
Roland Levillaina2d8ec62015-03-12 15:25:29 +000079 */
80 enum class Kind : uint8_t {
81 // Short location kinds, for entries fitting on one byte (3 bits
82 // for the kind, 5 bits for the value) in a DexRegisterMap.
David Brazdild9cb68e2015-08-25 13:52:43 +010083 kInStack = 0, // 0b000
84 kInRegister = 1, // 0b001
85 kInRegisterHigh = 2, // 0b010
Roland Levillaina2d8ec62015-03-12 15:25:29 +000086 kInFpuRegister = 3, // 0b011
David Brazdild9cb68e2015-08-25 13:52:43 +010087 kInFpuRegisterHigh = 4, // 0b100
88 kConstant = 5, // 0b101
Roland Levillaina2d8ec62015-03-12 15:25:29 +000089
90 // Large location kinds, requiring a 5-byte encoding (1 byte for the
91 // kind, 4 bytes for the value).
92
93 // Stack location at a large offset, meaning that the offset value
94 // divided by the stack frame slot size (4 bytes) cannot fit on a
95 // 5-bit unsigned integer (i.e., this offset value is greater than
96 // or equal to 2^5 * 4 = 128 bytes).
David Brazdild9cb68e2015-08-25 13:52:43 +010097 kInStackLargeOffset = 6, // 0b110
Roland Levillaina2d8ec62015-03-12 15:25:29 +000098
99 // Large constant, that cannot fit on a 5-bit signed integer (i.e.,
Roland Levillaina552e1c2015-03-26 15:01:03 +0000100 // lower than 0, or greater than or equal to 2^5 = 32).
David Brazdild9cb68e2015-08-25 13:52:43 +0100101 kConstantLargeValue = 7, // 0b111
102
103 // Entries with no location are not stored and do not need own marker.
104 kNone = static_cast<uint8_t>(-1),
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000105
106 kLastLocationKind = kConstantLargeValue
107 };
108
109 static_assert(
110 sizeof(Kind) == 1u,
111 "art::DexRegisterLocation::Kind has a size different from one byte.");
112
113 static const char* PrettyDescriptor(Kind kind) {
114 switch (kind) {
115 case Kind::kNone:
116 return "none";
117 case Kind::kInStack:
118 return "in stack";
119 case Kind::kInRegister:
120 return "in register";
David Brazdild9cb68e2015-08-25 13:52:43 +0100121 case Kind::kInRegisterHigh:
122 return "in register high";
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000123 case Kind::kInFpuRegister:
124 return "in fpu register";
David Brazdild9cb68e2015-08-25 13:52:43 +0100125 case Kind::kInFpuRegisterHigh:
126 return "in fpu register high";
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000127 case Kind::kConstant:
128 return "as constant";
129 case Kind::kInStackLargeOffset:
130 return "in stack (large offset)";
131 case Kind::kConstantLargeValue:
132 return "as constant (large value)";
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000133 }
David Brazdild9cb68e2015-08-25 13:52:43 +0100134 UNREACHABLE();
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000135 }
136
137 static bool IsShortLocationKind(Kind kind) {
138 switch (kind) {
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000139 case Kind::kInStack:
140 case Kind::kInRegister:
David Brazdild9cb68e2015-08-25 13:52:43 +0100141 case Kind::kInRegisterHigh:
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000142 case Kind::kInFpuRegister:
David Brazdild9cb68e2015-08-25 13:52:43 +0100143 case Kind::kInFpuRegisterHigh:
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000144 case Kind::kConstant:
145 return true;
146
147 case Kind::kInStackLargeOffset:
148 case Kind::kConstantLargeValue:
149 return false;
150
David Brazdild9cb68e2015-08-25 13:52:43 +0100151 case Kind::kNone:
152 LOG(FATAL) << "Unexpected location kind " << PrettyDescriptor(kind);
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000153 }
David Brazdild9cb68e2015-08-25 13:52:43 +0100154 UNREACHABLE();
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000155 }
156
157 // Convert `kind` to a "surface" kind, i.e. one that doesn't include
158 // any value with a "large" qualifier.
159 // TODO: Introduce another enum type for the surface kind?
160 static Kind ConvertToSurfaceKind(Kind kind) {
161 switch (kind) {
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000162 case Kind::kInStack:
163 case Kind::kInRegister:
David Brazdild9cb68e2015-08-25 13:52:43 +0100164 case Kind::kInRegisterHigh:
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000165 case Kind::kInFpuRegister:
David Brazdild9cb68e2015-08-25 13:52:43 +0100166 case Kind::kInFpuRegisterHigh:
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000167 case Kind::kConstant:
168 return kind;
169
170 case Kind::kInStackLargeOffset:
171 return Kind::kInStack;
172
173 case Kind::kConstantLargeValue:
174 return Kind::kConstant;
175
David Brazdild9cb68e2015-08-25 13:52:43 +0100176 case Kind::kNone:
177 return kind;
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000178 }
David Brazdild9cb68e2015-08-25 13:52:43 +0100179 UNREACHABLE();
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000180 }
181
Roland Levillaina552e1c2015-03-26 15:01:03 +0000182 // Required by art::StackMapStream::LocationCatalogEntriesIndices.
183 DexRegisterLocation() : kind_(Kind::kNone), value_(0) {}
184
185 DexRegisterLocation(Kind kind, int32_t value) : kind_(kind), value_(value) {}
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000186
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000187 static DexRegisterLocation None() {
188 return DexRegisterLocation(Kind::kNone, 0);
189 }
190
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000191 // Get the "surface" kind of the location, i.e., the one that doesn't
192 // include any value with a "large" qualifier.
193 Kind GetKind() const {
194 return ConvertToSurfaceKind(kind_);
195 }
196
197 // Get the value of the location.
198 int32_t GetValue() const { return value_; }
199
200 // Get the actual kind of the location.
201 Kind GetInternalKind() const { return kind_; }
202
Calin Juravle6ae70962015-03-18 16:31:28 +0000203 bool operator==(DexRegisterLocation other) const {
204 return kind_ == other.kind_ && value_ == other.value_;
205 }
206
207 bool operator!=(DexRegisterLocation other) const {
208 return !(*this == other);
209 }
210
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000211 private:
212 Kind kind_;
213 int32_t value_;
Roland Levillaina552e1c2015-03-26 15:01:03 +0000214
215 friend class DexRegisterLocationHashFn;
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000216};
217
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100218/**
Roland Levillaina552e1c2015-03-26 15:01:03 +0000219 * Store information on unique Dex register locations used in a method.
220 * The information is of the form:
Roland Levillain1c1da432015-07-16 11:54:44 +0100221 *
222 * [DexRegisterLocation+].
223 *
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000224 * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind).
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100225 */
Roland Levillaina552e1c2015-03-26 15:01:03 +0000226class DexRegisterLocationCatalog {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100227 public:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000228 explicit DexRegisterLocationCatalog(MemoryRegion region) : region_(region) {}
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100229
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000230 // Short (compressed) location, fitting on one byte.
231 typedef uint8_t ShortLocation;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100232
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000233 void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) {
234 DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location);
235 int32_t value = dex_register_location.GetValue();
236 if (DexRegisterLocation::IsShortLocationKind(kind)) {
237 // Short location. Compress the kind and the value as a single byte.
238 if (kind == DexRegisterLocation::Kind::kInStack) {
239 // Instead of storing stack offsets expressed in bytes for
240 // short stack locations, store slot offsets. A stack offset
241 // is a multiple of 4 (kFrameSlotSize). This means that by
242 // dividing it by 4, we can fit values from the [0, 128)
243 // interval in a short stack location, and not just values
244 // from the [0, 32) interval.
245 DCHECK_EQ(value % kFrameSlotSize, 0);
246 value /= kFrameSlotSize;
247 }
Roland Levillaina552e1c2015-03-26 15:01:03 +0000248 DCHECK(IsShortValue(value)) << value;
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000249 region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value));
250 } else {
251 // Large location. Write the location on one byte and the value
252 // on 4 bytes.
Roland Levillaina552e1c2015-03-26 15:01:03 +0000253 DCHECK(!IsShortValue(value)) << value;
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000254 if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
255 // Also divide large stack offsets by 4 for the sake of consistency.
256 DCHECK_EQ(value % kFrameSlotSize, 0);
257 value /= kFrameSlotSize;
258 }
259 // Data can be unaligned as the written Dex register locations can
260 // either be 1-byte or 5-byte wide. Use
261 // art::MemoryRegion::StoreUnaligned instead of
262 // art::MemoryRegion::Store to prevent unligned word accesses on ARM.
263 region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind);
264 region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value);
Roland Levillain442b46a2015-02-18 16:54:21 +0000265 }
266 }
267
Roland Levillaina552e1c2015-03-26 15:01:03 +0000268 // Find the offset of the location catalog entry number `location_catalog_entry_index`.
269 size_t FindLocationOffset(size_t location_catalog_entry_index) const {
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000270 size_t offset = kFixedSize;
Roland Levillaina552e1c2015-03-26 15:01:03 +0000271 // Skip the first `location_catalog_entry_index - 1` entries.
272 for (uint16_t i = 0; i < location_catalog_entry_index; ++i) {
273 // Read the first next byte and inspect its first 3 bits to decide
274 // whether it is a short or a large location.
275 DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
276 if (DexRegisterLocation::IsShortLocationKind(kind)) {
277 // Short location. Skip the current byte.
278 offset += SingleShortEntrySize();
279 } else {
280 // Large location. Skip the 5 next bytes.
281 offset += SingleLargeEntrySize();
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000282 }
283 }
284 return offset;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100285 }
286
Roland Levillaina552e1c2015-03-26 15:01:03 +0000287 // Get the internal kind of entry at `location_catalog_entry_index`.
288 DexRegisterLocation::Kind GetLocationInternalKind(size_t location_catalog_entry_index) const {
289 if (location_catalog_entry_index == kNoLocationEntryIndex) {
290 return DexRegisterLocation::Kind::kNone;
291 }
292 return ExtractKindAtOffset(FindLocationOffset(location_catalog_entry_index));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100293 }
294
Roland Levillaina552e1c2015-03-26 15:01:03 +0000295 // Get the (surface) kind and value of entry at `location_catalog_entry_index`.
296 DexRegisterLocation GetDexRegisterLocation(size_t location_catalog_entry_index) const {
297 if (location_catalog_entry_index == kNoLocationEntryIndex) {
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000298 return DexRegisterLocation::None();
299 }
Roland Levillaina552e1c2015-03-26 15:01:03 +0000300 size_t offset = FindLocationOffset(location_catalog_entry_index);
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000301 // Read the first byte and inspect its first 3 bits to get the location.
302 ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
303 DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte);
304 if (DexRegisterLocation::IsShortLocationKind(kind)) {
305 // Short location. Extract the value from the remaining 5 bits.
306 int32_t value = ExtractValueFromShortLocation(first_byte);
307 if (kind == DexRegisterLocation::Kind::kInStack) {
308 // Convert the stack slot (short) offset to a byte offset value.
309 value *= kFrameSlotSize;
310 }
311 return DexRegisterLocation(kind, value);
312 } else {
313 // Large location. Read the four next bytes to get the value.
314 int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind));
315 if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
316 // Convert the stack slot (large) offset to a byte offset value.
317 value *= kFrameSlotSize;
318 }
319 return DexRegisterLocation(kind, value);
320 }
Sebastien Hertz7cde48c2015-01-20 16:06:43 +0100321 }
322
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000323 // Compute the compressed kind of `location`.
324 static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) {
David Brazdild9cb68e2015-08-25 13:52:43 +0100325 DexRegisterLocation::Kind kind = location.GetInternalKind();
326 switch (kind) {
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000327 case DexRegisterLocation::Kind::kInStack:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000328 return IsShortStackOffsetValue(location.GetValue())
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000329 ? DexRegisterLocation::Kind::kInStack
330 : DexRegisterLocation::Kind::kInStackLargeOffset;
331
David Brazdild9cb68e2015-08-25 13:52:43 +0100332 case DexRegisterLocation::Kind::kInRegister:
333 case DexRegisterLocation::Kind::kInRegisterHigh:
334 DCHECK_GE(location.GetValue(), 0);
335 DCHECK_LT(location.GetValue(), 1 << kValueBits);
336 return kind;
337
338 case DexRegisterLocation::Kind::kInFpuRegister:
339 case DexRegisterLocation::Kind::kInFpuRegisterHigh:
340 DCHECK_GE(location.GetValue(), 0);
341 DCHECK_LT(location.GetValue(), 1 << kValueBits);
342 return kind;
343
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000344 case DexRegisterLocation::Kind::kConstant:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000345 return IsShortConstantValue(location.GetValue())
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000346 ? DexRegisterLocation::Kind::kConstant
347 : DexRegisterLocation::Kind::kConstantLargeValue;
348
David Brazdild9cb68e2015-08-25 13:52:43 +0100349 case DexRegisterLocation::Kind::kConstantLargeValue:
350 case DexRegisterLocation::Kind::kInStackLargeOffset:
351 case DexRegisterLocation::Kind::kNone:
352 LOG(FATAL) << "Unexpected location kind " << DexRegisterLocation::PrettyDescriptor(kind);
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000353 }
David Brazdild9cb68e2015-08-25 13:52:43 +0100354 UNREACHABLE();
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000355 }
356
357 // Can `location` be turned into a short location?
358 static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) {
David Brazdild9cb68e2015-08-25 13:52:43 +0100359 DexRegisterLocation::Kind kind = location.GetInternalKind();
360 switch (kind) {
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000361 case DexRegisterLocation::Kind::kInStack:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000362 return IsShortStackOffsetValue(location.GetValue());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000363
David Brazdild9cb68e2015-08-25 13:52:43 +0100364 case DexRegisterLocation::Kind::kInRegister:
365 case DexRegisterLocation::Kind::kInRegisterHigh:
366 case DexRegisterLocation::Kind::kInFpuRegister:
367 case DexRegisterLocation::Kind::kInFpuRegisterHigh:
368 return true;
369
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000370 case DexRegisterLocation::Kind::kConstant:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000371 return IsShortConstantValue(location.GetValue());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000372
David Brazdild9cb68e2015-08-25 13:52:43 +0100373 case DexRegisterLocation::Kind::kConstantLargeValue:
374 case DexRegisterLocation::Kind::kInStackLargeOffset:
375 case DexRegisterLocation::Kind::kNone:
376 LOG(FATAL) << "Unexpected location kind " << DexRegisterLocation::PrettyDescriptor(kind);
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000377 }
David Brazdild9cb68e2015-08-25 13:52:43 +0100378 UNREACHABLE();
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000379 }
380
381 static size_t EntrySize(const DexRegisterLocation& location) {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000382 return CanBeEncodedAsShortLocation(location) ? SingleShortEntrySize() : SingleLargeEntrySize();
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000383 }
384
385 static size_t SingleShortEntrySize() {
386 return sizeof(ShortLocation);
387 }
388
389 static size_t SingleLargeEntrySize() {
390 return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100391 }
392
Roland Levillain12baf472015-03-05 12:41:42 +0000393 size_t Size() const {
394 return region_.size();
395 }
396
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100397 void Dump(VariableIndentationOutputStream* vios, const CodeInfo& code_info);
Roland Levillain0396ed72015-05-27 15:12:19 +0100398
Roland Levillaina552e1c2015-03-26 15:01:03 +0000399 // Special (invalid) Dex register location catalog entry index meaning
400 // that there is no location for a given Dex register (i.e., it is
401 // mapped to a DexRegisterLocation::Kind::kNone location).
402 static constexpr size_t kNoLocationEntryIndex = -1;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100403
Roland Levillain12baf472015-03-05 12:41:42 +0000404 private:
Roland Levillaina552e1c2015-03-26 15:01:03 +0000405 static constexpr int kFixedSize = 0;
406
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000407 // Width of the kind "field" in a short location, in bits.
408 static constexpr size_t kKindBits = 3;
409 // Width of the value "field" in a short location, in bits.
410 static constexpr size_t kValueBits = 5;
411
412 static constexpr uint8_t kKindMask = (1 << kKindBits) - 1;
413 static constexpr int32_t kValueMask = (1 << kValueBits) - 1;
414 static constexpr size_t kKindOffset = 0;
415 static constexpr size_t kValueOffset = kKindBits;
416
Roland Levillaina552e1c2015-03-26 15:01:03 +0000417 static bool IsShortStackOffsetValue(int32_t value) {
418 DCHECK_EQ(value % kFrameSlotSize, 0);
419 return IsShortValue(value / kFrameSlotSize);
420 }
421
422 static bool IsShortConstantValue(int32_t value) {
423 return IsShortValue(value);
424 }
425
426 static bool IsShortValue(int32_t value) {
427 return IsUint<kValueBits>(value);
428 }
429
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000430 static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000431 uint8_t kind_integer_value = static_cast<uint8_t>(kind);
432 DCHECK(IsUint<kKindBits>(kind_integer_value)) << kind_integer_value;
433 DCHECK(IsShortValue(value)) << value;
434 return (kind_integer_value & kKindMask) << kKindOffset
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000435 | (value & kValueMask) << kValueOffset;
436 }
437
438 static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) {
439 uint8_t kind = (location >> kKindOffset) & kKindMask;
440 DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind));
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000441 // We do not encode kNone locations in the stack map.
442 DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone));
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000443 return static_cast<DexRegisterLocation::Kind>(kind);
444 }
445
446 static int32_t ExtractValueFromShortLocation(ShortLocation location) {
447 return (location >> kValueOffset) & kValueMask;
448 }
449
450 // Extract a location kind from the byte at position `offset`.
451 DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const {
452 ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
453 return ExtractKindFromShortLocation(first_byte);
454 }
455
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100456 MemoryRegion region_;
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000457
458 friend class CodeInfo;
459 friend class StackMapStream;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100460};
461
Roland Levillaina552e1c2015-03-26 15:01:03 +0000462/* Information on Dex register locations for a specific PC, mapping a
463 * stack map's Dex register to a location entry in a DexRegisterLocationCatalog.
464 * The information is of the form:
Roland Levillain1c1da432015-07-16 11:54:44 +0100465 *
466 * [live_bit_mask, entries*]
467 *
Roland Levillaina552e1c2015-03-26 15:01:03 +0000468 * where entries are concatenated unsigned integer values encoded on a number
469 * of bits (fixed per DexRegisterMap instances of a CodeInfo object) depending
470 * on the number of entries in the Dex register location catalog
471 * (see DexRegisterMap::SingleEntrySizeInBits). The map is 1-byte aligned.
472 */
473class DexRegisterMap {
474 public:
475 explicit DexRegisterMap(MemoryRegion region) : region_(region) {}
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000476 DexRegisterMap() {}
477
478 bool IsValid() const { return region_.pointer() != nullptr; }
Roland Levillaina552e1c2015-03-26 15:01:03 +0000479
480 // Get the surface kind of Dex register `dex_register_number`.
481 DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number,
482 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100483 const CodeInfo& code_info,
484 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000485 return DexRegisterLocation::ConvertToSurfaceKind(
David Brazdilf677ebf2015-05-29 16:29:43 +0100486 GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info, enc));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000487 }
488
489 // Get the internal kind of Dex register `dex_register_number`.
490 DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number,
491 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100492 const CodeInfo& code_info,
493 const StackMapEncoding& enc) const;
Roland Levillaina552e1c2015-03-26 15:01:03 +0000494
495 // Get the Dex register location `dex_register_number`.
496 DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number,
497 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100498 const CodeInfo& code_info,
499 const StackMapEncoding& enc) const;
Roland Levillaina552e1c2015-03-26 15:01:03 +0000500
501 int32_t GetStackOffsetInBytes(uint16_t dex_register_number,
502 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100503 const CodeInfo& code_info,
504 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000505 DexRegisterLocation location =
David Brazdilf677ebf2015-05-29 16:29:43 +0100506 GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000507 DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
508 // GetDexRegisterLocation returns the offset in bytes.
509 return location.GetValue();
510 }
511
512 int32_t GetConstant(uint16_t dex_register_number,
513 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100514 const CodeInfo& code_info,
515 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000516 DexRegisterLocation location =
David Brazdilf677ebf2015-05-29 16:29:43 +0100517 GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100518 DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant)
519 << DexRegisterLocation::PrettyDescriptor(location.GetKind());
Roland Levillaina552e1c2015-03-26 15:01:03 +0000520 return location.GetValue();
521 }
522
523 int32_t GetMachineRegister(uint16_t dex_register_number,
524 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +0100525 const CodeInfo& code_info,
526 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000527 DexRegisterLocation location =
David Brazdilf677ebf2015-05-29 16:29:43 +0100528 GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
David Brazdild9cb68e2015-08-25 13:52:43 +0100529 DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister ||
530 location.GetInternalKind() == DexRegisterLocation::Kind::kInRegisterHigh ||
531 location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister ||
532 location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegisterHigh)
Roland Levillaina552e1c2015-03-26 15:01:03 +0000533 << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
534 return location.GetValue();
535 }
536
537 // Get the index of the entry in the Dex register location catalog
538 // corresponding to `dex_register_number`.
539 size_t GetLocationCatalogEntryIndex(uint16_t dex_register_number,
540 uint16_t number_of_dex_registers,
541 size_t number_of_location_catalog_entries) const {
542 if (!IsDexRegisterLive(dex_register_number)) {
543 return DexRegisterLocationCatalog::kNoLocationEntryIndex;
544 }
545
546 if (number_of_location_catalog_entries == 1) {
547 // We do not allocate space for location maps in the case of a
548 // single-entry location catalog, as it is useless. The only valid
549 // entry index is 0;
550 return 0;
551 }
552
553 // The bit offset of the beginning of the map locations.
554 size_t map_locations_offset_in_bits =
555 GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
556 size_t index_in_dex_register_map = GetIndexInDexRegisterMap(dex_register_number);
557 DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
558 // The bit size of an entry.
559 size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
560 // The bit offset where `index_in_dex_register_map` is located.
561 size_t entry_offset_in_bits =
562 map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
563 size_t location_catalog_entry_index =
564 region_.LoadBits(entry_offset_in_bits, map_entry_size_in_bits);
565 DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
566 return location_catalog_entry_index;
567 }
568
569 // Map entry at `index_in_dex_register_map` to `location_catalog_entry_index`.
570 void SetLocationCatalogEntryIndex(size_t index_in_dex_register_map,
571 size_t location_catalog_entry_index,
572 uint16_t number_of_dex_registers,
573 size_t number_of_location_catalog_entries) {
574 DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
575 DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
576
577 if (number_of_location_catalog_entries == 1) {
578 // We do not allocate space for location maps in the case of a
579 // single-entry location catalog, as it is useless.
580 return;
581 }
582
583 // The bit offset of the beginning of the map locations.
584 size_t map_locations_offset_in_bits =
585 GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
586 // The bit size of an entry.
587 size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
588 // The bit offset where `index_in_dex_register_map` is located.
589 size_t entry_offset_in_bits =
590 map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
591 region_.StoreBits(entry_offset_in_bits, location_catalog_entry_index, map_entry_size_in_bits);
592 }
593
594 void SetLiveBitMask(uint16_t number_of_dex_registers,
595 const BitVector& live_dex_registers_mask) {
596 size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
597 for (uint16_t i = 0; i < number_of_dex_registers; ++i) {
598 region_.StoreBit(live_bit_mask_offset_in_bits + i, live_dex_registers_mask.IsBitSet(i));
599 }
600 }
601
602 bool IsDexRegisterLive(uint16_t dex_register_number) const {
603 size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
604 return region_.LoadBit(live_bit_mask_offset_in_bits + dex_register_number);
605 }
606
607 size_t GetNumberOfLiveDexRegisters(uint16_t number_of_dex_registers) const {
608 size_t number_of_live_dex_registers = 0;
609 for (size_t i = 0; i < number_of_dex_registers; ++i) {
610 if (IsDexRegisterLive(i)) {
611 ++number_of_live_dex_registers;
612 }
613 }
614 return number_of_live_dex_registers;
615 }
616
617 static size_t GetLiveBitMaskOffset() {
618 return kFixedSize;
619 }
620
621 // Compute the size of the live register bit mask (in bytes), for a
622 // method having `number_of_dex_registers` Dex registers.
623 static size_t GetLiveBitMaskSize(uint16_t number_of_dex_registers) {
624 return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte;
625 }
626
627 static size_t GetLocationMappingDataOffset(uint16_t number_of_dex_registers) {
628 return GetLiveBitMaskOffset() + GetLiveBitMaskSize(number_of_dex_registers);
629 }
630
631 size_t GetLocationMappingDataSize(uint16_t number_of_dex_registers,
632 size_t number_of_location_catalog_entries) const {
633 size_t location_mapping_data_size_in_bits =
634 GetNumberOfLiveDexRegisters(number_of_dex_registers)
635 * SingleEntrySizeInBits(number_of_location_catalog_entries);
636 return RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
637 }
638
639 // Return the size of a map entry in bits. Note that if
640 // `number_of_location_catalog_entries` equals 1, this function returns 0,
641 // which is fine, as there is no need to allocate a map for a
642 // single-entry location catalog; the only valid location catalog entry index
643 // for a live register in this case is 0 and there is no need to
644 // store it.
645 static size_t SingleEntrySizeInBits(size_t number_of_location_catalog_entries) {
646 // Handle the case of 0, as we cannot pass 0 to art::WhichPowerOf2.
647 return number_of_location_catalog_entries == 0
648 ? 0u
649 : WhichPowerOf2(RoundUpToPowerOfTwo(number_of_location_catalog_entries));
650 }
651
652 // Return the size of the DexRegisterMap object, in bytes.
653 size_t Size() const {
654 return region_.size();
655 }
656
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100657 void Dump(VariableIndentationOutputStream* vios,
658 const CodeInfo& code_info, uint16_t number_of_dex_registers) const;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100659
Roland Levillaina552e1c2015-03-26 15:01:03 +0000660 private:
661 // Return the index in the Dex register map corresponding to the Dex
662 // register number `dex_register_number`.
663 size_t GetIndexInDexRegisterMap(uint16_t dex_register_number) const {
664 if (!IsDexRegisterLive(dex_register_number)) {
665 return kInvalidIndexInDexRegisterMap;
666 }
667 return GetNumberOfLiveDexRegisters(dex_register_number);
668 }
669
670 // Special (invalid) Dex register map entry index meaning that there
671 // is no index in the map for a given Dex register (i.e., it must
672 // have been mapped to a DexRegisterLocation::Kind::kNone location).
673 static constexpr size_t kInvalidIndexInDexRegisterMap = -1;
674
675 static constexpr int kFixedSize = 0;
676
677 MemoryRegion region_;
678
679 friend class CodeInfo;
680 friend class StackMapStream;
681};
682
David Brazdilf677ebf2015-05-29 16:29:43 +0100683class StackMapEncoding {
684 public:
685 StackMapEncoding() {}
686
687 StackMapEncoding(size_t stack_mask_size,
688 size_t bytes_for_inline_info,
689 size_t bytes_for_dex_register_map,
690 size_t bytes_for_dex_pc,
691 size_t bytes_for_native_pc,
692 size_t bytes_for_register_mask)
693 : bytes_for_stack_mask_(stack_mask_size),
694 bytes_for_inline_info_(bytes_for_inline_info),
695 bytes_for_dex_register_map_(bytes_for_dex_register_map),
696 bytes_for_dex_pc_(bytes_for_dex_pc),
697 bytes_for_native_pc_(bytes_for_native_pc),
698 bytes_for_register_mask_(bytes_for_register_mask) {}
699
700 static StackMapEncoding CreateFromSizes(size_t stack_mask_size,
701 size_t inline_info_size,
702 size_t dex_register_map_size,
703 size_t dex_pc_max,
704 size_t native_pc_max,
705 size_t register_mask_max) {
706 return StackMapEncoding(
707 stack_mask_size,
708 // + 1 to also encode kNoInlineInfo: if an inline info offset
709 // is at 0xFF, we want to overflow to a larger encoding, because it will
710 // conflict with kNoInlineInfo.
711 // The offset is relative to the dex register map. TODO: Change this.
712 inline_info_size == 0
713 ? 0
714 : EncodingSizeInBytes(dex_register_map_size + inline_info_size + 1),
715 // + 1 to also encode kNoDexRegisterMap: if a dex register map offset
716 // is at 0xFF, we want to overflow to a larger encoding, because it will
717 // conflict with kNoDexRegisterMap.
718 EncodingSizeInBytes(dex_register_map_size + 1),
719 EncodingSizeInBytes(dex_pc_max),
720 EncodingSizeInBytes(native_pc_max),
721 EncodingSizeInBytes(register_mask_max));
722 }
723
724 // Get the size of one stack map of this CodeInfo object, in bytes.
725 // All stack maps of a CodeInfo have the same size.
726 size_t ComputeStackMapSize() const {
727 return bytes_for_register_mask_
728 + bytes_for_stack_mask_
729 + bytes_for_inline_info_
730 + bytes_for_dex_register_map_
731 + bytes_for_dex_pc_
732 + bytes_for_native_pc_;
733 }
734
735 bool HasInlineInfo() const { return bytes_for_inline_info_ > 0; }
736
737 size_t NumberOfBytesForStackMask() const { return bytes_for_stack_mask_; }
738 size_t NumberOfBytesForInlineInfo() const { return bytes_for_inline_info_; }
739 size_t NumberOfBytesForDexRegisterMap() const { return bytes_for_dex_register_map_; }
740 size_t NumberOfBytesForDexPc() const { return bytes_for_dex_pc_; }
741 size_t NumberOfBytesForNativePc() const { return bytes_for_native_pc_; }
742 size_t NumberOfBytesForRegisterMask() const { return bytes_for_register_mask_; }
743
744 size_t ComputeStackMapRegisterMaskOffset() const {
745 return kRegisterMaskOffset;
746 }
747
748 size_t ComputeStackMapStackMaskOffset() const {
749 return ComputeStackMapRegisterMaskOffset() + bytes_for_register_mask_;
750 }
751
752 size_t ComputeStackMapDexPcOffset() const {
753 return ComputeStackMapStackMaskOffset() + bytes_for_stack_mask_;
754 }
755
756 size_t ComputeStackMapNativePcOffset() const {
757 return ComputeStackMapDexPcOffset() + bytes_for_dex_pc_;
758 }
759
760 size_t ComputeStackMapDexRegisterMapOffset() const {
761 return ComputeStackMapNativePcOffset() + bytes_for_native_pc_;
762 }
763
764 size_t ComputeStackMapInlineInfoOffset() const {
765 return ComputeStackMapDexRegisterMapOffset() + bytes_for_dex_register_map_;
766 }
767
768 private:
769 static size_t EncodingSizeInBytes(size_t max_element) {
770 DCHECK(IsUint<32>(max_element));
771 return (max_element == 0) ? 0
772 : IsUint<8>(max_element) ? 1
773 : IsUint<16>(max_element) ? 2
774 : IsUint<24>(max_element) ? 3
775 : 4;
776 }
777
778 static constexpr int kRegisterMaskOffset = 0;
779
780 size_t bytes_for_stack_mask_;
781 size_t bytes_for_inline_info_;
782 size_t bytes_for_dex_register_map_;
783 size_t bytes_for_dex_pc_;
784 size_t bytes_for_native_pc_;
785 size_t bytes_for_register_mask_;
786};
787
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100788/**
789 * A Stack Map holds compilation information for a specific PC necessary for:
790 * - Mapping it to a dex PC,
791 * - Knowing which stack entries are objects,
792 * - Knowing which registers hold objects,
793 * - Knowing the inlining information,
794 * - Knowing the values of dex registers.
795 *
796 * The information is of the form:
Roland Levillain1c1da432015-07-16 11:54:44 +0100797 *
798 * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask,
799 * stack_mask].
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100800 */
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100801class StackMap {
802 public:
Nicolas Geoffraye12997f2015-05-22 14:01:33 +0100803 StackMap() {}
David Brazdilf677ebf2015-05-29 16:29:43 +0100804 explicit StackMap(MemoryRegion region) : region_(region) {}
Nicolas Geoffraye12997f2015-05-22 14:01:33 +0100805
806 bool IsValid() const { return region_.pointer() != nullptr; }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100807
David Brazdilf677ebf2015-05-29 16:29:43 +0100808 uint32_t GetDexPc(const StackMapEncoding& encoding) const {
809 return LoadAt(encoding.NumberOfBytesForDexPc(), encoding.ComputeStackMapDexPcOffset());
810 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100811
David Brazdilf677ebf2015-05-29 16:29:43 +0100812 void SetDexPc(const StackMapEncoding& encoding, uint32_t dex_pc) {
813 StoreAt(encoding.NumberOfBytesForDexPc(), encoding.ComputeStackMapDexPcOffset(), dex_pc);
814 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100815
David Brazdilf677ebf2015-05-29 16:29:43 +0100816 uint32_t GetNativePcOffset(const StackMapEncoding& encoding) const {
817 return LoadAt(encoding.NumberOfBytesForNativePc(), encoding.ComputeStackMapNativePcOffset());
818 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100819
David Brazdilf677ebf2015-05-29 16:29:43 +0100820 void SetNativePcOffset(const StackMapEncoding& encoding, uint32_t native_pc_offset) {
821 StoreAt(encoding.NumberOfBytesForNativePc(),
822 encoding.ComputeStackMapNativePcOffset(),
823 native_pc_offset);
824 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100825
David Brazdilf677ebf2015-05-29 16:29:43 +0100826 uint32_t GetDexRegisterMapOffset(const StackMapEncoding& encoding) const {
827 return LoadAt(encoding.NumberOfBytesForDexRegisterMap(),
828 encoding.ComputeStackMapDexRegisterMapOffset(),
829 /* check_max */ true);
830 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100831
David Brazdilf677ebf2015-05-29 16:29:43 +0100832 void SetDexRegisterMapOffset(const StackMapEncoding& encoding, uint32_t offset) {
833 StoreAt(encoding.NumberOfBytesForDexRegisterMap(),
834 encoding.ComputeStackMapDexRegisterMapOffset(),
835 offset);
836 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100837
David Brazdilf677ebf2015-05-29 16:29:43 +0100838 uint32_t GetInlineDescriptorOffset(const StackMapEncoding& encoding) const {
839 if (!encoding.HasInlineInfo()) return kNoInlineInfo;
840 return LoadAt(encoding.NumberOfBytesForInlineInfo(),
841 encoding.ComputeStackMapInlineInfoOffset(),
842 /* check_max */ true);
843 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100844
David Brazdilf677ebf2015-05-29 16:29:43 +0100845 void SetInlineDescriptorOffset(const StackMapEncoding& encoding, uint32_t offset) {
846 DCHECK(encoding.HasInlineInfo());
847 StoreAt(encoding.NumberOfBytesForInlineInfo(),
848 encoding.ComputeStackMapInlineInfoOffset(),
849 offset);
850 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100851
David Brazdilf677ebf2015-05-29 16:29:43 +0100852 uint32_t GetRegisterMask(const StackMapEncoding& encoding) const {
853 return LoadAt(encoding.NumberOfBytesForRegisterMask(),
854 encoding.ComputeStackMapRegisterMaskOffset());
855 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100856
David Brazdilf677ebf2015-05-29 16:29:43 +0100857 void SetRegisterMask(const StackMapEncoding& encoding, uint32_t mask) {
858 StoreAt(encoding.NumberOfBytesForRegisterMask(),
859 encoding.ComputeStackMapRegisterMaskOffset(),
860 mask);
861 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100862
David Brazdilf677ebf2015-05-29 16:29:43 +0100863 MemoryRegion GetStackMask(const StackMapEncoding& encoding) const {
864 return region_.Subregion(encoding.ComputeStackMapStackMaskOffset(),
865 encoding.NumberOfBytesForStackMask());
866 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100867
David Brazdilf677ebf2015-05-29 16:29:43 +0100868 void SetStackMask(const StackMapEncoding& encoding, const BitVector& sp_map) {
869 MemoryRegion region = GetStackMask(encoding);
David Brazdilf10a25f2015-06-02 14:29:52 +0100870 sp_map.CopyTo(region.start(), region.size());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100871 }
872
David Brazdilf677ebf2015-05-29 16:29:43 +0100873 bool HasDexRegisterMap(const StackMapEncoding& encoding) const {
874 return GetDexRegisterMapOffset(encoding) != kNoDexRegisterMap;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100875 }
876
David Brazdilf677ebf2015-05-29 16:29:43 +0100877 bool HasInlineInfo(const StackMapEncoding& encoding) const {
878 return GetInlineDescriptorOffset(encoding) != kNoInlineInfo;
Roland Levillain442b46a2015-02-18 16:54:21 +0000879 }
880
881 bool Equals(const StackMap& other) const {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100882 return region_.pointer() == other.region_.pointer()
883 && region_.size() == other.region_.size();
884 }
885
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100886 void Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +0100887 const CodeInfo& code_info,
David Brazdilf677ebf2015-05-29 16:29:43 +0100888 const StackMapEncoding& encoding,
Roland Levillainf2650d12015-05-28 14:53:28 +0100889 uint32_t code_offset,
890 uint16_t number_of_dex_registers,
891 const std::string& header_suffix = "") const;
892
Roland Levillain442b46a2015-02-18 16:54:21 +0000893 // Special (invalid) offset for the DexRegisterMapOffset field meaning
894 // that there is no Dex register map for this stack map.
895 static constexpr uint32_t kNoDexRegisterMap = -1;
896
897 // Special (invalid) offset for the InlineDescriptorOffset field meaning
898 // that there is no inline info for this stack map.
899 static constexpr uint32_t kNoInlineInfo = -1;
900
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100901 private:
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100902 static constexpr int kFixedSize = 0;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100903
David Brazdilf677ebf2015-05-29 16:29:43 +0100904 // Loads `number_of_bytes` at the given `offset` and assemble a uint32_t. If `check_max` is true,
905 // this method converts a maximum value of size `number_of_bytes` into a uint32_t 0xFFFFFFFF.
906 uint32_t LoadAt(size_t number_of_bytes, size_t offset, bool check_max = false) const;
907 void StoreAt(size_t number_of_bytes, size_t offset, uint32_t value) const;
908
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100909 MemoryRegion region_;
910
Nicolas Geoffray39468442014-09-02 15:17:15 +0100911 friend class StackMapStream;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100912};
913
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100914/**
915 * Inline information for a specific PC. The information is of the form:
Roland Levillain1c1da432015-07-16 11:54:44 +0100916 *
917 * [inlining_depth, entry+]
918 *
919 * where `entry` is of the form:
920 *
921 * [dex_pc, method_index, dex_register_map_offset].
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100922 */
923class InlineInfo {
924 public:
Roland Levillain1c1da432015-07-16 11:54:44 +0100925 // Memory layout: fixed contents.
926 typedef uint8_t DepthType;
927 // Memory layout: single entry contents.
928 typedef uint32_t MethodIndexType;
929 typedef uint32_t DexPcType;
930 typedef uint8_t InvokeTypeType;
931 typedef uint32_t DexRegisterMapType;
932
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100933 explicit InlineInfo(MemoryRegion region) : region_(region) {}
934
Roland Levillain1c1da432015-07-16 11:54:44 +0100935 DepthType GetDepth() const {
936 return region_.LoadUnaligned<DepthType>(kDepthOffset);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100937 }
938
Roland Levillain1c1da432015-07-16 11:54:44 +0100939 void SetDepth(DepthType depth) {
940 region_.StoreUnaligned<DepthType>(kDepthOffset, depth);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100941 }
942
Roland Levillain1c1da432015-07-16 11:54:44 +0100943 MethodIndexType GetMethodIndexAtDepth(DepthType depth) const {
944 return region_.LoadUnaligned<MethodIndexType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100945 kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100946 }
947
Roland Levillain1c1da432015-07-16 11:54:44 +0100948 void SetMethodIndexAtDepth(DepthType depth, MethodIndexType index) {
949 region_.StoreUnaligned<MethodIndexType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100950 kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset, index);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100951 }
952
Roland Levillain1c1da432015-07-16 11:54:44 +0100953 DexPcType GetDexPcAtDepth(DepthType depth) const {
954 return region_.LoadUnaligned<DexPcType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100955 kFixedSize + depth * SingleEntrySize() + kDexPcOffset);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100956 }
957
Roland Levillain1c1da432015-07-16 11:54:44 +0100958 void SetDexPcAtDepth(DepthType depth, DexPcType dex_pc) {
959 region_.StoreUnaligned<DexPcType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100960 kFixedSize + depth * SingleEntrySize() + kDexPcOffset, dex_pc);
961 }
962
Roland Levillain1c1da432015-07-16 11:54:44 +0100963 InvokeTypeType GetInvokeTypeAtDepth(DepthType depth) const {
964 return region_.LoadUnaligned<InvokeTypeType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100965 kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset);
966 }
967
Roland Levillain1c1da432015-07-16 11:54:44 +0100968 void SetInvokeTypeAtDepth(DepthType depth, InvokeTypeType invoke_type) {
969 region_.StoreUnaligned<InvokeTypeType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100970 kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset, invoke_type);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100971 }
972
Roland Levillain1c1da432015-07-16 11:54:44 +0100973 DexRegisterMapType GetDexRegisterMapOffsetAtDepth(DepthType depth) const {
974 return region_.LoadUnaligned<DexRegisterMapType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100975 kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100976 }
977
Roland Levillain1c1da432015-07-16 11:54:44 +0100978 void SetDexRegisterMapOffsetAtDepth(DepthType depth, DexRegisterMapType offset) {
979 region_.StoreUnaligned<DexRegisterMapType>(
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100980 kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset, offset);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100981 }
982
Roland Levillain1c1da432015-07-16 11:54:44 +0100983 bool HasDexRegisterMapAtDepth(DepthType depth) const {
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100984 return GetDexRegisterMapOffsetAtDepth(depth) != StackMap::kNoDexRegisterMap;
985 }
986
987 static size_t SingleEntrySize() {
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100988 return kFixedEntrySize;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100989 }
990
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100991 void Dump(VariableIndentationOutputStream* vios,
992 const CodeInfo& info, uint16_t* number_of_dex_registers) const;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100993
Roland Levillain1c1da432015-07-16 11:54:44 +0100994
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100995 private:
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100996 static constexpr int kDepthOffset = 0;
Roland Levillain1c1da432015-07-16 11:54:44 +0100997 static constexpr int kFixedSize = ELEMENT_BYTE_OFFSET_AFTER(Depth);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100998
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100999 static constexpr int kMethodIndexOffset = 0;
Roland Levillain1c1da432015-07-16 11:54:44 +01001000 static constexpr int kDexPcOffset = ELEMENT_BYTE_OFFSET_AFTER(MethodIndex);
1001 static constexpr int kInvokeTypeOffset = ELEMENT_BYTE_OFFSET_AFTER(DexPc);
1002 static constexpr int kDexRegisterMapOffset = ELEMENT_BYTE_OFFSET_AFTER(InvokeType);
1003 static constexpr int kFixedEntrySize = ELEMENT_BYTE_OFFSET_AFTER(DexRegisterMap);
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001004
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +01001005 MemoryRegion region_;
1006
1007 friend class CodeInfo;
1008 friend class StackMap;
1009 friend class StackMapStream;
1010};
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001011
1012/**
1013 * Wrapper around all compiler information collected for a method.
1014 * The information is of the form:
Roland Levillain1c1da432015-07-16 11:54:44 +01001015 *
1016 * [overall_size, encoding_info, number_of_location_catalog_entries, number_of_stack_maps,
1017 * stack_mask_size, DexRegisterLocationCatalog+, StackMap+, DexRegisterMap+, InlineInfo*]
1018 *
1019 * where `encoding_info` is of the form:
1020 *
1021 * [has_inline_info, inline_info_size_in_bytes, dex_register_map_size_in_bytes,
1022 * dex_pc_size_in_bytes, native_pc_size_in_bytes, register_mask_size_in_bytes].
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001023 */
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001024class CodeInfo {
1025 public:
Roland Levillain1c1da432015-07-16 11:54:44 +01001026 // Memory layout: fixed contents.
1027 typedef uint32_t OverallSizeType;
1028 typedef uint16_t EncodingInfoType;
1029 typedef uint32_t NumberOfLocationCatalogEntriesType;
1030 typedef uint32_t NumberOfStackMapsType;
1031 typedef uint32_t StackMaskSizeType;
1032
1033 // Memory (bit) layout: encoding info.
1034 static constexpr int HasInlineInfoBitSize = 1;
1035 static constexpr int InlineInfoBitSize = kNumberOfBitForNumberOfBytesForEncoding;
1036 static constexpr int DexRegisterMapBitSize = kNumberOfBitForNumberOfBytesForEncoding;
1037 static constexpr int DexPcBitSize = kNumberOfBitForNumberOfBytesForEncoding;
1038 static constexpr int NativePcBitSize = kNumberOfBitForNumberOfBytesForEncoding;
1039 static constexpr int RegisterMaskBitSize = kNumberOfBitForNumberOfBytesForEncoding;
1040
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001041 explicit CodeInfo(MemoryRegion region) : region_(region) {}
1042
Nicolas Geoffray39468442014-09-02 15:17:15 +01001043 explicit CodeInfo(const void* data) {
1044 uint32_t size = reinterpret_cast<const uint32_t*>(data)[0];
1045 region_ = MemoryRegion(const_cast<void*>(data), size);
1046 }
1047
David Brazdilf677ebf2015-05-29 16:29:43 +01001048 StackMapEncoding ExtractEncoding() const {
1049 return StackMapEncoding(region_.LoadUnaligned<uint32_t>(kStackMaskSizeOffset),
1050 GetNumberOfBytesForEncoding(kInlineInfoBitOffset),
1051 GetNumberOfBytesForEncoding(kDexRegisterMapBitOffset),
1052 GetNumberOfBytesForEncoding(kDexPcBitOffset),
1053 GetNumberOfBytesForEncoding(kNativePcBitOffset),
1054 GetNumberOfBytesForEncoding(kRegisterMaskBitOffset));
Nicolas Geoffray896f8f72015-03-30 15:44:25 +01001055 }
1056
David Brazdilf677ebf2015-05-29 16:29:43 +01001057 void SetEncoding(const StackMapEncoding& encoding) {
1058 region_.StoreUnaligned<uint32_t>(kStackMaskSizeOffset, encoding.NumberOfBytesForStackMask());
1059 region_.StoreBit(kHasInlineInfoBitOffset, encoding.NumberOfBytesForInlineInfo() != 0);
1060 SetEncodingAt(kInlineInfoBitOffset, encoding.NumberOfBytesForInlineInfo());
1061 SetEncodingAt(kDexRegisterMapBitOffset, encoding.NumberOfBytesForDexRegisterMap());
1062 SetEncodingAt(kDexPcBitOffset, encoding.NumberOfBytesForDexPc());
1063 SetEncodingAt(kNativePcBitOffset, encoding.NumberOfBytesForNativePc());
1064 SetEncodingAt(kRegisterMaskBitOffset, encoding.NumberOfBytesForRegisterMask());
Nicolas Geoffray896f8f72015-03-30 15:44:25 +01001065 }
1066
1067 void SetEncodingAt(size_t bit_offset, size_t number_of_bytes) {
Roland Levillaind780c002015-07-15 14:30:26 +01001068 region_.StoreBits(bit_offset, number_of_bytes, kNumberOfBitForNumberOfBytesForEncoding);
Nicolas Geoffray896f8f72015-03-30 15:44:25 +01001069 }
1070
1071 size_t GetNumberOfBytesForEncoding(size_t bit_offset) const {
Roland Levillaind780c002015-07-15 14:30:26 +01001072 return region_.LoadBits(bit_offset, kNumberOfBitForNumberOfBytesForEncoding);
Nicolas Geoffray004c2302015-03-20 10:06:38 +00001073 }
1074
1075 bool HasInlineInfo() const {
1076 return region_.LoadBit(kHasInlineInfoBitOffset);
1077 }
1078
David Brazdilf677ebf2015-05-29 16:29:43 +01001079 DexRegisterLocationCatalog GetDexRegisterLocationCatalog(const StackMapEncoding& encoding) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +00001080 return DexRegisterLocationCatalog(region_.Subregion(
David Brazdilf677ebf2015-05-29 16:29:43 +01001081 GetDexRegisterLocationCatalogOffset(encoding),
1082 GetDexRegisterLocationCatalogSize(encoding)));
Roland Levillaina552e1c2015-03-26 15:01:03 +00001083 }
1084
David Brazdilf677ebf2015-05-29 16:29:43 +01001085 StackMap GetStackMapAt(size_t i, const StackMapEncoding& encoding) const {
1086 size_t stack_map_size = encoding.ComputeStackMapSize();
1087 return StackMap(GetStackMaps(encoding).Subregion(i * stack_map_size, stack_map_size));
Nicolas Geoffray39468442014-09-02 15:17:15 +01001088 }
1089
Roland Levillain1c1da432015-07-16 11:54:44 +01001090 OverallSizeType GetOverallSize() const {
1091 return region_.LoadUnaligned<OverallSizeType>(kOverallSizeOffset);
Nicolas Geoffray39468442014-09-02 15:17:15 +01001092 }
1093
Roland Levillain1c1da432015-07-16 11:54:44 +01001094 void SetOverallSize(OverallSizeType size) {
1095 region_.StoreUnaligned<OverallSizeType>(kOverallSizeOffset, size);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001096 }
1097
Roland Levillain1c1da432015-07-16 11:54:44 +01001098 NumberOfLocationCatalogEntriesType GetNumberOfLocationCatalogEntries() const {
1099 return region_.LoadUnaligned<NumberOfLocationCatalogEntriesType>(
1100 kNumberOfLocationCatalogEntriesOffset);
Roland Levillaina552e1c2015-03-26 15:01:03 +00001101 }
1102
Roland Levillain1c1da432015-07-16 11:54:44 +01001103 void SetNumberOfLocationCatalogEntries(NumberOfLocationCatalogEntriesType num_entries) {
1104 region_.StoreUnaligned<NumberOfLocationCatalogEntriesType>(
1105 kNumberOfLocationCatalogEntriesOffset, num_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +00001106 }
1107
David Brazdilf677ebf2015-05-29 16:29:43 +01001108 uint32_t GetDexRegisterLocationCatalogSize(const StackMapEncoding& encoding) const {
1109 return ComputeDexRegisterLocationCatalogSize(GetDexRegisterLocationCatalogOffset(encoding),
Roland Levillain1c1da432015-07-16 11:54:44 +01001110 GetNumberOfLocationCatalogEntries());
Roland Levillaina552e1c2015-03-26 15:01:03 +00001111 }
1112
Roland Levillain1c1da432015-07-16 11:54:44 +01001113 NumberOfStackMapsType GetNumberOfStackMaps() const {
1114 return region_.LoadUnaligned<NumberOfStackMapsType>(kNumberOfStackMapsOffset);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001115 }
1116
Roland Levillain1c1da432015-07-16 11:54:44 +01001117 void SetNumberOfStackMaps(NumberOfStackMapsType number_of_stack_maps) {
1118 region_.StoreUnaligned<NumberOfStackMapsType>(kNumberOfStackMapsOffset, number_of_stack_maps);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001119 }
1120
David Brazdil77a48ae2015-09-15 12:34:04 +00001121 // Get the size of all the stack maps of this CodeInfo object, in bytes.
David Brazdilf677ebf2015-05-29 16:29:43 +01001122 size_t GetStackMapsSize(const StackMapEncoding& encoding) const {
1123 return encoding.ComputeStackMapSize() * GetNumberOfStackMaps();
Roland Levillain29ba1b02015-03-13 11:45:07 +00001124 }
1125
David Brazdilf677ebf2015-05-29 16:29:43 +01001126 uint32_t GetDexRegisterLocationCatalogOffset(const StackMapEncoding& encoding) const {
1127 return GetStackMapsOffset() + GetStackMapsSize(encoding);
Nicolas Geoffray004c2302015-03-20 10:06:38 +00001128 }
1129
David Brazdilf677ebf2015-05-29 16:29:43 +01001130 size_t GetDexRegisterMapsOffset(const StackMapEncoding& encoding) const {
1131 return GetDexRegisterLocationCatalogOffset(encoding)
1132 + GetDexRegisterLocationCatalogSize(encoding);
Roland Levillaina2d8ec62015-03-12 15:25:29 +00001133 }
1134
Nicolas Geoffray6530baf2015-05-26 15:22:58 +01001135 uint32_t GetStackMapsOffset() const {
1136 return kFixedSize;
1137 }
1138
David Brazdilf677ebf2015-05-29 16:29:43 +01001139 DexRegisterMap GetDexRegisterMapOf(StackMap stack_map,
1140 const StackMapEncoding& encoding,
1141 uint32_t number_of_dex_registers) const {
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +00001142 if (!stack_map.HasDexRegisterMap(encoding)) {
1143 return DexRegisterMap();
1144 } else {
1145 uint32_t offset = GetDexRegisterMapsOffset(encoding)
1146 + stack_map.GetDexRegisterMapOffset(encoding);
1147 size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
1148 return DexRegisterMap(region_.Subregion(offset, size));
1149 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001150 }
1151
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +01001152 // Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`.
1153 DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth,
1154 InlineInfo inline_info,
David Brazdilf677ebf2015-05-29 16:29:43 +01001155 const StackMapEncoding& encoding,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +01001156 uint32_t number_of_dex_registers) const {
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +00001157 if (!inline_info.HasDexRegisterMapAtDepth(depth)) {
1158 return DexRegisterMap();
1159 } else {
1160 uint32_t offset = GetDexRegisterMapsOffset(encoding)
1161 + inline_info.GetDexRegisterMapOffsetAtDepth(depth);
1162 size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
1163 return DexRegisterMap(region_.Subregion(offset, size));
1164 }
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +01001165 }
1166
David Brazdilf677ebf2015-05-29 16:29:43 +01001167 InlineInfo GetInlineInfoOf(StackMap stack_map, const StackMapEncoding& encoding) const {
1168 DCHECK(stack_map.HasInlineInfo(encoding));
1169 uint32_t offset = stack_map.GetInlineDescriptorOffset(encoding)
1170 + GetDexRegisterMapsOffset(encoding);
Nicolas Geoffray004c2302015-03-20 10:06:38 +00001171 uint8_t depth = region_.LoadUnaligned<uint8_t>(offset);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001172 return InlineInfo(region_.Subregion(offset,
1173 InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize()));
1174 }
1175
David Brazdilf677ebf2015-05-29 16:29:43 +01001176 StackMap GetStackMapForDexPc(uint32_t dex_pc, const StackMapEncoding& encoding) const {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001177 for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
David Brazdilf677ebf2015-05-29 16:29:43 +01001178 StackMap stack_map = GetStackMapAt(i, encoding);
1179 if (stack_map.GetDexPc(encoding) == dex_pc) {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001180 return stack_map;
1181 }
1182 }
Nicolas Geoffraye12997f2015-05-22 14:01:33 +01001183 return StackMap();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001184 }
1185
David Brazdil77a48ae2015-09-15 12:34:04 +00001186 // Searches the stack map list backwards because catch stack maps are stored
1187 // at the end.
1188 StackMap GetCatchStackMapForDexPc(uint32_t dex_pc, const StackMapEncoding& encoding) const {
1189 for (size_t i = GetNumberOfStackMaps(); i > 0; --i) {
1190 StackMap stack_map = GetStackMapAt(i - 1, encoding);
1191 if (stack_map.GetDexPc(encoding) == dex_pc) {
1192 return stack_map;
1193 }
1194 }
1195 return StackMap();
1196 }
1197
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +00001198 StackMap GetOsrStackMapForDexPc(uint32_t dex_pc, const StackMapEncoding& encoding) const {
1199 size_t e = GetNumberOfStackMaps();
1200 if (e == 0) {
1201 // There cannot be OSR stack map if there is no stack map.
1202 return StackMap();
1203 }
1204 // Walk over all stack maps. If two consecutive stack maps are identical, then we
1205 // have found a stack map suitable for OSR.
1206 for (size_t i = 0; i < e - 1; ++i) {
1207 StackMap stack_map = GetStackMapAt(i, encoding);
1208 if (stack_map.GetDexPc(encoding) == dex_pc) {
1209 StackMap other = GetStackMapAt(i + 1, encoding);
1210 if (other.GetDexPc(encoding) == dex_pc &&
1211 other.GetNativePcOffset(encoding) == stack_map.GetNativePcOffset(encoding)) {
1212 DCHECK_EQ(other.GetDexRegisterMapOffset(encoding),
1213 stack_map.GetDexRegisterMapOffset(encoding));
1214 DCHECK(!stack_map.HasInlineInfo(encoding));
1215 if (i < e - 2) {
1216 // Make sure there are not three identical stack maps following each other.
1217 DCHECK_NE(stack_map.GetNativePcOffset(encoding),
1218 GetStackMapAt(i + 2, encoding).GetNativePcOffset(encoding));
1219 }
1220 return stack_map;
1221 }
1222 }
1223 }
1224 return StackMap();
1225 }
1226
David Brazdilf677ebf2015-05-29 16:29:43 +01001227 StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset,
1228 const StackMapEncoding& encoding) const {
David Brazdil77a48ae2015-09-15 12:34:04 +00001229 // TODO: Safepoint stack maps are sorted by native_pc_offset but catch stack
1230 // maps are not. If we knew that the method does not have try/catch,
1231 // we could do binary search.
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001232 for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
David Brazdilf677ebf2015-05-29 16:29:43 +01001233 StackMap stack_map = GetStackMapAt(i, encoding);
1234 if (stack_map.GetNativePcOffset(encoding) == native_pc_offset) {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001235 return stack_map;
1236 }
1237 }
Nicolas Geoffraye12997f2015-05-22 14:01:33 +01001238 return StackMap();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001239 }
1240
Roland Levillainf2650d12015-05-28 14:53:28 +01001241 // Dump this CodeInfo object on `os`. `code_offset` is the (absolute)
1242 // native PC of the compiled method and `number_of_dex_registers` the
1243 // number of Dex virtual registers used in this method. If
1244 // `dump_stack_maps` is true, also dump the stack maps and the
1245 // associated Dex register maps.
Vladimir Marko8f1e08a2015-06-26 12:06:30 +01001246 void Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +01001247 uint32_t code_offset,
1248 uint16_t number_of_dex_registers,
1249 bool dump_stack_maps) const;
Nicolas Geoffray004c2302015-03-20 10:06:38 +00001250
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001251 private:
Nicolas Geoffray39468442014-09-02 15:17:15 +01001252 static constexpr int kOverallSizeOffset = 0;
Roland Levillain1c1da432015-07-16 11:54:44 +01001253 static constexpr int kEncodingInfoOffset = ELEMENT_BYTE_OFFSET_AFTER(OverallSize);
1254 static constexpr int kNumberOfLocationCatalogEntriesOffset =
1255 ELEMENT_BYTE_OFFSET_AFTER(EncodingInfo);
Roland Levillaina552e1c2015-03-26 15:01:03 +00001256 static constexpr int kNumberOfStackMapsOffset =
Roland Levillain1c1da432015-07-16 11:54:44 +01001257 ELEMENT_BYTE_OFFSET_AFTER(NumberOfLocationCatalogEntries);
1258 static constexpr int kStackMaskSizeOffset = ELEMENT_BYTE_OFFSET_AFTER(NumberOfStackMaps);
1259 static constexpr int kFixedSize = ELEMENT_BYTE_OFFSET_AFTER(StackMaskSize);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001260
Roland Levillain1c1da432015-07-16 11:54:44 +01001261 static constexpr int kHasInlineInfoBitOffset = kEncodingInfoOffset * kBitsPerByte;
1262 static constexpr int kInlineInfoBitOffset = ELEMENT_BIT_OFFSET_AFTER(HasInlineInfo);
1263 static constexpr int kDexRegisterMapBitOffset = ELEMENT_BIT_OFFSET_AFTER(InlineInfo);
1264 static constexpr int kDexPcBitOffset = ELEMENT_BIT_OFFSET_AFTER(DexRegisterMap);
1265 static constexpr int kNativePcBitOffset = ELEMENT_BIT_OFFSET_AFTER(DexPc);
1266 static constexpr int kRegisterMaskBitOffset = ELEMENT_BIT_OFFSET_AFTER(NativePc);
1267
1268 static constexpr int kEncodingInfoPastTheEndBitOffset = ELEMENT_BIT_OFFSET_AFTER(RegisterMask);
1269 static constexpr int kEncodingInfoOverallBitSize =
1270 kEncodingInfoPastTheEndBitOffset - kHasInlineInfoBitOffset;
1271
1272 static_assert(kEncodingInfoOverallBitSize <= (sizeof(EncodingInfoType) * kBitsPerByte),
1273 "art::CodeInfo::EncodingInfoType is too short to hold all encoding info elements.");
Nicolas Geoffray004c2302015-03-20 10:06:38 +00001274
David Brazdilf677ebf2015-05-29 16:29:43 +01001275 MemoryRegion GetStackMaps(const StackMapEncoding& encoding) const {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001276 return region_.size() == 0
1277 ? MemoryRegion()
David Brazdilf677ebf2015-05-29 16:29:43 +01001278 : region_.Subregion(GetStackMapsOffset(), GetStackMapsSize(encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001279 }
1280
Roland Levillaina552e1c2015-03-26 15:01:03 +00001281 // Compute the size of the Dex register map associated to the stack map at
1282 // `dex_register_map_offset_in_code_info`.
1283 size_t ComputeDexRegisterMapSizeOf(uint32_t dex_register_map_offset_in_code_info,
1284 uint16_t number_of_dex_registers) const {
1285 // Offset where the actual mapping data starts within art::DexRegisterMap.
1286 size_t location_mapping_data_offset_in_dex_register_map =
1287 DexRegisterMap::GetLocationMappingDataOffset(number_of_dex_registers);
1288 // Create a temporary art::DexRegisterMap to be able to call
1289 // art::DexRegisterMap::GetNumberOfLiveDexRegisters and
1290 DexRegisterMap dex_register_map_without_locations(
1291 MemoryRegion(region_.Subregion(dex_register_map_offset_in_code_info,
1292 location_mapping_data_offset_in_dex_register_map)));
1293 size_t number_of_live_dex_registers =
1294 dex_register_map_without_locations.GetNumberOfLiveDexRegisters(number_of_dex_registers);
1295 size_t location_mapping_data_size_in_bits =
Roland Levillain1c1da432015-07-16 11:54:44 +01001296 DexRegisterMap::SingleEntrySizeInBits(GetNumberOfLocationCatalogEntries())
Roland Levillaina552e1c2015-03-26 15:01:03 +00001297 * number_of_live_dex_registers;
1298 size_t location_mapping_data_size_in_bytes =
1299 RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
1300 size_t dex_register_map_size =
1301 location_mapping_data_offset_in_dex_register_map + location_mapping_data_size_in_bytes;
1302 return dex_register_map_size;
1303 }
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +00001304
Roland Levillaina552e1c2015-03-26 15:01:03 +00001305 // Compute the size of a Dex register location catalog starting at offset `origin`
1306 // in `region_` and containing `number_of_dex_locations` entries.
1307 size_t ComputeDexRegisterLocationCatalogSize(uint32_t origin,
1308 uint32_t number_of_dex_locations) const {
1309 // TODO: Ideally, we would like to use art::DexRegisterLocationCatalog::Size or
1310 // art::DexRegisterLocationCatalog::FindLocationOffset, but the
1311 // DexRegisterLocationCatalog is not yet built. Try to factor common code.
1312 size_t offset = origin + DexRegisterLocationCatalog::kFixedSize;
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +00001313
Roland Levillaina552e1c2015-03-26 15:01:03 +00001314 // Skip the first `number_of_dex_locations - 1` entries.
1315 for (uint16_t i = 0; i < number_of_dex_locations; ++i) {
1316 // Read the first next byte and inspect its first 3 bits to decide
1317 // whether it is a short or a large location.
1318 DexRegisterLocationCatalog::ShortLocation first_byte =
1319 region_.LoadUnaligned<DexRegisterLocationCatalog::ShortLocation>(offset);
1320 DexRegisterLocation::Kind kind =
1321 DexRegisterLocationCatalog::ExtractKindFromShortLocation(first_byte);
1322 if (DexRegisterLocation::IsShortLocationKind(kind)) {
1323 // Short location. Skip the current byte.
1324 offset += DexRegisterLocationCatalog::SingleShortEntrySize();
1325 } else {
1326 // Large location. Skip the 5 next bytes.
1327 offset += DexRegisterLocationCatalog::SingleLargeEntrySize();
Roland Levillaina2d8ec62015-03-12 15:25:29 +00001328 }
1329 }
1330 size_t size = offset - origin;
1331 return size;
1332 }
1333
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001334 MemoryRegion region_;
Nicolas Geoffray39468442014-09-02 15:17:15 +01001335 friend class StackMapStream;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001336};
1337
Roland Levillain1c1da432015-07-16 11:54:44 +01001338#undef ELEMENT_BYTE_OFFSET_AFTER
1339#undef ELEMENT_BIT_OFFSET_AFTER
1340
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001341} // namespace art
1342
1343#endif // ART_RUNTIME_STACK_MAP_H_