stack_map.h revision f2650d1f957b158496de8016bc43fb575e81d6bc
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"
2180afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/bit_utils.h"
2299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#include "memory_region.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
42a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// Dex register location container used by DexRegisterMap and StackMapStream.
43a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillainclass DexRegisterLocation {
44a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain public:
45a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  /*
46a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * The location kind used to populate the Dex register information in a
47a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * StackMapStream can either be:
48a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kNone: the register has no location yet, meaning it has not been set;
49a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kConstant: value holds the constant;
50a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kStack: value holds the stack offset;
51a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kRegister: value holds the physical register number;
52a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kFpuRegister: value holds the physical register number.
53a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   *
54a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * In addition, DexRegisterMap also uses these values:
55a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   * - kInStackLargeOffset: value holds a "large" stack offset (greater than
56a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain   *   or equal to 128 bytes);
57a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain   * - kConstantLargeValue: value holds a "large" constant (lower than 0, or
58a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain   *   or greater than or equal to 32).
59a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain   */
60a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  enum class Kind : uint8_t {
61a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Short location kinds, for entries fitting on one byte (3 bits
62a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // for the kind, 5 bits for the value) in a DexRegisterMap.
63a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kNone = 0,                // 0b000
64a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInStack = 1,             // 0b001
65a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInRegister = 2,          // 0b010
66a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInFpuRegister = 3,       // 0b011
67a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kConstant = 4,            // 0b100
68a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
69a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Large location kinds, requiring a 5-byte encoding (1 byte for the
70a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // kind, 4 bytes for the value).
71a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
72a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Stack location at a large offset, meaning that the offset value
73a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // divided by the stack frame slot size (4 bytes) cannot fit on a
74a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // 5-bit unsigned integer (i.e., this offset value is greater than
75a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // or equal to 2^5 * 4 = 128 bytes).
76a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kInStackLargeOffset = 5,  // 0b101
77a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
78a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Large constant, that cannot fit on a 5-bit signed integer (i.e.,
79a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // lower than 0, or greater than or equal to 2^5 = 32).
80a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kConstantLargeValue = 6,  // 0b110
81a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
82a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    kLastLocationKind = kConstantLargeValue
83a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  };
84a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
85a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static_assert(
86a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      sizeof(Kind) == 1u,
87a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      "art::DexRegisterLocation::Kind has a size different from one byte.");
88a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
89a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static const char* PrettyDescriptor(Kind kind) {
90a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (kind) {
91a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kNone:
92a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "none";
93a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStack:
94a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in stack";
95a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInRegister:
96a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in register";
97a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInFpuRegister:
98a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in fpu register";
99a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstant:
100a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "as constant";
101a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStackLargeOffset:
102a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "in stack (large offset)";
103a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstantLargeValue:
104a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return "as constant (large value)";
105a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
106a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
107a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
108a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
109a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
110a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static bool IsShortLocationKind(Kind kind) {
111a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (kind) {
112a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kNone:
113a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStack:
114a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInRegister:
115a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInFpuRegister:
116a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstant:
117a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return true;
118a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
119a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStackLargeOffset:
120a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstantLargeValue:
121a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return false;
122a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
123a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
124a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
125a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
126a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
127a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
128a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Convert `kind` to a "surface" kind, i.e. one that doesn't include
129a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // any value with a "large" qualifier.
130a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Introduce another enum type for the surface kind?
131a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static Kind ConvertToSurfaceKind(Kind kind) {
132a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (kind) {
133a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kNone:
134a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStack:
135a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInRegister:
136a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInFpuRegister:
137a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstant:
138a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return kind;
139a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
140a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kInStackLargeOffset:
141a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return Kind::kInStack;
142a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
143a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case Kind::kConstantLargeValue:
144a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return Kind::kConstant;
145a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
146a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
147a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
148a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
149a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
150a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
151a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Required by art::StackMapStream::LocationCatalogEntriesIndices.
152a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation() : kind_(Kind::kNone), value_(0) {}
153a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
154a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation(Kind kind, int32_t value) : kind_(kind), value_(value) {}
155a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
156fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  static DexRegisterLocation None() {
157fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    return DexRegisterLocation(Kind::kNone, 0);
158fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray  }
159fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray
160a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Get the "surface" kind of the location, i.e., the one that doesn't
161a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // include any value with a "large" qualifier.
162a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  Kind GetKind() const {
163a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return ConvertToSurfaceKind(kind_);
164a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
165a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
166a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Get the value of the location.
167a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  int32_t GetValue() const { return value_; }
168a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
169a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Get the actual kind of the location.
170a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  Kind GetInternalKind() const { return kind_; }
171a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
1726ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle  bool operator==(DexRegisterLocation other) const {
1736ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle    return kind_ == other.kind_ && value_ == other.value_;
1746ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle  }
1756ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle
1766ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle  bool operator!=(DexRegisterLocation other) const {
1776ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle    return !(*this == other);
1786ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle  }
1796ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle
180a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain private:
181a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  Kind kind_;
182a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  int32_t value_;
183a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
184a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  friend class DexRegisterLocationHashFn;
185a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain};
186a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
18799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
188a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * Store information on unique Dex register locations used in a method.
189a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * The information is of the form:
190a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * [DexRegisterLocation+].
191fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind).
19299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
193a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainclass DexRegisterLocationCatalog {
19499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public:
195a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  explicit DexRegisterLocationCatalog(MemoryRegion region) : region_(region) {}
19699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
197a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Short (compressed) location, fitting on one byte.
198a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  typedef uint8_t ShortLocation;
199a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
200a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) {
201a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location);
202a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    int32_t value = dex_register_location.GetValue();
203a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    if (DexRegisterLocation::IsShortLocationKind(kind)) {
204a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Short location.  Compress the kind and the value as a single byte.
205a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStack) {
206a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Instead of storing stack offsets expressed in bytes for
207a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // short stack locations, store slot offsets.  A stack offset
208a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // is a multiple of 4 (kFrameSlotSize).  This means that by
209a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // dividing it by 4, we can fit values from the [0, 128)
210a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // interval in a short stack location, and not just values
211a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // from the [0, 32) interval.
212a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_EQ(value % kFrameSlotSize, 0);
213a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value /= kFrameSlotSize;
214a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
215a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      DCHECK(IsShortValue(value)) << value;
216a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value));
217a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    } else {
218a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Large location.  Write the location on one byte and the value
219a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // on 4 bytes.
220a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      DCHECK(!IsShortValue(value)) << value;
221a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
222a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Also divide large stack offsets by 4 for the sake of consistency.
223a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_EQ(value % kFrameSlotSize, 0);
224a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value /= kFrameSlotSize;
225a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
226a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Data can be unaligned as the written Dex register locations can
227a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // either be 1-byte or 5-byte wide.  Use
228a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // art::MemoryRegion::StoreUnaligned instead of
229a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // art::MemoryRegion::Store to prevent unligned word accesses on ARM.
230a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind);
231a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value);
232a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
233a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
23499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
235a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Find the offset of the location catalog entry number `location_catalog_entry_index`.
236a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t FindLocationOffset(size_t location_catalog_entry_index) const {
237a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    size_t offset = kFixedSize;
238a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // Skip the first `location_catalog_entry_index - 1` entries.
239a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    for (uint16_t i = 0; i < location_catalog_entry_index; ++i) {
240a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // Read the first next byte and inspect its first 3 bits to decide
241a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // whether it is a short or a large location.
242a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
243a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      if (DexRegisterLocation::IsShortLocationKind(kind)) {
244a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        // Short location.  Skip the current byte.
245a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        offset += SingleShortEntrySize();
246a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      } else {
247a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        // Large location.  Skip the 5 next bytes.
248a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        offset += SingleLargeEntrySize();
249a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
250442b46a087c389a91a0b51547ac9205058432364Roland Levillain    }
251a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return offset;
252442b46a087c389a91a0b51547ac9205058432364Roland Levillain  }
253442b46a087c389a91a0b51547ac9205058432364Roland Levillain
254a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the internal kind of entry at `location_catalog_entry_index`.
255a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation::Kind GetLocationInternalKind(size_t location_catalog_entry_index) const {
256a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (location_catalog_entry_index == kNoLocationEntryIndex) {
257a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      return DexRegisterLocation::Kind::kNone;
258a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
259a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return ExtractKindAtOffset(FindLocationOffset(location_catalog_entry_index));
26099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
26199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
262a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the (surface) kind and value of entry at `location_catalog_entry_index`.
263a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation GetDexRegisterLocation(size_t location_catalog_entry_index) const {
264a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (location_catalog_entry_index == kNoLocationEntryIndex) {
265fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray      return DexRegisterLocation::None();
266fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    }
267a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t offset = FindLocationOffset(location_catalog_entry_index);
268a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    // Read the first byte and inspect its first 3 bits to get the location.
269a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
270a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte);
271a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    if (DexRegisterLocation::IsShortLocationKind(kind)) {
272a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Short location.  Extract the value from the remaining 5 bits.
273a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      int32_t value = ExtractValueFromShortLocation(first_byte);
274a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStack) {
275a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Convert the stack slot (short) offset to a byte offset value.
276a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value *= kFrameSlotSize;
277a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
278a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      return DexRegisterLocation(kind, value);
279a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    } else {
280a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      // Large location.  Read the four next bytes to get the value.
281a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind));
282a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
283a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        // Convert the stack slot (large) offset to a byte offset value.
284a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        value *= kFrameSlotSize;
285a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
286a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      return DexRegisterLocation(kind, value);
287a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
28899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
28999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
290a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Compute the compressed kind of `location`.
291a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) {
292a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (location.GetInternalKind()) {
293a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kNone:
294a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_EQ(location.GetValue(), 0);
295a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return DexRegisterLocation::Kind::kNone;
296a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
297a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInRegister:
298a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_GE(location.GetValue(), 0);
299a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        DCHECK_LT(location.GetValue(), 1 << kValueBits);
300a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return DexRegisterLocation::Kind::kInRegister;
301a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
302a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInFpuRegister:
303a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        DCHECK_GE(location.GetValue(), 0);
304a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        DCHECK_LT(location.GetValue(), 1 << kValueBits);
305a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return DexRegisterLocation::Kind::kInFpuRegister;
306a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
307a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInStack:
308a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        return IsShortStackOffsetValue(location.GetValue())
309a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            ? DexRegisterLocation::Kind::kInStack
310a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            : DexRegisterLocation::Kind::kInStackLargeOffset;
311a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
312a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kConstant:
313a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        return IsShortConstantValue(location.GetValue())
314a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            ? DexRegisterLocation::Kind::kConstant
315a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain            : DexRegisterLocation::Kind::kConstantLargeValue;
316a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
317a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
318a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        LOG(FATAL) << "Unexpected location kind"
319a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain                   << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
320a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
321a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
322a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
323a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
324a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Can `location` be turned into a short location?
325a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) {
326a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    switch (location.GetInternalKind()) {
327a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kNone:
328a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInRegister:
329a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInFpuRegister:
330a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        return true;
331a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
332a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kInStack:
333a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        return IsShortStackOffsetValue(location.GetValue());
334a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
335a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      case DexRegisterLocation::Kind::kConstant:
336a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        return IsShortConstantValue(location.GetValue());
337a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
338a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      default:
339a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        UNREACHABLE();
340a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
341a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
342a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
343a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static size_t EntrySize(const DexRegisterLocation& location) {
344a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return CanBeEncodedAsShortLocation(location) ? SingleShortEntrySize() : SingleLargeEntrySize();
345a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
346a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
347a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static size_t SingleShortEntrySize() {
348a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return sizeof(ShortLocation);
349a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
350a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
351a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static size_t SingleLargeEntrySize() {
352a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t);
35399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
35499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
35512baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain  size_t Size() const {
35612baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain    return region_.size();
35712baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain  }
35812baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain
3590396ed7d3ad30778cb4af19e7086bea0deace9b9Roland Levillain  void Dump(std::ostream& os, const CodeInfo& code_info);
3600396ed7d3ad30778cb4af19e7086bea0deace9b9Roland Levillain
361a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Special (invalid) Dex register location catalog entry index meaning
362a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // that there is no location for a given Dex register (i.e., it is
363a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // mapped to a DexRegisterLocation::Kind::kNone location).
364a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr size_t kNoLocationEntryIndex = -1;
36599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
36612baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain private:
367a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr int kFixedSize = 0;
368a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
369a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Width of the kind "field" in a short location, in bits.
370a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kKindBits = 3;
371a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Width of the value "field" in a short location, in bits.
372a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kValueBits = 5;
373a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
374a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr uint8_t kKindMask = (1 << kKindBits) - 1;
375a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr int32_t kValueMask = (1 << kValueBits) - 1;
376a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kKindOffset = 0;
377a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static constexpr size_t kValueOffset = kKindBits;
378a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
379a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static bool IsShortStackOffsetValue(int32_t value) {
380a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK_EQ(value % kFrameSlotSize, 0);
381a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return IsShortValue(value / kFrameSlotSize);
382a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
383a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
384a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static bool IsShortConstantValue(int32_t value) {
385a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return IsShortValue(value);
386a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
387a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
388a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static bool IsShortValue(int32_t value) {
389a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return IsUint<kValueBits>(value);
390a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
391a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
392a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) {
393a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    uint8_t kind_integer_value = static_cast<uint8_t>(kind);
394a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK(IsUint<kKindBits>(kind_integer_value)) << kind_integer_value;
395a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK(IsShortValue(value)) << value;
396a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return (kind_integer_value & kKindMask) << kKindOffset
397a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain        | (value & kValueMask) << kValueOffset;
398a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
399a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
400a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) {
401a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    uint8_t kind = (location >> kKindOffset) & kKindMask;
402a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind));
403fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    // We do not encode kNone locations in the stack map.
404fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray    DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone));
405a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return static_cast<DexRegisterLocation::Kind>(kind);
406a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
407a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
408a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  static int32_t ExtractValueFromShortLocation(ShortLocation location) {
409a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return (location >> kValueOffset) & kValueMask;
410a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
411a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
412a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // Extract a location kind from the byte at position `offset`.
413a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const {
414a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
415a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return ExtractKindFromShortLocation(first_byte);
416a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
417a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
41899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion region_;
419a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
420a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  friend class CodeInfo;
421a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  friend class StackMapStream;
42299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray};
42399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
424a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain/* Information on Dex register locations for a specific PC, mapping a
425a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * stack map's Dex register to a location entry in a DexRegisterLocationCatalog.
426a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * The information is of the form:
427a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * [live_bit_mask, entries*]
428a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * where entries are concatenated unsigned integer values encoded on a number
429a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * of bits (fixed per DexRegisterMap instances of a CodeInfo object) depending
430a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * on the number of entries in the Dex register location catalog
431a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * (see DexRegisterMap::SingleEntrySizeInBits).  The map is 1-byte aligned.
432a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain */
433a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainclass DexRegisterMap {
434a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain public:
435a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  explicit DexRegisterMap(MemoryRegion region) : region_(region) {}
436a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
437a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the surface kind of Dex register `dex_register_number`.
438a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number,
439a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                            uint16_t number_of_dex_registers,
440a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                            const CodeInfo& code_info) const {
441a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return DexRegisterLocation::ConvertToSurfaceKind(
442a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info));
443a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
444a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
445a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the internal kind of Dex register `dex_register_number`.
446a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number,
447a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                                    uint16_t number_of_dex_registers,
448a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                                    const CodeInfo& code_info) const;
449a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
450a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the Dex register location `dex_register_number`.
451a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number,
452a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                             uint16_t number_of_dex_registers,
453a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                             const CodeInfo& code_info) const;
454a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
455a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  int32_t GetStackOffsetInBytes(uint16_t dex_register_number,
456a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                uint16_t number_of_dex_registers,
457a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                const CodeInfo& code_info) const {
458a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DexRegisterLocation location =
459a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
460a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
461a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // GetDexRegisterLocation returns the offset in bytes.
462a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return location.GetValue();
463a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
464a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
465a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  int32_t GetConstant(uint16_t dex_register_number,
466a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                      uint16_t number_of_dex_registers,
467a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                      const CodeInfo& code_info) const {
468a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DexRegisterLocation location =
469a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
470b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant)
471b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray        << DexRegisterLocation::PrettyDescriptor(location.GetKind());
472a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return location.GetValue();
473a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
474a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
475a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  int32_t GetMachineRegister(uint16_t dex_register_number,
476a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                             uint16_t number_of_dex_registers,
477a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                             const CodeInfo& code_info) const {
478a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DexRegisterLocation location =
479a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
480a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister
481a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain           || location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister)
482a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind());
483a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return location.GetValue();
484a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
485a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
486a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Get the index of the entry in the Dex register location catalog
487a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // corresponding to `dex_register_number`.
488a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t GetLocationCatalogEntryIndex(uint16_t dex_register_number,
489a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                      uint16_t number_of_dex_registers,
490a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                      size_t number_of_location_catalog_entries) const {
491a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (!IsDexRegisterLive(dex_register_number)) {
492a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      return DexRegisterLocationCatalog::kNoLocationEntryIndex;
493a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
494a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
495a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (number_of_location_catalog_entries == 1) {
496a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // We do not allocate space for location maps in the case of a
497a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // single-entry location catalog, as it is useless.  The only valid
498a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // entry index is 0;
499a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      return 0;
500a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
501a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
502a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit offset of the beginning of the map locations.
503a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t map_locations_offset_in_bits =
504a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
505a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t index_in_dex_register_map = GetIndexInDexRegisterMap(dex_register_number);
506a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
507a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit size of an entry.
508a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
509a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit offset where `index_in_dex_register_map` is located.
510a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t entry_offset_in_bits =
511a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
512a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t location_catalog_entry_index =
513a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        region_.LoadBits(entry_offset_in_bits, map_entry_size_in_bits);
514a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
515a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return location_catalog_entry_index;
516a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
517a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
518a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Map entry at `index_in_dex_register_map` to `location_catalog_entry_index`.
519a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  void SetLocationCatalogEntryIndex(size_t index_in_dex_register_map,
520a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                    size_t location_catalog_entry_index,
521a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                    uint16_t number_of_dex_registers,
522a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                    size_t number_of_location_catalog_entries) {
523a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
524a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
525a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
526a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (number_of_location_catalog_entries == 1) {
527a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // We do not allocate space for location maps in the case of a
528a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // single-entry location catalog, as it is useless.
529a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      return;
530a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
531a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
532a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit offset of the beginning of the map locations.
533a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t map_locations_offset_in_bits =
534a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
535a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit size of an entry.
536a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
537a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // The bit offset where `index_in_dex_register_map` is located.
538a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t entry_offset_in_bits =
539a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
540a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    region_.StoreBits(entry_offset_in_bits, location_catalog_entry_index, map_entry_size_in_bits);
541a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
542a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
543a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  void SetLiveBitMask(uint16_t number_of_dex_registers,
544a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                      const BitVector& live_dex_registers_mask) {
545a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
546a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    for (uint16_t i = 0; i < number_of_dex_registers; ++i) {
547a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      region_.StoreBit(live_bit_mask_offset_in_bits + i, live_dex_registers_mask.IsBitSet(i));
548a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
549a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
550a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
551a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  bool IsDexRegisterLive(uint16_t dex_register_number) const {
552a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
553a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return region_.LoadBit(live_bit_mask_offset_in_bits + dex_register_number);
554a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
555a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
556a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t GetNumberOfLiveDexRegisters(uint16_t number_of_dex_registers) const {
557a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t number_of_live_dex_registers = 0;
558a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    for (size_t i = 0; i < number_of_dex_registers; ++i) {
559a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      if (IsDexRegisterLive(i)) {
560a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        ++number_of_live_dex_registers;
561a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      }
562a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
563a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return number_of_live_dex_registers;
564a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
565a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
566a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static size_t GetLiveBitMaskOffset() {
567a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return kFixedSize;
568a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
569a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
570a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Compute the size of the live register bit mask (in bytes), for a
571a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // method having `number_of_dex_registers` Dex registers.
572a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static size_t GetLiveBitMaskSize(uint16_t number_of_dex_registers) {
573a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte;
574a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
575a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
576a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static size_t GetLocationMappingDataOffset(uint16_t number_of_dex_registers) {
577a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return GetLiveBitMaskOffset() + GetLiveBitMaskSize(number_of_dex_registers);
578a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
579a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
580a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t GetLocationMappingDataSize(uint16_t number_of_dex_registers,
581a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                    size_t number_of_location_catalog_entries) const {
582a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t location_mapping_data_size_in_bits =
583a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetNumberOfLiveDexRegisters(number_of_dex_registers)
584a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        * SingleEntrySizeInBits(number_of_location_catalog_entries);
585a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
586a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
587a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
588a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Return the size of a map entry in bits.  Note that if
589a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // `number_of_location_catalog_entries` equals 1, this function returns 0,
590a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // which is fine, as there is no need to allocate a map for a
591a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // single-entry location catalog; the only valid location catalog entry index
592a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // for a live register in this case is 0 and there is no need to
593a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // store it.
594a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static size_t SingleEntrySizeInBits(size_t number_of_location_catalog_entries) {
595a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // Handle the case of 0, as we cannot pass 0 to art::WhichPowerOf2.
596a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return number_of_location_catalog_entries == 0
597a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        ? 0u
598a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        : WhichPowerOf2(RoundUpToPowerOfTwo(number_of_location_catalog_entries));
599a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
600a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
601a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Return the size of the DexRegisterMap object, in bytes.
602a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t Size() const {
603a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return region_.size();
604a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
605a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
606b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  void Dump(std::ostream& o, const CodeInfo& code_info, uint16_t number_of_dex_registers) const;
607b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
608a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain private:
609a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Return the index in the Dex register map corresponding to the Dex
610a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // register number `dex_register_number`.
611a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t GetIndexInDexRegisterMap(uint16_t dex_register_number) const {
612a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    if (!IsDexRegisterLive(dex_register_number)) {
613a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      return kInvalidIndexInDexRegisterMap;
614a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    }
615a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return GetNumberOfLiveDexRegisters(dex_register_number);
616a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
617a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
618a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Special (invalid) Dex register map entry index meaning that there
619a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // is no index in the map for a given Dex register (i.e., it must
620a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // have been mapped to a DexRegisterLocation::Kind::kNone location).
621a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr size_t kInvalidIndexInDexRegisterMap = -1;
622a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
623a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr int kFixedSize = 0;
624a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
625a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  MemoryRegion region_;
626a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
627a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  friend class CodeInfo;
628a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  friend class StackMapStream;
629a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain};
630a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
63199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
63299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * A Stack Map holds compilation information for a specific PC necessary for:
63399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Mapping it to a dex PC,
63499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which stack entries are objects,
63599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which registers hold objects,
63699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the inlining information,
63799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the values of dex registers.
63899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray *
63999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form:
640a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask,
641a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * stack_mask].
64299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
64399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass StackMap {
64499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public:
64599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  explicit StackMap(MemoryRegion region) : region_(region) {}
646e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray  StackMap() {}
647e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray
648e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray  bool IsValid() const { return region_.pointer() != nullptr; }
64999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
650004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  uint32_t GetDexPc(const CodeInfo& info) const;
65199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
652004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetDexPc(const CodeInfo& info, uint32_t dex_pc);
65399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
654004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  uint32_t GetNativePcOffset(const CodeInfo& info) const;
65599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
656004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetNativePcOffset(const CodeInfo& info, uint32_t native_pc_offset);
65799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
658004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  uint32_t GetDexRegisterMapOffset(const CodeInfo& info) const;
65999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
660004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetDexRegisterMapOffset(const CodeInfo& info, uint32_t offset);
66199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
662004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  uint32_t GetInlineDescriptorOffset(const CodeInfo& info) const;
66399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
664004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetInlineDescriptorOffset(const CodeInfo& info, uint32_t offset);
66599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
666004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  uint32_t GetRegisterMask(const CodeInfo& info) const;
66799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
668004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetRegisterMask(const CodeInfo& info, uint32_t mask);
66999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
670004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  MemoryRegion GetStackMask(const CodeInfo& info) const;
67199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
672004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetStackMask(const CodeInfo& info, const BitVector& sp_map) {
673004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    MemoryRegion region = GetStackMask(info);
67499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    for (size_t i = 0; i < region.size_in_bits(); i++) {
67599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray      region.StoreBit(i, sp_map.IsBitSet(i));
67699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    }
67799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
67899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
679004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  bool HasDexRegisterMap(const CodeInfo& info) const {
680004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return GetDexRegisterMapOffset(info) != kNoDexRegisterMap;
681442b46a087c389a91a0b51547ac9205058432364Roland Levillain  }
682442b46a087c389a91a0b51547ac9205058432364Roland Levillain
683004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  bool HasInlineInfo(const CodeInfo& info) const {
684004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return GetInlineDescriptorOffset(info) != kNoInlineInfo;
68599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
68699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
687442b46a087c389a91a0b51547ac9205058432364Roland Levillain  bool Equals(const StackMap& other) const {
68899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return region_.pointer() == other.region_.pointer()
68999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray       && region_.size() == other.region_.size();
69099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
69199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
692004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  static size_t ComputeStackMapSize(size_t stack_mask_size,
693004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray                                    size_t inline_info_size,
694004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray                                    size_t dex_register_map_size,
695004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray                                    size_t dex_pc_max,
696896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                    size_t native_pc_max,
697896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                    size_t register_mask_max);
698376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray
699f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain  void Dump(std::ostream& os,
700f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain            const CodeInfo& code_info,
701f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain            uint32_t code_offset,
702f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain            uint16_t number_of_dex_registers,
703f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain            const std::string& header_suffix = "") const;
704f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain
705442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // Special (invalid) offset for the DexRegisterMapOffset field meaning
706442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // that there is no Dex register map for this stack map.
707442b46a087c389a91a0b51547ac9205058432364Roland Levillain  static constexpr uint32_t kNoDexRegisterMap = -1;
708442b46a087c389a91a0b51547ac9205058432364Roland Levillain
709442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // Special (invalid) offset for the InlineDescriptorOffset field meaning
710442b46a087c389a91a0b51547ac9205058432364Roland Levillain  // that there is no inline info for this stack map.
711442b46a087c389a91a0b51547ac9205058432364Roland Levillain  static constexpr uint32_t kNoInlineInfo = -1;
712442b46a087c389a91a0b51547ac9205058432364Roland Levillain
71399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private:
714896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static size_t ComputeStackMapSizeInternal(size_t stack_mask_size,
715896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                            size_t number_of_bytes_for_inline_info,
716896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                            size_t number_of_bytes_for_dex_map,
717896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                            size_t number_of_bytes_for_dex_pc,
718896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                            size_t number_of_bytes_for_native_pc,
719896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                            size_t number_of_bytes_for_register_mask);
720896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray
721a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Instead of plain types such as "uint32_t", introduce
722a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // typedefs (and document the memory layout of StackMap).
723004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  static constexpr int kRegisterMaskOffset = 0;
724896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kFixedSize = 0;
72599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
72699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion region_;
72799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
7283946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class CodeInfo;
7293946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class StackMapStream;
73099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray};
73199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
732b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray/**
733b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray * Inline information for a specific PC. The information is of the form:
734b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray * [inlining_depth, [dex_pc, method_index, dex_register_map_offset]+]
735b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray */
736b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffrayclass InlineInfo {
737b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray public:
738b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  explicit InlineInfo(MemoryRegion region) : region_(region) {}
739b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
740b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  uint8_t GetDepth() const {
741b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    return region_.LoadUnaligned<uint8_t>(kDepthOffset);
742b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  }
743b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
744b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  void SetDepth(uint8_t depth) {
745b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    region_.StoreUnaligned<uint8_t>(kDepthOffset, depth);
746b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  }
747b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
748b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  uint32_t GetMethodIndexAtDepth(uint8_t depth) const {
749b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray    return region_.LoadUnaligned<uint32_t>(
750b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray        kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset);
751b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  }
752b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
753b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  void SetMethodIndexAtDepth(uint8_t depth, uint32_t index) {
754b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray    region_.StoreUnaligned<uint32_t>(
755b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray        kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset, index);
756b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  }
757b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
758b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  uint32_t GetDexPcAtDepth(uint8_t depth) const {
759b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    return region_.LoadUnaligned<uint32_t>(
760b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray        kFixedSize + depth * SingleEntrySize() + kDexPcOffset);
761b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  }
762b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
763b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  void SetDexPcAtDepth(uint8_t depth, uint32_t dex_pc) {
764b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    region_.StoreUnaligned<uint32_t>(
765b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray        kFixedSize + depth * SingleEntrySize() + kDexPcOffset, dex_pc);
766b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray  }
767b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray
768b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray  uint8_t GetInvokeTypeAtDepth(uint8_t depth) const {
769b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray    return region_.LoadUnaligned<uint8_t>(
770b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray        kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset);
771b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray  }
772b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray
773b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray  void SetInvokeTypeAtDepth(uint8_t depth, uint8_t invoke_type) {
774b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray    region_.StoreUnaligned<uint8_t>(
775b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray        kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset, invoke_type);
776b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  }
777b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
778b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  uint32_t GetDexRegisterMapOffsetAtDepth(uint8_t depth) const {
779b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    return region_.LoadUnaligned<uint32_t>(
780b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray        kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset);
781b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  }
782b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
783b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  void SetDexRegisterMapOffsetAtDepth(uint8_t depth, uint32_t offset) {
784b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    region_.StoreUnaligned<uint32_t>(
785b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray        kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset, offset);
786b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  }
787b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
788b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  bool HasDexRegisterMapAtDepth(uint8_t depth) const {
789b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    return GetDexRegisterMapOffsetAtDepth(depth) != StackMap::kNoDexRegisterMap;
790b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  }
791b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
792b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  static size_t SingleEntrySize() {
793b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray    return kFixedEntrySize;
794b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  }
795b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
796b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  void Dump(std::ostream& os, const CodeInfo& info, uint16_t* number_of_dex_registers) const;
797b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
798b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray private:
799b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  // TODO: Instead of plain types such as "uint8_t", introduce
800b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  // typedefs (and document the memory layout of InlineInfo).
801b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  static constexpr int kDepthOffset = 0;
802b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  static constexpr int kFixedSize = kDepthOffset + sizeof(uint8_t);
803b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
804b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray  static constexpr int kMethodIndexOffset = 0;
805b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray  static constexpr int kDexPcOffset = kMethodIndexOffset + sizeof(uint32_t);
806b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray  static constexpr int kInvokeTypeOffset = kDexPcOffset + sizeof(uint32_t);
807b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray  static constexpr int kDexRegisterMapOffset = kInvokeTypeOffset + sizeof(uint8_t);
808b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray  static constexpr int kFixedEntrySize = kDexRegisterMapOffset + sizeof(uint32_t);
809b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray
810b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  MemoryRegion region_;
811b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
812b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  friend class CodeInfo;
813b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  friend class StackMap;
814b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  friend class StackMapStream;
815b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray};
81699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
81799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/**
81899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Wrapper around all compiler information collected for a method.
81999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form:
820a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * [overall_size, number_of_location_catalog_entries, number_of_stack_maps, stack_mask_size,
821a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * DexRegisterLocationCatalog+, StackMap+, DexRegisterMap+, InlineInfo*].
82299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */
82399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass CodeInfo {
82499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public:
82599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  explicit CodeInfo(MemoryRegion region) : region_(region) {}
82699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
8273946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  explicit CodeInfo(const void* data) {
8283946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    uint32_t size = reinterpret_cast<const uint32_t*>(data)[0];
8293946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    region_ = MemoryRegion(const_cast<void*>(data), size);
8303946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
8313946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
832896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static size_t EncodingSizeInBytes(size_t max_element) {
833896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    DCHECK(IsUint<32>(max_element));
834896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return (max_element == 0) ? 0
835896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray         : IsUint<8>(max_element) ? 1
836896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray         : IsUint<16>(max_element) ? 2
837896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray         : IsUint<24>(max_element) ? 3
838896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray         : 4;
839896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  }
840896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray
841004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  void SetEncoding(size_t inline_info_size,
842004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray                   size_t dex_register_map_size,
843004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray                   size_t dex_pc_max,
844896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                   size_t native_pc_max,
845896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                   size_t register_mask_max) {
846004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    if (inline_info_size != 0) {
847004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray      region_.StoreBit(kHasInlineInfoBitOffset, 1);
848896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      // + 1 to also encode kNoInlineInfo: if an inline info offset
849896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      // is at 0xFF, we want to overflow to a larger encoding, because it will
850896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      // conflict with kNoInlineInfo.
851896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      // The offset is relative to the dex register map. TODO: Change this.
852896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      SetEncodingAt(kInlineInfoBitOffset,
853896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                    EncodingSizeInBytes(dex_register_map_size + inline_info_size + 1));
854004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    } else {
855004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray      region_.StoreBit(kHasInlineInfoBitOffset, 0);
856896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      SetEncodingAt(kInlineInfoBitOffset, 0);
857004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    }
858896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    // + 1 to also encode kNoDexRegisterMap: if a dex register map offset
859896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    // is at 0xFF, we want to overflow to a larger encoding, because it will
860896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    // conflict with kNoDexRegisterMap.
861896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    SetEncodingAt(kDexRegisterMapBitOffset, EncodingSizeInBytes(dex_register_map_size + 1));
862896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    SetEncodingAt(kDexPcBitOffset, EncodingSizeInBytes(dex_pc_max));
863896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    SetEncodingAt(kNativePcBitOffset, EncodingSizeInBytes(native_pc_max));
864896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    SetEncodingAt(kRegisterMaskBitOffset, EncodingSizeInBytes(register_mask_max));
865896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  }
866896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray
867896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  void SetEncodingAt(size_t bit_offset, size_t number_of_bytes) {
868896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    // We encode the number of bytes needed for writing a value on 3 bits,
869896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    // for values that we know are maximum 32bits.
870896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    region_.StoreBit(bit_offset, (number_of_bytes & 1));
871896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    region_.StoreBit(bit_offset + 1, (number_of_bytes & 2));
872896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    region_.StoreBit(bit_offset + 2, (number_of_bytes & 4));
873896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  }
874896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray
875896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t GetNumberOfBytesForEncoding(size_t bit_offset) const {
876896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return region_.LoadBit(bit_offset)
877896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (region_.LoadBit(bit_offset + 1) << 1)
878896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (region_.LoadBit(bit_offset + 2) << 2);
879004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
880004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
881004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  bool HasInlineInfo() const {
882004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return region_.LoadBit(kHasInlineInfoBitOffset);
883004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
884004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
885896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t NumberOfBytesForInlineInfo() const {
886896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return GetNumberOfBytesForEncoding(kInlineInfoBitOffset);
887896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  }
888896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray
889896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t NumberOfBytesForDexRegisterMap() const {
890896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return GetNumberOfBytesForEncoding(kDexRegisterMapBitOffset);
891004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
892004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
893896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t NumberOfBytesForRegisterMask() const {
894896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return GetNumberOfBytesForEncoding(kRegisterMaskBitOffset);
895004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
896004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
897896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t NumberOfBytesForNativePc() const {
898896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return GetNumberOfBytesForEncoding(kNativePcBitOffset);
899004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
900004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
901896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  size_t NumberOfBytesForDexPc() const {
902896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return GetNumberOfBytesForEncoding(kDexPcBitOffset);
903004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
904004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
905004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapRegisterMaskOffset() const {
906004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return StackMap::kRegisterMaskOffset;
907004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
908004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
909004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapStackMaskOffset() const {
910896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return ComputeStackMapRegisterMaskOffset()
911896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (NumberOfBytesForRegisterMask() * sizeof(uint8_t));
912004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
913004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
914004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapDexPcOffset() const {
915004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return ComputeStackMapStackMaskOffset() + GetStackMaskSize();
916004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
917004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
918004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapNativePcOffset() const {
919004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return ComputeStackMapDexPcOffset()
920896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (NumberOfBytesForDexPc() * sizeof(uint8_t));
921004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
922004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
923004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapDexRegisterMapOffset() const {
924004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return ComputeStackMapNativePcOffset()
925896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (NumberOfBytesForNativePc() * sizeof(uint8_t));
926004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
927004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
928004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  size_t ComputeStackMapInlineInfoOffset() const {
929004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    CHECK(HasInlineInfo());
930004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    return ComputeStackMapDexRegisterMapOffset()
931896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray        + (NumberOfBytesForDexRegisterMap() * sizeof(uint8_t));
932004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
933004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
934a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  DexRegisterLocationCatalog GetDexRegisterLocationCatalog() const {
935a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return DexRegisterLocationCatalog(region_.Subregion(
936a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetDexRegisterLocationCatalogOffset(),
937a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        GetDexRegisterLocationCatalogSize()));
938a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
939a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
9403946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  StackMap GetStackMapAt(size_t i) const {
94199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    size_t size = StackMapSize();
9423946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    return StackMap(GetStackMaps().Subregion(i * size, size));
9433946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
9443946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
9453946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  uint32_t GetOverallSize() const {
946aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    return region_.LoadUnaligned<uint32_t>(kOverallSizeOffset);
9473946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
9483946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
9493946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  void SetOverallSize(uint32_t size) {
950aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    region_.StoreUnaligned<uint32_t>(kOverallSizeOffset, size);
95199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
95299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
953a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  uint32_t GetNumberOfDexRegisterLocationCatalogEntries() const {
954a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return region_.LoadUnaligned<uint32_t>(kNumberOfDexRegisterLocationCatalogEntriesOffset);
955a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
956a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
957a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  void SetNumberOfDexRegisterLocationCatalogEntries(uint32_t num_entries) {
958a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    region_.StoreUnaligned<uint32_t>(kNumberOfDexRegisterLocationCatalogEntriesOffset, num_entries);
959a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
960a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
961a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  uint32_t GetDexRegisterLocationCatalogSize() const {
962a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return ComputeDexRegisterLocationCatalogSize(GetDexRegisterLocationCatalogOffset(),
963a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                                 GetNumberOfDexRegisterLocationCatalogEntries());
964a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
965a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
96699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  uint32_t GetStackMaskSize() const {
967aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    return region_.LoadUnaligned<uint32_t>(kStackMaskSizeOffset);
96899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
96999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
97099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetStackMaskSize(uint32_t size) {
971aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    region_.StoreUnaligned<uint32_t>(kStackMaskSizeOffset, size);
97299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
97399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
97499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  size_t GetNumberOfStackMaps() const {
975aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    return region_.LoadUnaligned<uint32_t>(kNumberOfStackMapsOffset);
97699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
97799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
97899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  void SetNumberOfStackMaps(uint32_t number_of_stack_maps) {
979aec8f930571ce10d6ce9a4249c45866a7f213397Nicolas Geoffray    region_.StoreUnaligned<uint32_t>(kNumberOfStackMapsOffset, number_of_stack_maps);
98099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
98199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
98229ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  // Get the size of one stack map of this CodeInfo object, in bytes.
98329ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  // All stack maps of a CodeInfo have the same size.
98499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  size_t StackMapSize() const {
985896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray    return StackMap::ComputeStackMapSizeInternal(GetStackMaskSize(),
986896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                                 NumberOfBytesForInlineInfo(),
987896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                                 NumberOfBytesForDexRegisterMap(),
988896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                                 NumberOfBytesForDexPc(),
989896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                                 NumberOfBytesForNativePc(),
990896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray                                                 NumberOfBytesForRegisterMask());
99199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
99299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
99329ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  // Get the size all the stack maps of this CodeInfo object, in bytes.
994a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t GetStackMapsSize() const {
99529ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain    return StackMapSize() * GetNumberOfStackMaps();
99629ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain  }
99729ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain
9986530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray  uint32_t GetDexRegisterLocationCatalogOffset() const {
999a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return GetStackMapsOffset() + GetStackMapsSize();
1000004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  }
1001004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
10026530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray  size_t GetDexRegisterMapsOffset() const {
1003a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return GetDexRegisterLocationCatalogOffset() + GetDexRegisterLocationCatalogSize();
1004a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
1005a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
10066530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray  uint32_t GetStackMapsOffset() const {
10076530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray    return kFixedSize;
10086530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray  }
10096530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray
1010442b46a087c389a91a0b51547ac9205058432364Roland Levillain  DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) const {
1011004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    DCHECK(stack_map.HasDexRegisterMap(*this));
1012a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    uint32_t offset = GetDexRegisterMapsOffset() + stack_map.GetDexRegisterMapOffset(*this);
1013a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
1014a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return DexRegisterMap(region_.Subregion(offset, size));
101599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
101699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
1017b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  // Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`.
1018b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth,
1019b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray                                          InlineInfo inline_info,
1020b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray                                          uint32_t number_of_dex_registers) const {
1021b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    DCHECK(inline_info.HasDexRegisterMapAtDepth(depth));
1022b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    uint32_t offset =
1023b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray        GetDexRegisterMapsOffset() + inline_info.GetDexRegisterMapOffsetAtDepth(depth);
1024b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
1025b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray    return DexRegisterMap(region_.Subregion(offset, size));
1026b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  }
1027b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray
1028442b46a087c389a91a0b51547ac9205058432364Roland Levillain  InlineInfo GetInlineInfoOf(StackMap stack_map) const {
1029004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    DCHECK(stack_map.HasInlineInfo(*this));
1030004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    uint32_t offset = stack_map.GetInlineDescriptorOffset(*this) + GetDexRegisterMapsOffset();
1031004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray    uint8_t depth = region_.LoadUnaligned<uint8_t>(offset);
103299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return InlineInfo(region_.Subregion(offset,
103399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize()));
103499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
103599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
1036442b46a087c389a91a0b51547ac9205058432364Roland Levillain  StackMap GetStackMapForDexPc(uint32_t dex_pc) const {
103799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
10383946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      StackMap stack_map = GetStackMapAt(i);
1039004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray      if (stack_map.GetDexPc(*this) == dex_pc) {
104099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        return stack_map;
104199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray      }
104299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    }
1043e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray    return StackMap();
104499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
104599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
1046442b46a087c389a91a0b51547ac9205058432364Roland Levillain  StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) const {
104799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    // TODO: stack maps are sorted by native pc, we can do a binary search.
104899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
10493946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      StackMap stack_map = GetStackMapAt(i);
1050004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray      if (stack_map.GetNativePcOffset(*this) == native_pc_offset) {
105199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        return stack_map;
105299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray      }
105399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    }
1054e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray    return StackMap();
105599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  }
105699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
1057f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain  // Dump this CodeInfo object on `os`.  `code_offset` is the (absolute)
1058f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain  // native PC of the compiled method and `number_of_dex_registers` the
1059f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain  // number of Dex virtual registers used in this method.  If
1060f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain  // `dump_stack_maps` is true, also dump the stack maps and the
1061f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain  // associated Dex register maps.
1062f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain  void Dump(std::ostream& os,
1063f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain            uint32_t code_offset,
1064f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain            uint16_t number_of_dex_registers,
1065f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain            bool dump_stack_maps) const;
1066004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
106799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private:
1068a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // TODO: Instead of plain types such as "uint32_t", introduce
1069a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  // typedefs (and document the memory layout of CodeInfo).
10703946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  static constexpr int kOverallSizeOffset = 0;
1071004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  static constexpr int kEncodingInfoOffset = kOverallSizeOffset + sizeof(uint32_t);
1072a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr int kNumberOfDexRegisterLocationCatalogEntriesOffset =
1073896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray      kEncodingInfoOffset + sizeof(uint16_t);
1074a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  static constexpr int kNumberOfStackMapsOffset =
1075a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      kNumberOfDexRegisterLocationCatalogEntriesOffset + sizeof(uint32_t);
107699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kStackMaskSizeOffset = kNumberOfStackMapsOffset + sizeof(uint32_t);
107799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  static constexpr int kFixedSize = kStackMaskSizeOffset + sizeof(uint32_t);
107899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
1079004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray  static constexpr int kHasInlineInfoBitOffset = (kEncodingInfoOffset * kBitsPerByte);
1080896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kInlineInfoBitOffset = kHasInlineInfoBitOffset + 1;
1081896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kDexRegisterMapBitOffset = kInlineInfoBitOffset + 3;
1082896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kDexPcBitOffset = kDexRegisterMapBitOffset + 3;
1083896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kNativePcBitOffset = kDexPcBitOffset + 3;
1084896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray  static constexpr int kRegisterMaskBitOffset = kNativePcBitOffset + 3;
1085004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray
108699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion GetStackMaps() const {
108799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray    return region_.size() == 0
108899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray        ? MemoryRegion()
1089a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        : region_.Subregion(GetStackMapsOffset(), GetStackMapsSize());
1090a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
1091a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
1092a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Compute the size of the Dex register map associated to the stack map at
1093a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // `dex_register_map_offset_in_code_info`.
1094a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t ComputeDexRegisterMapSizeOf(uint32_t dex_register_map_offset_in_code_info,
1095a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                     uint16_t number_of_dex_registers) const {
1096a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // Offset where the actual mapping data starts within art::DexRegisterMap.
1097a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t location_mapping_data_offset_in_dex_register_map =
1098a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        DexRegisterMap::GetLocationMappingDataOffset(number_of_dex_registers);
1099a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // Create a temporary art::DexRegisterMap to be able to call
1100a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // art::DexRegisterMap::GetNumberOfLiveDexRegisters and
1101a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    DexRegisterMap dex_register_map_without_locations(
1102a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        MemoryRegion(region_.Subregion(dex_register_map_offset_in_code_info,
1103a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                       location_mapping_data_offset_in_dex_register_map)));
1104a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t number_of_live_dex_registers =
1105a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        dex_register_map_without_locations.GetNumberOfLiveDexRegisters(number_of_dex_registers);
1106a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t location_mapping_data_size_in_bits =
1107a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        DexRegisterMap::SingleEntrySizeInBits(GetNumberOfDexRegisterLocationCatalogEntries())
1108a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        * number_of_live_dex_registers;
1109a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t location_mapping_data_size_in_bytes =
1110a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
1111a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t dex_register_map_size =
1112a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        location_mapping_data_offset_in_dex_register_map + location_mapping_data_size_in_bytes;
1113a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    return dex_register_map_size;
1114a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  }
1115a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
1116a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // Compute the size of a Dex register location catalog starting at offset `origin`
1117a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  // in `region_` and containing `number_of_dex_locations` entries.
1118a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain  size_t ComputeDexRegisterLocationCatalogSize(uint32_t origin,
1119a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain                                               uint32_t number_of_dex_locations) const {
1120a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // TODO: Ideally, we would like to use art::DexRegisterLocationCatalog::Size or
1121a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // art::DexRegisterLocationCatalog::FindLocationOffset, but the
1122a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // DexRegisterLocationCatalog is not yet built.  Try to factor common code.
1123a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    size_t offset = origin + DexRegisterLocationCatalog::kFixedSize;
1124a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain
1125a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    // Skip the first `number_of_dex_locations - 1` entries.
1126a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain    for (uint16_t i = 0; i < number_of_dex_locations; ++i) {
1127a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // Read the first next byte and inspect its first 3 bits to decide
1128a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      // whether it is a short or a large location.
1129a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      DexRegisterLocationCatalog::ShortLocation first_byte =
1130a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain          region_.LoadUnaligned<DexRegisterLocationCatalog::ShortLocation>(offset);
1131a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      DexRegisterLocation::Kind kind =
1132a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain          DexRegisterLocationCatalog::ExtractKindFromShortLocation(first_byte);
1133a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      if (DexRegisterLocation::IsShortLocationKind(kind)) {
1134a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        // Short location.  Skip the current byte.
1135a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        offset += DexRegisterLocationCatalog::SingleShortEntrySize();
1136a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain      } else {
1137a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        // Large location.  Skip the 5 next bytes.
1138a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain        offset += DexRegisterLocationCatalog::SingleLargeEntrySize();
1139a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain      }
1140a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    }
1141a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    size_t size = offset - origin;
1142a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain    return size;
1143a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain  }
1144a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain
114599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray  MemoryRegion region_;
11463946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  friend class StackMapStream;
114799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray};
114899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
114999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}  // namespace art
115099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray
115199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#endif  // ART_RUNTIME_STACK_MAP_H_
1152