stack_map.h revision 896f8f7fe562f6e59119cb32531da9f0a5f13d18
199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/*
299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray *
499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * you may not use this file except in compliance with the License.
699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * You may obtain a copy of the License at
799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray *
899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray *
1099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Unless required by applicable law or agreed to in writing, software
1199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
1299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * See the License for the specific language governing permissions and
1499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * limitations under the License.
1599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
1699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
1799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#ifndef ART_RUNTIME_STACK_MAP_H_
1899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#define ART_RUNTIME_STACK_MAP_H_
1999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
2099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#include "base/bit_vector.h"
2199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#include "memory_region.h"
22376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray#include "utils.h"
2399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
2499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffraynamespace art {
2599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
26a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// Size of a frame slot, in bytes.  This constant is a signed value,
27a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// to please the compiler in arithmetic operations involving int32_t
28a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// (signed) values.
29a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainstatic constexpr ssize_t kFrameSlotSize = 4;
30a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
31fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray// Size of Dex virtual registers.
32a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainstatic constexpr size_t kVRegSize = 4;
33fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray
34004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffrayclass CodeInfo;
35004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
3699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
3799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Classes in the following file are wrapper on stack map information backed
3899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * by a MemoryRegion. As such they read and write to the region, they don't have
3999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * their own fields.
4099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
4199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
4299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
4399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Inline information for a specific PC. The information is of the form:
4499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * [inlining_depth, [method_dex reference]+]
4599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
4699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass InlineInfo {
4799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public:
4899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  explicit InlineInfo(MemoryRegion region) : region_(region) {}
4999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
5099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  uint8_t GetDepth() const {
51ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    return region_.LoadUnaligned<uint8_t>(kDepthOffset);
5299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
5399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
5499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetDepth(uint8_t depth) {
55ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    region_.StoreUnaligned<uint8_t>(kDepthOffset, depth);
5699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
5799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
5899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  uint32_t GetMethodReferenceIndexAtDepth(uint8_t depth) const {
59ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    return region_.LoadUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize());
6099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
6199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
6299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetMethodReferenceIndexAtDepth(uint8_t depth, uint32_t index) {
63ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    region_.StoreUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize(), index);
6499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
6599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
6699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static size_t SingleEntrySize() {
6799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return sizeof(uint32_t);
6899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
6999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
7099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private:
71a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Instead of plain types such as "uint8_t", introduce
72a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // typedefs (and document the memory layout of InlineInfo).
7399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kDepthOffset = 0;
7499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kFixedSize = kDepthOffset + sizeof(uint8_t);
7599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
7699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion region_;
7799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
783946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class CodeInfo;
793946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class StackMap;
803946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class StackMapStream;
8199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray};
8299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
83a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// Dex register location container used by DexRegisterMap and StackMapStream.
84a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillainclass DexRegisterLocation {
85a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain public:
86a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  /*
87a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * The location kind used to populate the Dex register information in a
88a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * StackMapStream can either be:
89a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kNone: the register has no location yet, meaning it has not been set;
90a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kConstant: value holds the constant;
91a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kStack: value holds the stack offset;
92a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kRegister: value holds the physical register number;
93a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kFpuRegister: value holds the physical register number.
94a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   *
95a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * In addition, DexRegisterMap also uses these values:
96a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kInStackLargeOffset: value holds a "large" stack offset (greater than
97a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain   *   or equal to 128 bytes);
98a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain   * - kConstantLargeValue: value holds a "large" constant (lower than 0, or
99a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain   *   or greater than or equal to 32).
100a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   */
101a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  enum class Kind : uint8_t {
102a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Short location kinds, for entries fitting on one byte (3 bits
103a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // for the kind, 5 bits for the value) in a DexRegisterMap.
104a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kNone = 0,                // 0b000
105a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInStack = 1,             // 0b001
106a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInRegister = 2,          // 0b010
107a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInFpuRegister = 3,       // 0b011
108a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kConstant = 4,            // 0b100
109a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
110a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Large location kinds, requiring a 5-byte encoding (1 byte for the
111a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // kind, 4 bytes for the value).
112a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
113a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Stack location at a large offset, meaning that the offset value
114a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // divided by the stack frame slot size (4 bytes) cannot fit on a
115a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // 5-bit unsigned integer (i.e., this offset value is greater than
116a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // or equal to 2^5 * 4 = 128 bytes).
117a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInStackLargeOffset = 5,  // 0b101
118a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
119a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Large constant, that cannot fit on a 5-bit signed integer (i.e.,
120a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // lower than 0, or greater than or equal to 2^5 = 32).
121a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kConstantLargeValue = 6,  // 0b110
122a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
123a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kLastLocationKind = kConstantLargeValue
124a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  };
125a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
126a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static_assert(
127a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      sizeof(Kind) == 1u,
128a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      "art::DexRegisterLocation::Kind has a size different from one byte.");
129a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
130a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static const char* PrettyDescriptor(Kind kind) {
131a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (kind) {
132a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kNone:
133a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "none";
134a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStack:
135a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in stack";
136a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInRegister:
137a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in register";
138a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInFpuRegister:
139a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in fpu register";
140a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstant:
141a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "as constant";
142a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStackLargeOffset:
143a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in stack (large offset)";
144a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstantLargeValue:
145a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "as constant (large value)";
146a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
147a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
148a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
149a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
150a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
151a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static bool IsShortLocationKind(Kind kind) {
152a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (kind) {
153a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kNone:
154a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStack:
155a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInRegister:
156a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInFpuRegister:
157a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstant:
158a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return true;
159a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
160a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStackLargeOffset:
161a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstantLargeValue:
162a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return false;
163a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
164a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
165a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
166a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
167a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
168a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
169a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Convert `kind` to a "surface" kind, i.e. one that doesn't include
170a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // any value with a "large" qualifier.
171a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Introduce another enum type for the surface kind?
172a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static Kind ConvertToSurfaceKind(Kind kind) {
173a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (kind) {
174a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kNone:
175a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStack:
176a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInRegister:
177a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInFpuRegister:
178a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstant:
179a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return kind;
180a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
181a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStackLargeOffset:
182a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return Kind::kInStack;
183a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
184a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstantLargeValue:
185a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return Kind::kConstant;
186a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
187a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
188a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
189a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
190a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
191a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
192a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Required by art::StackMapStream::LocationCatalogEntriesIndices.
193a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation() : kind_(Kind::kNone), value_(0) {}
194a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
195a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation(Kind kind, int32_t value) : kind_(kind), value_(value) {}
196a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
197fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  static DexRegisterLocation None() {
198fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    return DexRegisterLocation(Kind::kNone, 0);
199fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  }
200fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray
201a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Get the "surface" kind of the location, i.e., the one that doesn't
202a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // include any value with a "large" qualifier.
203a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  Kind GetKind() const {
204a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return ConvertToSurfaceKind(kind_);
205a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
206a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
207a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Get the value of the location.
208a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  int32_t GetValue() const { return value_; }
209a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
210a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Get the actual kind of the location.
211a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  Kind GetInternalKind() const { return kind_; }
212a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
2136ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle  bool operator==(DexRegisterLocation other) const {
2146ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle    return kind_ == other.kind_ && value_ == other.value_;
2156ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle  }
2166ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle
2176ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle  bool operator!=(DexRegisterLocation other) const {
2186ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle    return !(*this == other);
2196ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle  }
2206ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle
221a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain private:
222a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  Kind kind_;
223a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  int32_t value_;
224a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
225a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  friend class DexRegisterLocationHashFn;
226a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain};
227a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
22899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
229a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * Store information on unique Dex register locations used in a method.
230a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * The information is of the form:
231a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * [DexRegisterLocation+].
232fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind).
23399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
234a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainclass DexRegisterLocationCatalog {
23599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public:
236a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  explicit DexRegisterLocationCatalog(MemoryRegion region) : region_(region) {}
23799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
238a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Short (compressed) location, fitting on one byte.
239a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  typedef uint8_t ShortLocation;
240a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
241a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) {
242a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location);
243a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    int32_t value = dex_register_location.GetValue();
244a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    if (DexRegisterLocation::IsShortLocationKind(kind)) {
245a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Short location.  Compress the kind and the value as a single byte.
246a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStack) {
247a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Instead of storing stack offsets expressed in bytes for
248a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // short stack locations, store slot offsets.  A stack offset
249a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // is a multiple of 4 (kFrameSlotSize).  This means that by
250a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // dividing it by 4, we can fit values from the [0, 128)
251a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // interval in a short stack location, and not just values
252a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // from the [0, 32) interval.
253a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_EQ(value % kFrameSlotSize, 0);
254a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value /= kFrameSlotSize;
255a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
256a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      DCHECK(IsShortValue(value)) << value;
257a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value));
258a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    } else {
259a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Large location.  Write the location on one byte and the value
260a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // on 4 bytes.
261a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      DCHECK(!IsShortValue(value)) << value;
262a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
263a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Also divide large stack offsets by 4 for the sake of consistency.
264a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_EQ(value % kFrameSlotSize, 0);
265a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value /= kFrameSlotSize;
266a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
267a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Data can be unaligned as the written Dex register locations can
268a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // either be 1-byte or 5-byte wide.  Use
269a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // art::MemoryRegion::StoreUnaligned instead of
270a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // art::MemoryRegion::Store to prevent unligned word accesses on ARM.
271a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind);
272a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value);
273a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
274a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
27599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
276a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Find the offset of the location catalog entry number `location_catalog_entry_index`.
277a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t FindLocationOffset(size_t location_catalog_entry_index) const {
278a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    size_t offset = kFixedSize;
279a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // Skip the first `location_catalog_entry_index - 1` entries.
280a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    for (uint16_t i = 0; i < location_catalog_entry_index; ++i) {
281a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // Read the first next byte and inspect its first 3 bits to decide
282a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // whether it is a short or a large location.
283a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
284a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      if (DexRegisterLocation::IsShortLocationKind(kind)) {
285a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        // Short location.  Skip the current byte.
286a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        offset += SingleShortEntrySize();
287a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      } else {
288a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        // Large location.  Skip the 5 next bytes.
289a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        offset += SingleLargeEntrySize();
290a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
291442b46a087c389a91a0b51547ac9205058432364Roland Levillain    }
292a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return offset;
293442b46a087c389a91a0b51547ac9205058432364Roland Levillain  }
294442b46a087c389a91a0b51547ac9205058432364Roland Levillain
295a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the internal kind of entry at `location_catalog_entry_index`.
296a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation::Kind GetLocationInternalKind(size_t location_catalog_entry_index) const {
297a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (location_catalog_entry_index == kNoLocationEntryIndex) {
298a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      return DexRegisterLocation::Kind::kNone;
299a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
300a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return ExtractKindAtOffset(FindLocationOffset(location_catalog_entry_index));
30199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
30299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
303a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the (surface) kind and value of entry at `location_catalog_entry_index`.
304a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation GetDexRegisterLocation(size_t location_catalog_entry_index) const {
305a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (location_catalog_entry_index == kNoLocationEntryIndex) {
306fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray      return DexRegisterLocation::None();
307fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    }
308a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t offset = FindLocationOffset(location_catalog_entry_index);
309a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Read the first byte and inspect its first 3 bits to get the location.
310a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
311a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte);
312a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    if (DexRegisterLocation::IsShortLocationKind(kind)) {
313a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Short location.  Extract the value from the remaining 5 bits.
314a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      int32_t value = ExtractValueFromShortLocation(first_byte);
315a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStack) {
316a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Convert the stack slot (short) offset to a byte offset value.
317a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value *= kFrameSlotSize;
318a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
319a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      return DexRegisterLocation(kind, value);
320a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    } else {
321a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Large location.  Read the four next bytes to get the value.
322a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind));
323a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
324a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Convert the stack slot (large) offset to a byte offset value.
325a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value *= kFrameSlotSize;
326a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
327a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      return DexRegisterLocation(kind, value);
328a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
32999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
33099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
331a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Compute the compressed kind of `location`.
332a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) {
333a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (location.GetInternalKind()) {
334a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kNone:
335a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_EQ(location.GetValue(), 0);
336a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return DexRegisterLocation::Kind::kNone;
337a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
338a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInRegister:
339a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_GE(location.GetValue(), 0);
340a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        DCHECK_LT(location.GetValue(), 1 << kValueBits);
341a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return DexRegisterLocation::Kind::kInRegister;
342a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
343a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInFpuRegister:
344a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_GE(location.GetValue(), 0);
345a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        DCHECK_LT(location.GetValue(), 1 << kValueBits);
346a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return DexRegisterLocation::Kind::kInFpuRegister;
347a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
348a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInStack:
349a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        return IsShortStackOffsetValue(location.GetValue())
350a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            ? DexRegisterLocation::Kind::kInStack
351a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            : DexRegisterLocation::Kind::kInStackLargeOffset;
352a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
353a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kConstant:
354a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        return IsShortConstantValue(location.GetValue())
355a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            ? DexRegisterLocation::Kind::kConstant
356a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            : DexRegisterLocation::Kind::kConstantLargeValue;
357a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
358a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
359a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        LOG(FATAL) << "Unexpected location kind"
360a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain                   << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
361a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
362a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
363a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
364a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
365a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Can `location` be turned into a short location?
366a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) {
367a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (location.GetInternalKind()) {
368a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kNone:
369a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInRegister:
370a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInFpuRegister:
371a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return true;
372a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
373a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInStack:
374a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        return IsShortStackOffsetValue(location.GetValue());
375a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
376a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kConstant:
377a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        return IsShortConstantValue(location.GetValue());
378a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
379a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
380a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
381a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
382a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
383a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
384a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static size_t EntrySize(const DexRegisterLocation& location) {
385a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return CanBeEncodedAsShortLocation(location) ? SingleShortEntrySize() : SingleLargeEntrySize();
386a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
387a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
388a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static size_t SingleShortEntrySize() {
389a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return sizeof(ShortLocation);
390a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
391a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
392a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static size_t SingleLargeEntrySize() {
393a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t);
39499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
39599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
39612baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain  size_t Size() const {
39712baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain    return region_.size();
39812baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain  }
39912baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain
400a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Special (invalid) Dex register location catalog entry index meaning
401a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // that there is no location for a given Dex register (i.e., it is
402a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // mapped to a DexRegisterLocation::Kind::kNone location).
403a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr size_t kNoLocationEntryIndex = -1;
40499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
40512baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain private:
406a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr int kFixedSize = 0;
407a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
408a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Width of the kind "field" in a short location, in bits.
409a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kKindBits = 3;
410a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Width of the value "field" in a short location, in bits.
411a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kValueBits = 5;
412a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
413a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr uint8_t kKindMask = (1 << kKindBits) - 1;
414a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr int32_t kValueMask = (1 << kValueBits) - 1;
415a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kKindOffset = 0;
416a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kValueOffset = kKindBits;
417a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
418a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static bool IsShortStackOffsetValue(int32_t value) {
419a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK_EQ(value % kFrameSlotSize, 0);
420a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return IsShortValue(value / kFrameSlotSize);
421a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
422a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
423a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static bool IsShortConstantValue(int32_t value) {
424a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return IsShortValue(value);
425a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
426a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
427a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static bool IsShortValue(int32_t value) {
428a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return IsUint<kValueBits>(value);
429a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
430a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
431a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) {
432a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    uint8_t kind_integer_value = static_cast<uint8_t>(kind);
433a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK(IsUint<kKindBits>(kind_integer_value)) << kind_integer_value;
434a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK(IsShortValue(value)) << value;
435a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return (kind_integer_value & kKindMask) << kKindOffset
436a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        | (value & kValueMask) << kValueOffset;
437a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
438a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
439a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) {
440a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    uint8_t kind = (location >> kKindOffset) & kKindMask;
441a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind));
442fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    // We do not encode kNone locations in the stack map.
443fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone));
444a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return static_cast<DexRegisterLocation::Kind>(kind);
445a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
446a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
447a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static int32_t ExtractValueFromShortLocation(ShortLocation location) {
448a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return (location >> kValueOffset) & kValueMask;
449a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
450a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
451a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Extract a location kind from the byte at position `offset`.
452a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const {
453a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
454a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return ExtractKindFromShortLocation(first_byte);
455a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
456a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
45799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion region_;
458a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
459a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  friend class CodeInfo;
460a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  friend class StackMapStream;
46199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray};
46299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
463a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain/* Information on Dex register locations for a specific PC, mapping a
464a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * stack map's Dex register to a location entry in a DexRegisterLocationCatalog.
465a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * The information is of the form:
466a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * [live_bit_mask, entries*]
467a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * where entries are concatenated unsigned integer values encoded on a number
468a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * of bits (fixed per DexRegisterMap instances of a CodeInfo object) depending
469a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * on the number of entries in the Dex register location catalog
470a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * (see DexRegisterMap::SingleEntrySizeInBits).  The map is 1-byte aligned.
471a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain */
472a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainclass DexRegisterMap {
473a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain public:
474a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  explicit DexRegisterMap(MemoryRegion region) : region_(region) {}
475a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
476a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the surface kind of Dex register `dex_register_number`.
477a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number,
478a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                            uint16_t number_of_dex_registers,
479a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                            const CodeInfo& code_info) const {
480a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return DexRegisterLocation::ConvertToSurfaceKind(
481a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info));
482a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
483a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
484a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the internal kind of Dex register `dex_register_number`.
485a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number,
486a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                                    uint16_t number_of_dex_registers,
487a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                                    const CodeInfo& code_info) const;
488a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
489a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the Dex register location `dex_register_number`.
490a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number,
491a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                             uint16_t number_of_dex_registers,
492a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                             const CodeInfo& code_info) const;
493a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
494a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  int32_t GetStackOffsetInBytes(uint16_t dex_register_number,
495a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                uint16_t number_of_dex_registers,
496a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                const CodeInfo& code_info) const {
497a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DexRegisterLocation location =
498a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
499a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
500a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // GetDexRegisterLocation returns the offset in bytes.
501a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return location.GetValue();
502a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
503a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
504a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  int32_t GetConstant(uint16_t dex_register_number,
505a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                      uint16_t number_of_dex_registers,
506a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                      const CodeInfo& code_info) const {
507a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DexRegisterLocation location =
508a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
509a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant);
510a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return location.GetValue();
511a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
512a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
513a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  int32_t GetMachineRegister(uint16_t dex_register_number,
514a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                             uint16_t number_of_dex_registers,
515a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                             const CodeInfo& code_info) const {
516a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DexRegisterLocation location =
517a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
518a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister
519a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain           || location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister)
520a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
521a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return location.GetValue();
522a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
523a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
524a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the index of the entry in the Dex register location catalog
525a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // corresponding to `dex_register_number`.
526a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t GetLocationCatalogEntryIndex(uint16_t dex_register_number,
527a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                      uint16_t number_of_dex_registers,
528a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                      size_t number_of_location_catalog_entries) const {
529a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (!IsDexRegisterLive(dex_register_number)) {
530a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      return DexRegisterLocationCatalog::kNoLocationEntryIndex;
531a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
532a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
533a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (number_of_location_catalog_entries == 1) {
534a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // We do not allocate space for location maps in the case of a
535a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // single-entry location catalog, as it is useless.  The only valid
536a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // entry index is 0;
537a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      return 0;
538a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
539a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
540a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit offset of the beginning of the map locations.
541a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t map_locations_offset_in_bits =
542a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
543a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t index_in_dex_register_map = GetIndexInDexRegisterMap(dex_register_number);
544a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
545a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit size of an entry.
546a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
547a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit offset where `index_in_dex_register_map` is located.
548a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t entry_offset_in_bits =
549a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
550a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t location_catalog_entry_index =
551a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        region_.LoadBits(entry_offset_in_bits, map_entry_size_in_bits);
552a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
553a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return location_catalog_entry_index;
554a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
555a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
556a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Map entry at `index_in_dex_register_map` to `location_catalog_entry_index`.
557a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  void SetLocationCatalogEntryIndex(size_t index_in_dex_register_map,
558a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                    size_t location_catalog_entry_index,
559a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                    uint16_t number_of_dex_registers,
560a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                    size_t number_of_location_catalog_entries) {
561a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
562a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
563a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
564a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (number_of_location_catalog_entries == 1) {
565a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // We do not allocate space for location maps in the case of a
566a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // single-entry location catalog, as it is useless.
567a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      return;
568a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
569a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
570a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit offset of the beginning of the map locations.
571a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t map_locations_offset_in_bits =
572a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
573a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit size of an entry.
574a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
575a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit offset where `index_in_dex_register_map` is located.
576a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t entry_offset_in_bits =
577a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
578a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    region_.StoreBits(entry_offset_in_bits, location_catalog_entry_index, map_entry_size_in_bits);
579a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
580a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
581a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  void SetLiveBitMask(uint16_t number_of_dex_registers,
582a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                      const BitVector& live_dex_registers_mask) {
583a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
584a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    for (uint16_t i = 0; i < number_of_dex_registers; ++i) {
585a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      region_.StoreBit(live_bit_mask_offset_in_bits + i, live_dex_registers_mask.IsBitSet(i));
586a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
587a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
588a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
589a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  bool IsDexRegisterLive(uint16_t dex_register_number) const {
590a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
591a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return region_.LoadBit(live_bit_mask_offset_in_bits + dex_register_number);
592a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
593a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
594a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t GetNumberOfLiveDexRegisters(uint16_t number_of_dex_registers) const {
595a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t number_of_live_dex_registers = 0;
596a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    for (size_t i = 0; i < number_of_dex_registers; ++i) {
597a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      if (IsDexRegisterLive(i)) {
598a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        ++number_of_live_dex_registers;
599a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      }
600a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
601a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return number_of_live_dex_registers;
602a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
603a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
604a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static size_t GetLiveBitMaskOffset() {
605a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return kFixedSize;
606a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
607a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
608a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Compute the size of the live register bit mask (in bytes), for a
609a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // method having `number_of_dex_registers` Dex registers.
610a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static size_t GetLiveBitMaskSize(uint16_t number_of_dex_registers) {
611a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte;
612a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
613a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
614a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static size_t GetLocationMappingDataOffset(uint16_t number_of_dex_registers) {
615a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return GetLiveBitMaskOffset() + GetLiveBitMaskSize(number_of_dex_registers);
616a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
617a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
618a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t GetLocationMappingDataSize(uint16_t number_of_dex_registers,
619a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                    size_t number_of_location_catalog_entries) const {
620a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t location_mapping_data_size_in_bits =
621a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetNumberOfLiveDexRegisters(number_of_dex_registers)
622a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        * SingleEntrySizeInBits(number_of_location_catalog_entries);
623a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
624a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
625a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
626a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Return the size of a map entry in bits.  Note that if
627a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // `number_of_location_catalog_entries` equals 1, this function returns 0,
628a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // which is fine, as there is no need to allocate a map for a
629a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // single-entry location catalog; the only valid location catalog entry index
630a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // for a live register in this case is 0 and there is no need to
631a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // store it.
632a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static size_t SingleEntrySizeInBits(size_t number_of_location_catalog_entries) {
633a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // Handle the case of 0, as we cannot pass 0 to art::WhichPowerOf2.
634a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return number_of_location_catalog_entries == 0
635a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        ? 0u
636a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        : WhichPowerOf2(RoundUpToPowerOfTwo(number_of_location_catalog_entries));
637a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
638a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
639a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Return the size of the DexRegisterMap object, in bytes.
640a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t Size() const {
641a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return region_.size();
642a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
643a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
644a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain private:
645a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Return the index in the Dex register map corresponding to the Dex
646a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // register number `dex_register_number`.
647a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t GetIndexInDexRegisterMap(uint16_t dex_register_number) const {
648a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (!IsDexRegisterLive(dex_register_number)) {
649a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      return kInvalidIndexInDexRegisterMap;
650a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
651a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return GetNumberOfLiveDexRegisters(dex_register_number);
652a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
653a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
654a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Special (invalid) Dex register map entry index meaning that there
655a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // is no index in the map for a given Dex register (i.e., it must
656a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // have been mapped to a DexRegisterLocation::Kind::kNone location).
657a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr size_t kInvalidIndexInDexRegisterMap = -1;
658a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
659a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr int kFixedSize = 0;
660a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
661a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  MemoryRegion region_;
662a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
663a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  friend class CodeInfo;
664a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  friend class StackMapStream;
665a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain};
666a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
66799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
66899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * A Stack Map holds compilation information for a specific PC necessary for:
66999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Mapping it to a dex PC,
67099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which stack entries are objects,
67199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which registers hold objects,
67299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the inlining information,
67399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the values of dex registers.
67499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray *
67599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form:
676a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask,
677a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * stack_mask].
67899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray *
67999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Note that register_mask is fixed size, but stack_mask is variable size, depending on the
68099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * stack size of a method.
68199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
68299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass StackMap {
68399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public:
68499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  explicit StackMap(MemoryRegion region) : region_(region) {}
68599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
686004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  uint32_t GetDexPc(const CodeInfo& info) const;
68799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
688004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetDexPc(const CodeInfo& info, uint32_t dex_pc);
68999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
690004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  uint32_t GetNativePcOffset(const CodeInfo& info) const;
69199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
692004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetNativePcOffset(const CodeInfo& info, uint32_t native_pc_offset);
69399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
694004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  uint32_t GetDexRegisterMapOffset(const CodeInfo& info) const;
69599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
696004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetDexRegisterMapOffset(const CodeInfo& info, uint32_t offset);
69799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
698004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  uint32_t GetInlineDescriptorOffset(const CodeInfo& info) const;
69999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
700004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetInlineDescriptorOffset(const CodeInfo& info, uint32_t offset);
70199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
702004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  uint32_t GetRegisterMask(const CodeInfo& info) const;
70399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
704004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetRegisterMask(const CodeInfo& info, uint32_t mask);
70599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
706004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  MemoryRegion GetStackMask(const CodeInfo& info) const;
70799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
708004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetStackMask(const CodeInfo& info, const BitVector& sp_map) {
709004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    MemoryRegion region = GetStackMask(info);
71099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    for (size_t i = 0; i < region.size_in_bits(); i++) {
71199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray      region.StoreBit(i, sp_map.IsBitSet(i));
71299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    }
71399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
71499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
715004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  bool HasDexRegisterMap(const CodeInfo& info) const {
716004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return GetDexRegisterMapOffset(info) != kNoDexRegisterMap;
717442b46a087c389a91a0b51547ac9205058432364Roland Levillain  }
718442b46a087c389a91a0b51547ac9205058432364Roland Levillain
719004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  bool HasInlineInfo(const CodeInfo& info) const {
720004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return GetInlineDescriptorOffset(info) != kNoInlineInfo;
72199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
72299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
723442b46a087c389a91a0b51547ac9205058432364Roland Levillain  bool Equals(const StackMap& other) const {
72499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return region_.pointer() == other.region_.pointer()
72599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray       && region_.size() == other.region_.size();
72699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
72799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
728004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  static size_t ComputeStackMapSize(size_t stack_mask_size,
729004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray                                    size_t inline_info_size,
730004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray                                    size_t dex_register_map_size,
731004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray                                    size_t dex_pc_max,
732896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                    size_t native_pc_max,
733896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                    size_t register_mask_max);
734376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray
735442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // Special (invalid) offset for the DexRegisterMapOffset field meaning
736442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // that there is no Dex register map for this stack map.
737442b46a087c389a91a0b51547ac9205058432364Roland Levillain  static constexpr uint32_t kNoDexRegisterMap = -1;
738442b46a087c389a91a0b51547ac9205058432364Roland Levillain
739442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // Special (invalid) offset for the InlineDescriptorOffset field meaning
740442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // that there is no inline info for this stack map.
741442b46a087c389a91a0b51547ac9205058432364Roland Levillain  static constexpr uint32_t kNoInlineInfo = -1;
742442b46a087c389a91a0b51547ac9205058432364Roland Levillain
74399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private:
744896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static size_t ComputeStackMapSizeInternal(size_t stack_mask_size,
745896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                            size_t number_of_bytes_for_inline_info,
746896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                            size_t number_of_bytes_for_dex_map,
747896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                            size_t number_of_bytes_for_dex_pc,
748896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                            size_t number_of_bytes_for_native_pc,
749896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                            size_t number_of_bytes_for_register_mask);
750896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray
751a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Instead of plain types such as "uint32_t", introduce
752a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // typedefs (and document the memory layout of StackMap).
753004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  static constexpr int kRegisterMaskOffset = 0;
754896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kFixedSize = 0;
75599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
75699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion region_;
75799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
7583946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class CodeInfo;
7593946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class StackMapStream;
76099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray};
76199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
76299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
76399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
76499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Wrapper around all compiler information collected for a method.
76599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form:
766a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * [overall_size, number_of_location_catalog_entries, number_of_stack_maps, stack_mask_size,
767a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * DexRegisterLocationCatalog+, StackMap+, DexRegisterMap+, InlineInfo*].
76899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
76999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass CodeInfo {
77099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public:
77199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  explicit CodeInfo(MemoryRegion region) : region_(region) {}
77299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
7733946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  explicit CodeInfo(const void* data) {
7743946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    uint32_t size = reinterpret_cast<const uint32_t*>(data)[0];
7753946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    region_ = MemoryRegion(const_cast<void*>(data), size);
7763946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
7773946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
778896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static size_t EncodingSizeInBytes(size_t max_element) {
779896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    DCHECK(IsUint<32>(max_element));
780896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return (max_element == 0) ? 0
781896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray         : IsUint<8>(max_element) ? 1
782896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray         : IsUint<16>(max_element) ? 2
783896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray         : IsUint<24>(max_element) ? 3
784896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray         : 4;
785896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  }
786896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray
787004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetEncoding(size_t inline_info_size,
788004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray                   size_t dex_register_map_size,
789004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray                   size_t dex_pc_max,
790896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                   size_t native_pc_max,
791896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                   size_t register_mask_max) {
792004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    if (inline_info_size != 0) {
793004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray      region_.StoreBit(kHasInlineInfoBitOffset, 1);
794896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      // + 1 to also encode kNoInlineInfo: if an inline info offset
795896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      // is at 0xFF, we want to overflow to a larger encoding, because it will
796896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      // conflict with kNoInlineInfo.
797896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      // The offset is relative to the dex register map. TODO: Change this.
798896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      SetEncodingAt(kInlineInfoBitOffset,
799896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                    EncodingSizeInBytes(dex_register_map_size + inline_info_size + 1));
800004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    } else {
801004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray      region_.StoreBit(kHasInlineInfoBitOffset, 0);
802896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      SetEncodingAt(kInlineInfoBitOffset, 0);
803004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    }
804896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    // + 1 to also encode kNoDexRegisterMap: if a dex register map offset
805896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    // is at 0xFF, we want to overflow to a larger encoding, because it will
806896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    // conflict with kNoDexRegisterMap.
807896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    SetEncodingAt(kDexRegisterMapBitOffset, EncodingSizeInBytes(dex_register_map_size + 1));
808896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    SetEncodingAt(kDexPcBitOffset, EncodingSizeInBytes(dex_pc_max));
809896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    SetEncodingAt(kNativePcBitOffset, EncodingSizeInBytes(native_pc_max));
810896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    SetEncodingAt(kRegisterMaskBitOffset, EncodingSizeInBytes(register_mask_max));
811896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  }
812896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray
813896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  void SetEncodingAt(size_t bit_offset, size_t number_of_bytes) {
814896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    // We encode the number of bytes needed for writing a value on 3 bits,
815896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    // for values that we know are maximum 32bits.
816896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    region_.StoreBit(bit_offset, (number_of_bytes & 1));
817896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    region_.StoreBit(bit_offset + 1, (number_of_bytes & 2));
818896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    region_.StoreBit(bit_offset + 2, (number_of_bytes & 4));
819896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  }
820896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray
821896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t GetNumberOfBytesForEncoding(size_t bit_offset) const {
822896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return region_.LoadBit(bit_offset)
823896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (region_.LoadBit(bit_offset + 1) << 1)
824896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (region_.LoadBit(bit_offset + 2) << 2);
825004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
826004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
827004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  bool HasInlineInfo() const {
828004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return region_.LoadBit(kHasInlineInfoBitOffset);
829004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
830004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
831896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t NumberOfBytesForInlineInfo() const {
832896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return GetNumberOfBytesForEncoding(kInlineInfoBitOffset);
833896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  }
834896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray
835896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t NumberOfBytesForDexRegisterMap() const {
836896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return GetNumberOfBytesForEncoding(kDexRegisterMapBitOffset);
837004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
838004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
839896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t NumberOfBytesForRegisterMask() const {
840896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return GetNumberOfBytesForEncoding(kRegisterMaskBitOffset);
841004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
842004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
843896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t NumberOfBytesForNativePc() const {
844896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return GetNumberOfBytesForEncoding(kNativePcBitOffset);
845004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
846004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
847896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t NumberOfBytesForDexPc() const {
848896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return GetNumberOfBytesForEncoding(kDexPcBitOffset);
849004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
850004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
851004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapRegisterMaskOffset() const {
852004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return StackMap::kRegisterMaskOffset;
853004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
854004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
855004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapStackMaskOffset() const {
856896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return ComputeStackMapRegisterMaskOffset()
857896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (NumberOfBytesForRegisterMask() * sizeof(uint8_t));
858004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
859004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
860004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapDexPcOffset() const {
861004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return ComputeStackMapStackMaskOffset() + GetStackMaskSize();
862004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
863004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
864004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapNativePcOffset() const {
865004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return ComputeStackMapDexPcOffset()
866896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (NumberOfBytesForDexPc() * sizeof(uint8_t));
867004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
868004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
869004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapDexRegisterMapOffset() const {
870004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return ComputeStackMapNativePcOffset()
871896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (NumberOfBytesForNativePc() * sizeof(uint8_t));
872004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
873004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
874004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapInlineInfoOffset() const {
875004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    CHECK(HasInlineInfo());
876004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return ComputeStackMapDexRegisterMapOffset()
877896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (NumberOfBytesForDexRegisterMap() * sizeof(uint8_t));
878004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
879004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
880a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  uint32_t GetDexRegisterLocationCatalogOffset() const {
881a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return kFixedSize;
882a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
883a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
884a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocationCatalog GetDexRegisterLocationCatalog() const {
885a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return DexRegisterLocationCatalog(region_.Subregion(
886a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetDexRegisterLocationCatalogOffset(),
887a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetDexRegisterLocationCatalogSize()));
888a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
889a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
8903946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  StackMap GetStackMapAt(size_t i) const {
89199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    size_t size = StackMapSize();
8923946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    return StackMap(GetStackMaps().Subregion(i * size, size));
8933946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
8943946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
8953946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  uint32_t GetOverallSize() const {
896aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    return region_.LoadUnaligned<uint32_t>(kOverallSizeOffset);
8973946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
8983946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
8993946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  void SetOverallSize(uint32_t size) {
900aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    region_.StoreUnaligned<uint32_t>(kOverallSizeOffset, size);
90199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
90299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
903a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  uint32_t GetNumberOfDexRegisterLocationCatalogEntries() const {
904a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return region_.LoadUnaligned<uint32_t>(kNumberOfDexRegisterLocationCatalogEntriesOffset);
905a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
906a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
907a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  void SetNumberOfDexRegisterLocationCatalogEntries(uint32_t num_entries) {
908a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    region_.StoreUnaligned<uint32_t>(kNumberOfDexRegisterLocationCatalogEntriesOffset, num_entries);
909a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
910a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
911a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  uint32_t GetDexRegisterLocationCatalogSize() const {
912a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return ComputeDexRegisterLocationCatalogSize(GetDexRegisterLocationCatalogOffset(),
913a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                                 GetNumberOfDexRegisterLocationCatalogEntries());
914a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
915a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
91699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  uint32_t GetStackMaskSize() const {
917aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    return region_.LoadUnaligned<uint32_t>(kStackMaskSizeOffset);
91899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
91999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
92099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetStackMaskSize(uint32_t size) {
921aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    region_.StoreUnaligned<uint32_t>(kStackMaskSizeOffset, size);
92299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
92399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
92499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  size_t GetNumberOfStackMaps() const {
925aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    return region_.LoadUnaligned<uint32_t>(kNumberOfStackMapsOffset);
92699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
92799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
92899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetNumberOfStackMaps(uint32_t number_of_stack_maps) {
929aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    region_.StoreUnaligned<uint32_t>(kNumberOfStackMapsOffset, number_of_stack_maps);
93099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
93199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
93229ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  // Get the size of one stack map of this CodeInfo object, in bytes.
93329ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  // All stack maps of a CodeInfo have the same size.
93499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  size_t StackMapSize() const {
935896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return StackMap::ComputeStackMapSizeInternal(GetStackMaskSize(),
936896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                                 NumberOfBytesForInlineInfo(),
937896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                                 NumberOfBytesForDexRegisterMap(),
938896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                                 NumberOfBytesForDexPc(),
939896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                                 NumberOfBytesForNativePc(),
940896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                                 NumberOfBytesForRegisterMask());
94199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
94299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
94329ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  // Get the size all the stack maps of this CodeInfo object, in bytes.
944a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t GetStackMapsSize() const {
94529ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain    return StackMapSize() * GetNumberOfStackMaps();
94629ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  }
94729ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain
948004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t GetDexRegisterMapsOffset() const {
949a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return GetStackMapsOffset() + GetStackMapsSize();
950004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
951004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
952a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  uint32_t GetStackMapsOffset() const {
953a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return GetDexRegisterLocationCatalogOffset() + GetDexRegisterLocationCatalogSize();
954a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
955a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
956442b46a087c389a91a0b51547ac9205058432364Roland Levillain  DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) const {
957004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    DCHECK(stack_map.HasDexRegisterMap(*this));
958a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    uint32_t offset = GetDexRegisterMapsOffset() + stack_map.GetDexRegisterMapOffset(*this);
959a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
960a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return DexRegisterMap(region_.Subregion(offset, size));
96199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
96299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
963442b46a087c389a91a0b51547ac9205058432364Roland Levillain  InlineInfo GetInlineInfoOf(StackMap stack_map) const {
964004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    DCHECK(stack_map.HasInlineInfo(*this));
965004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    uint32_t offset = stack_map.GetInlineDescriptorOffset(*this) + GetDexRegisterMapsOffset();
966004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    uint8_t depth = region_.LoadUnaligned<uint8_t>(offset);
96799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return InlineInfo(region_.Subregion(offset,
96899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize()));
96999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
97099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
971442b46a087c389a91a0b51547ac9205058432364Roland Levillain  StackMap GetStackMapForDexPc(uint32_t dex_pc) const {
97299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
9733946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      StackMap stack_map = GetStackMapAt(i);
974004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray      if (stack_map.GetDexPc(*this) == dex_pc) {
97599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        return stack_map;
97699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray      }
97799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    }
97899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    LOG(FATAL) << "Unreachable";
9792c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers    UNREACHABLE();
98099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
98199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
982442b46a087c389a91a0b51547ac9205058432364Roland Levillain  StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) const {
98399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    // TODO: stack maps are sorted by native pc, we can do a binary search.
98499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
9853946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      StackMap stack_map = GetStackMapAt(i);
986004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray      if (stack_map.GetNativePcOffset(*this) == native_pc_offset) {
98799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        return stack_map;
98899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray      }
98999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    }
99099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    LOG(FATAL) << "Unreachable";
9912c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers    UNREACHABLE();
99299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
99399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
994004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void Dump(std::ostream& os, uint16_t number_of_dex_registers) const;
995004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const;
996004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
99799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private:
998a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Instead of plain types such as "uint32_t", introduce
999a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // typedefs (and document the memory layout of CodeInfo).
10003946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  static constexpr int kOverallSizeOffset = 0;
1001004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  static constexpr int kEncodingInfoOffset = kOverallSizeOffset + sizeof(uint32_t);
1002a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr int kNumberOfDexRegisterLocationCatalogEntriesOffset =
1003896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      kEncodingInfoOffset + sizeof(uint16_t);
1004a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr int kNumberOfStackMapsOffset =
1005a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      kNumberOfDexRegisterLocationCatalogEntriesOffset + sizeof(uint32_t);
100699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kStackMaskSizeOffset = kNumberOfStackMapsOffset + sizeof(uint32_t);
100799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kFixedSize = kStackMaskSizeOffset + sizeof(uint32_t);
100899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
1009004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  static constexpr int kHasInlineInfoBitOffset = (kEncodingInfoOffset * kBitsPerByte);
1010896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kInlineInfoBitOffset = kHasInlineInfoBitOffset + 1;
1011896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kDexRegisterMapBitOffset = kInlineInfoBitOffset + 3;
1012896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kDexPcBitOffset = kDexRegisterMapBitOffset + 3;
1013896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kNativePcBitOffset = kDexPcBitOffset + 3;
1014896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kRegisterMaskBitOffset = kNativePcBitOffset + 3;
1015004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
101699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion GetStackMaps() const {
101799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return region_.size() == 0
101899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        ? MemoryRegion()
1019a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        : region_.Subregion(GetStackMapsOffset(), GetStackMapsSize());
1020a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
1021a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
1022a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Compute the size of the Dex register map associated to the stack map at
1023a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // `dex_register_map_offset_in_code_info`.
1024a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t ComputeDexRegisterMapSizeOf(uint32_t dex_register_map_offset_in_code_info,
1025a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                     uint16_t number_of_dex_registers) const {
1026a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // Offset where the actual mapping data starts within art::DexRegisterMap.
1027a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t location_mapping_data_offset_in_dex_register_map =
1028a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        DexRegisterMap::GetLocationMappingDataOffset(number_of_dex_registers);
1029a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // Create a temporary art::DexRegisterMap to be able to call
1030a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // art::DexRegisterMap::GetNumberOfLiveDexRegisters and
1031a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DexRegisterMap dex_register_map_without_locations(
1032a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        MemoryRegion(region_.Subregion(dex_register_map_offset_in_code_info,
1033a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                       location_mapping_data_offset_in_dex_register_map)));
1034a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t number_of_live_dex_registers =
1035a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        dex_register_map_without_locations.GetNumberOfLiveDexRegisters(number_of_dex_registers);
1036a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t location_mapping_data_size_in_bits =
1037a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        DexRegisterMap::SingleEntrySizeInBits(GetNumberOfDexRegisterLocationCatalogEntries())
1038a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        * number_of_live_dex_registers;
1039a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t location_mapping_data_size_in_bytes =
1040a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
1041a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t dex_register_map_size =
1042a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        location_mapping_data_offset_in_dex_register_map + location_mapping_data_size_in_bytes;
1043a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return dex_register_map_size;
1044a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
1045a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
1046a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Compute the size of a Dex register location catalog starting at offset `origin`
1047a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // in `region_` and containing `number_of_dex_locations` entries.
1048a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t ComputeDexRegisterLocationCatalogSize(uint32_t origin,
1049a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                               uint32_t number_of_dex_locations) const {
1050a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // TODO: Ideally, we would like to use art::DexRegisterLocationCatalog::Size or
1051a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // art::DexRegisterLocationCatalog::FindLocationOffset, but the
1052a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // DexRegisterLocationCatalog is not yet built.  Try to factor common code.
1053a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t offset = origin + DexRegisterLocationCatalog::kFixedSize;
1054a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
1055a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // Skip the first `number_of_dex_locations - 1` entries.
1056a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    for (uint16_t i = 0; i < number_of_dex_locations; ++i) {
1057a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // Read the first next byte and inspect its first 3 bits to decide
1058a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // whether it is a short or a large location.
1059a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      DexRegisterLocationCatalog::ShortLocation first_byte =
1060a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain          region_.LoadUnaligned<DexRegisterLocationCatalog::ShortLocation>(offset);
1061a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      DexRegisterLocation::Kind kind =
1062a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain          DexRegisterLocationCatalog::ExtractKindFromShortLocation(first_byte);
1063a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      if (DexRegisterLocation::IsShortLocationKind(kind)) {
1064a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        // Short location.  Skip the current byte.
1065a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        offset += DexRegisterLocationCatalog::SingleShortEntrySize();
1066a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      } else {
1067a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        // Large location.  Skip the 5 next bytes.
1068a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        offset += DexRegisterLocationCatalog::SingleLargeEntrySize();
1069a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
1070a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
1071a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    size_t size = offset - origin;
1072a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return size;
1073a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
1074a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
107599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion region_;
10763946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class StackMapStream;
107799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray};
107899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
107999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}  // namespace art
108099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
108199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#endif  // ART_RUNTIME_STACK_MAP_H_
1082