stack_map.h revision fead4e4f397455aa31905b2982d4d861126ab89d
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.
29a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillainstatic ssize_t constexpr kFrameSlotSize = 4;
30a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
319ac0e4d4ed1b45cf8767ef1d339afcdd205bf55aRoland Levillain// Word alignment required on ARM, in bytes.
329ac0e4d4ed1b45cf8767ef1d339afcdd205bf55aRoland Levillainstatic constexpr size_t kWordAlignment = 4;
339ac0e4d4ed1b45cf8767ef1d339afcdd205bf55aRoland Levillain
34fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray// Size of Dex virtual registers.
35fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffraystatic size_t constexpr kVRegSize = 4;
36fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray
3799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
3899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Classes in the following file are wrapper on stack map information backed
3999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * by a MemoryRegion. As such they read and write to the region, they don't have
4099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * their own fields.
4199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
4299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
4399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
4499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Inline information for a specific PC. The information is of the form:
4599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * [inlining_depth, [method_dex reference]+]
4699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
4799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass InlineInfo {
4899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public:
4999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  explicit InlineInfo(MemoryRegion region) : region_(region) {}
5099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
5199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  uint8_t GetDepth() const {
52ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    return region_.LoadUnaligned<uint8_t>(kDepthOffset);
5399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
5499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
5599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetDepth(uint8_t depth) {
56ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    region_.StoreUnaligned<uint8_t>(kDepthOffset, depth);
5799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
5899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
5999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  uint32_t GetMethodReferenceIndexAtDepth(uint8_t depth) const {
60ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    return region_.LoadUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize());
6199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
6299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
6399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetMethodReferenceIndexAtDepth(uint8_t depth, uint32_t index) {
64ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    region_.StoreUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize(), index);
6599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
6699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
6799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static size_t SingleEntrySize() {
6899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return sizeof(uint32_t);
6999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
7099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
7199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private:
72a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Instead of plain types such as "uint8_t", introduce
73a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // typedefs (and document the memory layout of InlineInfo).
7499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kDepthOffset = 0;
7599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kFixedSize = kDepthOffset + sizeof(uint8_t);
7699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
7799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion region_;
7899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
793946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class CodeInfo;
803946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class StackMap;
813946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class StackMapStream;
8299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray};
8399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
84a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// Dex register location container used by DexRegisterMap and StackMapStream.
85a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillainclass DexRegisterLocation {
86a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain public:
87a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  /*
88a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * The location kind used to populate the Dex register information in a
89a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * StackMapStream can either be:
90a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kNone: the register has no location yet, meaning it has not been set;
91a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kConstant: value holds the constant;
92a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kStack: value holds the stack offset;
93a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kRegister: value holds the physical register number;
94a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kFpuRegister: value holds the physical register number.
95a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   *
96a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * In addition, DexRegisterMap also uses these values:
97a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kInStackLargeOffset: value holds a "large" stack offset (greater than
98a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   *   128 bytes);
99a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kConstantLargeValue: value holds a "large" constant (lower than or
100a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   *   equal to -16, or greater than 16).
101a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   */
102a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  enum class Kind : uint8_t {
103a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Short location kinds, for entries fitting on one byte (3 bits
104a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // for the kind, 5 bits for the value) in a DexRegisterMap.
105a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kNone = 0,                // 0b000
106a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInStack = 1,             // 0b001
107a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInRegister = 2,          // 0b010
108a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInFpuRegister = 3,       // 0b011
109a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kConstant = 4,            // 0b100
110a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
111a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Large location kinds, requiring a 5-byte encoding (1 byte for the
112a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // kind, 4 bytes for the value).
113a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
114a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Stack location at a large offset, meaning that the offset value
115a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // divided by the stack frame slot size (4 bytes) cannot fit on a
116a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // 5-bit unsigned integer (i.e., this offset value is greater than
117a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // or equal to 2^5 * 4 = 128 bytes).
118a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInStackLargeOffset = 5,  // 0b101
119a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
120a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Large constant, that cannot fit on a 5-bit signed integer (i.e.,
121a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // lower than -2^(5-1) = -16, or greater than or equal to
122a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // 2^(5-1) - 1 = 15).
123a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kConstantLargeValue = 6,  // 0b110
124a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
125a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kLastLocationKind = kConstantLargeValue
126a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  };
127a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
128a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static_assert(
129a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      sizeof(Kind) == 1u,
130a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      "art::DexRegisterLocation::Kind has a size different from one byte.");
131a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
132a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static const char* PrettyDescriptor(Kind kind) {
133a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (kind) {
134a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kNone:
135a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "none";
136a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStack:
137a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in stack";
138a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInRegister:
139a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in register";
140a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInFpuRegister:
141a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in fpu register";
142a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstant:
143a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "as constant";
144a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStackLargeOffset:
145a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in stack (large offset)";
146a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstantLargeValue:
147a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "as constant (large value)";
148a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
149a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
150a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
151a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
152a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
153a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static bool IsShortLocationKind(Kind kind) {
154a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (kind) {
155a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kNone:
156a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStack:
157a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInRegister:
158a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInFpuRegister:
159a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstant:
160a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return true;
161a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
162a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStackLargeOffset:
163a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstantLargeValue:
164a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return false;
165a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
166a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
167a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
168a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
169a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
170a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
171a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Convert `kind` to a "surface" kind, i.e. one that doesn't include
172a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // any value with a "large" qualifier.
173a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Introduce another enum type for the surface kind?
174a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static Kind ConvertToSurfaceKind(Kind kind) {
175a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (kind) {
176a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kNone:
177a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStack:
178a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInRegister:
179a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInFpuRegister:
180a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstant:
181a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return kind;
182a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
183a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStackLargeOffset:
184a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return Kind::kInStack;
185a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
186a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstantLargeValue:
187a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return Kind::kConstant;
188a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
189a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
190a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
191a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
192a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
193a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
194a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  DexRegisterLocation(Kind kind, int32_t value)
195a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      : 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
213a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain private:
214a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  Kind kind_;
215a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  int32_t value_;
216a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain};
217a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
21899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
21999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Information on dex register values for a specific PC. The information is
22099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * of the form:
221fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray * [live_bit_mask, DexRegisterLocation+].
222fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind).
22399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
22499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass DexRegisterMap {
22599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public:
22699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  explicit DexRegisterMap(MemoryRegion region) : region_(region) {}
22799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
228a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Short (compressed) location, fitting on one byte.
229a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  typedef uint8_t ShortLocation;
230a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
231fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  static size_t LiveBitMaskSize(uint16_t number_of_dex_registers) {
232fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte;
233fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  }
234fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray
235fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  void SetLiveBitMask(size_t offset,
236fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray                      uint16_t number_of_dex_registers,
237fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray                      const BitVector& live_dex_registers_mask) {
238fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    for (uint16_t i = 0; i < number_of_dex_registers; i++) {
239fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray      region_.StoreBit(offset + i, live_dex_registers_mask.IsBitSet(i));
240fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    }
241fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  }
242fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray
243a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) {
244a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location);
245a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    int32_t value = dex_register_location.GetValue();
246a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    if (DexRegisterLocation::IsShortLocationKind(kind)) {
247a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Short location.  Compress the kind and the value as a single byte.
248a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStack) {
249a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Instead of storing stack offsets expressed in bytes for
250a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // short stack locations, store slot offsets.  A stack offset
251a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // is a multiple of 4 (kFrameSlotSize).  This means that by
252a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // dividing it by 4, we can fit values from the [0, 128)
253a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // interval in a short stack location, and not just values
254a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // from the [0, 32) interval.
255a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_EQ(value % kFrameSlotSize, 0);
256a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value /= kFrameSlotSize;
257a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
258a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      DCHECK(IsUint<kValueBits>(value)) << value;
259a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value));
260a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    } else {
261a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Large location.  Write the location on one byte and the value
262a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // on 4 bytes.
263a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      DCHECK(!IsUint<kValueBits>(value)) << value;
264a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
265a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Also divide large stack offsets by 4 for the sake of consistency.
266a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_EQ(value % kFrameSlotSize, 0);
267a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value /= kFrameSlotSize;
268a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
269a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Data can be unaligned as the written Dex register locations can
270a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // either be 1-byte or 5-byte wide.  Use
271a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // art::MemoryRegion::StoreUnaligned instead of
272a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // art::MemoryRegion::Store to prevent unligned word accesses on ARM.
273a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind);
274a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value);
275a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
276a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
27799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
278fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  bool IsDexRegisterLive(uint16_t dex_register_index) const {
279a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    size_t offset = kFixedSize;
280fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    return region_.LoadBit(offset + dex_register_index);
281fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  }
282fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray
283fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  static constexpr size_t kNoDexRegisterLocationOffset = -1;
284fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray
285fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  static size_t GetDexRegisterMapLocationsOffset(uint16_t number_of_dex_registers) {
286fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    return kLiveBitMaskOffset + LiveBitMaskSize(number_of_dex_registers);
287fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  }
288fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray
289fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  // Find the offset of the Dex register location number `dex_register_index`.
290fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  size_t FindLocationOffset(uint16_t dex_register_index, uint16_t number_of_dex_registers) const {
291fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    if (!IsDexRegisterLive(dex_register_index)) return kNoDexRegisterLocationOffset;
292fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    size_t offset = GetDexRegisterMapLocationsOffset(number_of_dex_registers);
293a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Skip the first `dex_register_index - 1` entries.
294a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    for (uint16_t i = 0; i < dex_register_index; ++i) {
295fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray      if (IsDexRegisterLive(i)) {
296fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        // Read the first next byte and inspect its first 3 bits to decide
297fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        // whether it is a short or a large location.
298fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
299fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        if (DexRegisterLocation::IsShortLocationKind(kind)) {
300fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray          // Short location.  Skip the current byte.
301fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray          offset += SingleShortEntrySize();
302fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        } else {
303fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray          // Large location.  Skip the 5 next bytes.
304fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray          offset += SingleLargeEntrySize();
305fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        }
306a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
307442b46a087c389a91a0b51547ac9205058432364Roland Levillain    }
308a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return offset;
309442b46a087c389a91a0b51547ac9205058432364Roland Levillain  }
310442b46a087c389a91a0b51547ac9205058432364Roland Levillain
311a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Get the surface kind.
312fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_index,
313fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray                                            uint16_t number_of_dex_registers) const {
314fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    return IsDexRegisterLive(dex_register_index)
315fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        ? DexRegisterLocation::ConvertToSurfaceKind(
316fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray              GetLocationInternalKind(dex_register_index, number_of_dex_registers))
317fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        : DexRegisterLocation::Kind::kNone;
31899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
31999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
320a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Get the internal kind.
321fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_index,
322fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray                                                    uint16_t number_of_dex_registers) const {
323fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    return IsDexRegisterLive(dex_register_index)
324fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        ? ExtractKindAtOffset(FindLocationOffset(dex_register_index, number_of_dex_registers))
325fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        : DexRegisterLocation::Kind::kNone;
32699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
32799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
328a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Rename as GetDexRegisterLocation?
329fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  DexRegisterLocation GetLocationKindAndValue(uint16_t dex_register_index,
330fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray                                              uint16_t number_of_dex_registers) const {
331fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    if (!IsDexRegisterLive(dex_register_index)) {
332fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray      return DexRegisterLocation::None();
333fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    }
334fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    size_t offset = FindLocationOffset(dex_register_index, number_of_dex_registers);
335a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Read the first byte and inspect its first 3 bits to get the location.
336a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
337a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte);
338a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    if (DexRegisterLocation::IsShortLocationKind(kind)) {
339a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Short location.  Extract the value from the remaining 5 bits.
340a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      int32_t value = ExtractValueFromShortLocation(first_byte);
341a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStack) {
342a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Convert the stack slot (short) offset to a byte offset value.
343a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value *= kFrameSlotSize;
344a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
345a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      return DexRegisterLocation(kind, value);
346a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    } else {
347a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Large location.  Read the four next bytes to get the value.
348a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind));
349a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
350a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Convert the stack slot (large) offset to a byte offset value.
351a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value *= kFrameSlotSize;
352a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
353a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      return DexRegisterLocation(kind, value);
354a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
35599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
35699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
357fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  int32_t GetStackOffsetInBytes(uint16_t dex_register_index,
358fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray                                uint16_t number_of_dex_registers) const {
359fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    DexRegisterLocation location =
360fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        GetLocationKindAndValue(dex_register_index, number_of_dex_registers);
361a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
362a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // GetLocationKindAndValue returns the offset in bytes.
363a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return location.GetValue();
3647cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz  }
3657cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz
366fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  int32_t GetConstant(uint16_t dex_register_index, uint16_t number_of_dex_registers) const {
367fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    DexRegisterLocation location =
368fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        GetLocationKindAndValue(dex_register_index, number_of_dex_registers);
369a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant);
370a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return location.GetValue();
3717cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz  }
3727cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz
373fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  int32_t GetMachineRegister(uint16_t dex_register_index, uint16_t number_of_dex_registers) const {
374fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    DexRegisterLocation location =
375fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        GetLocationKindAndValue(dex_register_index, number_of_dex_registers);
376a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister
377a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain           || location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister)
378a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
379a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return location.GetValue();
3807cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz  }
3817cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz
382a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Compute the compressed kind of `location`.
383a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) {
384a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (location.GetInternalKind()) {
385a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kNone:
386a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_EQ(location.GetValue(), 0);
387a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return DexRegisterLocation::Kind::kNone;
388a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
389a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInRegister:
390a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_GE(location.GetValue(), 0);
391a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_LT(location.GetValue(), 1 << DexRegisterMap::kValueBits);
392a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return DexRegisterLocation::Kind::kInRegister;
393a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
394a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInFpuRegister:
395a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_GE(location.GetValue(), 0);
396a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_LT(location.GetValue(), 1 << DexRegisterMap::kValueBits);
397a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return DexRegisterLocation::Kind::kInFpuRegister;
398a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
399a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInStack:
400a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_EQ(location.GetValue() % kFrameSlotSize, 0);
401a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return IsUint<DexRegisterMap::kValueBits>(location.GetValue() / kFrameSlotSize)
402a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            ? DexRegisterLocation::Kind::kInStack
403a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            : DexRegisterLocation::Kind::kInStackLargeOffset;
404a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
405a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kConstant:
406a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return IsUint<DexRegisterMap::kValueBits>(location.GetValue())
407a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            ? DexRegisterLocation::Kind::kConstant
408a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            : DexRegisterLocation::Kind::kConstantLargeValue;
409a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
410a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
411a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        LOG(FATAL) << "Unexpected location kind"
412a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain                   << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
413a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
414a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
415a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
416a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
417a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Can `location` be turned into a short location?
418a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) {
419a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (location.GetInternalKind()) {
420a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kNone:
421a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInRegister:
422a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInFpuRegister:
423a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return true;
424a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
425a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInStack:
426a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_EQ(location.GetValue() % kFrameSlotSize, 0);
427a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return IsUint<kValueBits>(location.GetValue() / kFrameSlotSize);
428a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
429a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kConstant:
430a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return IsUint<kValueBits>(location.GetValue());
431a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
432a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
433a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
434a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
435a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
436a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
437a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static size_t EntrySize(const DexRegisterLocation& location) {
438a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return CanBeEncodedAsShortLocation(location)
439a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        ? DexRegisterMap::SingleShortEntrySize()
440a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        : DexRegisterMap::SingleLargeEntrySize();
441a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
442a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
443a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static size_t SingleShortEntrySize() {
444a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return sizeof(ShortLocation);
445a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
446a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
447a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static size_t SingleLargeEntrySize() {
448a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t);
44999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
45099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
45112baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain  size_t Size() const {
45212baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain    return region_.size();
45312baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain  }
45412baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain
455fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  static constexpr int kLiveBitMaskOffset = 0;
456fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  static constexpr int kFixedSize = kLiveBitMaskOffset;
45799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
45812baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain private:
459a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Width of the kind "field" in a short location, in bits.
460a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kKindBits = 3;
461a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Width of the value "field" in a short location, in bits.
462a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kValueBits = 5;
463a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
464a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr uint8_t kKindMask = (1 << kKindBits) - 1;
465a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr int32_t kValueMask = (1 << kValueBits) - 1;
466a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kKindOffset = 0;
467a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kValueOffset = kKindBits;
468a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
469a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) {
470a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DCHECK(IsUint<kKindBits>(static_cast<uint8_t>(kind))) << static_cast<uint8_t>(kind);
471a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DCHECK(IsUint<kValueBits>(value)) << value;
472a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return (static_cast<uint8_t>(kind) & kKindMask) << kKindOffset
473a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        | (value & kValueMask) << kValueOffset;
474a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
475a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
476a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) {
477a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    uint8_t kind = (location >> kKindOffset) & kKindMask;
478a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind));
479fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    // We do not encode kNone locations in the stack map.
480fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone));
481a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return static_cast<DexRegisterLocation::Kind>(kind);
482a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
483a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
484a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static int32_t ExtractValueFromShortLocation(ShortLocation location) {
485a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return (location >> kValueOffset) & kValueMask;
486a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
487a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
488a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Extract a location kind from the byte at position `offset`.
489a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const {
490a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
491a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return ExtractKindFromShortLocation(first_byte);
492a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
493a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
49499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion region_;
495a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
496a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  friend class CodeInfo;
497a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  friend class StackMapStream;
49899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray};
49999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
50099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
50199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * A Stack Map holds compilation information for a specific PC necessary for:
50299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Mapping it to a dex PC,
50399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which stack entries are objects,
50499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which registers hold objects,
50599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the inlining information,
50699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the values of dex registers.
50799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray *
50899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form:
5093946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask, stack_mask].
51099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray *
51199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Note that register_mask is fixed size, but stack_mask is variable size, depending on the
51299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * stack size of a method.
51399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
51499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass StackMap {
51599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public:
51699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  explicit StackMap(MemoryRegion region) : region_(region) {}
51799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
51899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  uint32_t GetDexPc() const {
519ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    return region_.LoadUnaligned<uint32_t>(kDexPcOffset);
52099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
52199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
52299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetDexPc(uint32_t dex_pc) {
523ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    region_.StoreUnaligned<uint32_t>(kDexPcOffset, dex_pc);
52499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
52599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
5263946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  uint32_t GetNativePcOffset() const {
527ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    return region_.LoadUnaligned<uint32_t>(kNativePcOffsetOffset);
52899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
52999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
5303946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  void SetNativePcOffset(uint32_t native_pc_offset) {
531ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    region_.StoreUnaligned<uint32_t>(kNativePcOffsetOffset, native_pc_offset);
53299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
53399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
53499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  uint32_t GetDexRegisterMapOffset() const {
535ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    return region_.LoadUnaligned<uint32_t>(kDexRegisterMapOffsetOffset);
53699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
53799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
53899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetDexRegisterMapOffset(uint32_t offset) {
539ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    region_.StoreUnaligned<uint32_t>(kDexRegisterMapOffsetOffset, offset);
54099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
54199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
54299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  uint32_t GetInlineDescriptorOffset() const {
543ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    return region_.LoadUnaligned<uint32_t>(kInlineDescriptorOffsetOffset);
54499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
54599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
54699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetInlineDescriptorOffset(uint32_t offset) {
547ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    region_.StoreUnaligned<uint32_t>(kInlineDescriptorOffsetOffset, offset);
54899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
54999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
55099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  uint32_t GetRegisterMask() const {
551ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    return region_.LoadUnaligned<uint32_t>(kRegisterMaskOffset);
55299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
55399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
55499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetRegisterMask(uint32_t mask) {
555ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    region_.StoreUnaligned<uint32_t>(kRegisterMaskOffset, mask);
55699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
55799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
55899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion GetStackMask() const {
55999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return region_.Subregion(kStackMaskOffset, StackMaskSize());
56099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
56199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
56299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetStackMask(const BitVector& sp_map) {
56399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    MemoryRegion region = GetStackMask();
56499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    for (size_t i = 0; i < region.size_in_bits(); i++) {
56599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray      region.StoreBit(i, sp_map.IsBitSet(i));
56699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    }
56799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
56899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
569442b46a087c389a91a0b51547ac9205058432364Roland Levillain  bool HasDexRegisterMap() const {
570442b46a087c389a91a0b51547ac9205058432364Roland Levillain    return GetDexRegisterMapOffset() != kNoDexRegisterMap;
571442b46a087c389a91a0b51547ac9205058432364Roland Levillain  }
572442b46a087c389a91a0b51547ac9205058432364Roland Levillain
57399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  bool HasInlineInfo() const {
574442b46a087c389a91a0b51547ac9205058432364Roland Levillain    return GetInlineDescriptorOffset() != kNoInlineInfo;
57599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
57699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
577442b46a087c389a91a0b51547ac9205058432364Roland Levillain  bool Equals(const StackMap& other) const {
57899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return region_.pointer() == other.region_.pointer()
57999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray       && region_.size() == other.region_.size();
58099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
58199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
582ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain  static size_t ComputeStackMapSize(size_t stack_mask_size) {
583ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    return StackMap::kFixedSize + stack_mask_size;
584376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray  }
585376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray
586442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // Special (invalid) offset for the DexRegisterMapOffset field meaning
587442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // that there is no Dex register map for this stack map.
588442b46a087c389a91a0b51547ac9205058432364Roland Levillain  static constexpr uint32_t kNoDexRegisterMap = -1;
589442b46a087c389a91a0b51547ac9205058432364Roland Levillain
590442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // Special (invalid) offset for the InlineDescriptorOffset field meaning
591442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // that there is no inline info for this stack map.
592442b46a087c389a91a0b51547ac9205058432364Roland Levillain  static constexpr uint32_t kNoInlineInfo = -1;
593442b46a087c389a91a0b51547ac9205058432364Roland Levillain
59499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private:
595a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Instead of plain types such as "uint32_t", introduce
596a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // typedefs (and document the memory layout of StackMap).
59799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kDexPcOffset = 0;
5983946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  static constexpr int kNativePcOffsetOffset = kDexPcOffset + sizeof(uint32_t);
5993946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  static constexpr int kDexRegisterMapOffsetOffset = kNativePcOffsetOffset + sizeof(uint32_t);
60099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kInlineDescriptorOffsetOffset =
60199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray      kDexRegisterMapOffsetOffset + sizeof(uint32_t);
60299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kRegisterMaskOffset = kInlineDescriptorOffsetOffset + sizeof(uint32_t);
60399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kFixedSize = kRegisterMaskOffset + sizeof(uint32_t);
60499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kStackMaskOffset = kFixedSize;
60599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
60699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  size_t StackMaskSize() const { return region_.size() - kFixedSize; }
60799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
60899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion region_;
60999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
6103946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class CodeInfo;
6113946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class StackMapStream;
61299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray};
61399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
61499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
61599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
61699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Wrapper around all compiler information collected for a method.
61799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form:
6183946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray * [overall_size, number_of_stack_maps, stack_mask_size, StackMap+, DexRegisterInfo+, InlineInfo*].
61999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
62099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass CodeInfo {
62199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public:
62299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  explicit CodeInfo(MemoryRegion region) : region_(region) {}
62399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
6243946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  explicit CodeInfo(const void* data) {
6253946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    uint32_t size = reinterpret_cast<const uint32_t*>(data)[0];
6263946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    region_ = MemoryRegion(const_cast<void*>(data), size);
6273946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
6283946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
6293946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  StackMap GetStackMapAt(size_t i) const {
63099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    size_t size = StackMapSize();
6313946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    return StackMap(GetStackMaps().Subregion(i * size, size));
6323946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
6333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
6343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  uint32_t GetOverallSize() const {
6353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    return region_.Load<uint32_t>(kOverallSizeOffset);
6363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
6373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
6383946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  void SetOverallSize(uint32_t size) {
6393946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    region_.Store<uint32_t>(kOverallSizeOffset, size);
64099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
64199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
64299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  uint32_t GetStackMaskSize() const {
64399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return region_.Load<uint32_t>(kStackMaskSizeOffset);
64499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
64599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
64699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetStackMaskSize(uint32_t size) {
64799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    region_.Store<uint32_t>(kStackMaskSizeOffset, size);
64899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
64999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
65099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  size_t GetNumberOfStackMaps() const {
65199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return region_.Load<uint32_t>(kNumberOfStackMapsOffset);
65299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
65399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
65499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetNumberOfStackMaps(uint32_t number_of_stack_maps) {
65599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    region_.Store<uint32_t>(kNumberOfStackMapsOffset, number_of_stack_maps);
65699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
65799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
65829ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  // Get the size of one stack map of this CodeInfo object, in bytes.
65929ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  // All stack maps of a CodeInfo have the same size.
66099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  size_t StackMapSize() const {
661ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain    return StackMap::ComputeStackMapSize(GetStackMaskSize());
66299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
66399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
66429ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  // Get the size all the stack maps of this CodeInfo object, in bytes.
66529ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  size_t StackMapsSize() const {
66629ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain    return StackMapSize() * GetNumberOfStackMaps();
66729ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  }
66829ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain
669a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  uint32_t GetStackMapsOffset() const {
670a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return kFixedSize;
671a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
672a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
673442b46a087c389a91a0b51547ac9205058432364Roland Levillain  DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) const {
674442b46a087c389a91a0b51547ac9205058432364Roland Levillain    DCHECK(stack_map.HasDexRegisterMap());
67599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    uint32_t offset = stack_map.GetDexRegisterMapOffset();
676a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    size_t size = ComputeDexRegisterMapSize(offset, number_of_dex_registers);
677a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return DexRegisterMap(region_.Subregion(offset, size));
67899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
67999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
680442b46a087c389a91a0b51547ac9205058432364Roland Levillain  InlineInfo GetInlineInfoOf(StackMap stack_map) const {
681442b46a087c389a91a0b51547ac9205058432364Roland Levillain    DCHECK(stack_map.HasInlineInfo());
68299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    uint32_t offset = stack_map.GetInlineDescriptorOffset();
68399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    uint8_t depth = region_.Load<uint8_t>(offset);
68499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return InlineInfo(region_.Subregion(offset,
68599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize()));
68699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
68799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
688442b46a087c389a91a0b51547ac9205058432364Roland Levillain  StackMap GetStackMapForDexPc(uint32_t dex_pc) const {
68999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
6903946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      StackMap stack_map = GetStackMapAt(i);
69199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray      if (stack_map.GetDexPc() == dex_pc) {
69299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        return stack_map;
69399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray      }
69499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    }
69599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    LOG(FATAL) << "Unreachable";
6962c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers    UNREACHABLE();
69799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
69899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
699442b46a087c389a91a0b51547ac9205058432364Roland Levillain  StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) const {
70099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    // TODO: stack maps are sorted by native pc, we can do a binary search.
70199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
7023946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      StackMap stack_map = GetStackMapAt(i);
7033946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      if (stack_map.GetNativePcOffset() == native_pc_offset) {
70499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        return stack_map;
70599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray      }
70699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    }
70799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    LOG(FATAL) << "Unreachable";
7082c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers    UNREACHABLE();
70999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
71099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
71199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private:
712a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Instead of plain types such as "uint32_t", introduce
713a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // typedefs (and document the memory layout of CodeInfo).
7143946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  static constexpr int kOverallSizeOffset = 0;
7153946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  static constexpr int kNumberOfStackMapsOffset = kOverallSizeOffset + sizeof(uint32_t);
71699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kStackMaskSizeOffset = kNumberOfStackMapsOffset + sizeof(uint32_t);
71799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kFixedSize = kStackMaskSizeOffset + sizeof(uint32_t);
71899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
71999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion GetStackMaps() const {
72099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return region_.size() == 0
72199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        ? MemoryRegion()
72229ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain        : region_.Subregion(kFixedSize, StackMapsSize());
72399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
72499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
725a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Compute the size of a Dex register map starting at offset `origin` in
726a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // `region_` and containing `number_of_dex_registers` locations.
727a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  size_t ComputeDexRegisterMapSize(uint32_t origin, uint32_t number_of_dex_registers) const {
728a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // TODO: Ideally, we would like to use art::DexRegisterMap::Size or
729a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // art::DexRegisterMap::FindLocationOffset, but the DexRegisterMap is not
730a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // yet built.  Try to factor common code.
731fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    size_t offset =
732fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        origin + DexRegisterMap::GetDexRegisterMapLocationsOffset(number_of_dex_registers);
733fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray
734fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    // Create a temporary DexRegisterMap to be able to call DexRegisterMap.IsDexRegisterLive.
735fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    DexRegisterMap only_live_mask(MemoryRegion(region_.Subregion(origin, offset - origin)));
736fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray
737a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Skip the first `number_of_dex_registers - 1` entries.
738a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    for (uint16_t i = 0; i < number_of_dex_registers; ++i) {
739fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray      if (only_live_mask.IsDexRegisterLive(i)) {
740fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        // Read the first next byte and inspect its first 3 bits to decide
741fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        // whether it is a short or a large location.
742fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        DexRegisterMap::ShortLocation first_byte =
743fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray            region_.LoadUnaligned<DexRegisterMap::ShortLocation>(offset);
744fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        DexRegisterLocation::Kind kind =
745fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray            DexRegisterMap::ExtractKindFromShortLocation(first_byte);
746fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        if (DexRegisterLocation::IsShortLocationKind(kind)) {
747fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray          // Short location.  Skip the current byte.
748fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray          offset += DexRegisterMap::SingleShortEntrySize();
749fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        } else {
750fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray          // Large location.  Skip the 5 next bytes.
751fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray          offset += DexRegisterMap::SingleLargeEntrySize();
752fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray        }
753a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
754a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
755a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    size_t size = offset - origin;
756a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return size;
757a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
758a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
75999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion region_;
7603946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class StackMapStream;
76199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray};
76299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
76399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}  // namespace art
76499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
76599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#endif  // ART_RUNTIME_STACK_MAP_H_
766