Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_STACK_MAP_H_
     18 #define ART_RUNTIME_STACK_MAP_H_
     19 
     20 #include "base/bit_vector.h"
     21 #include "base/bit_utils.h"
     22 #include "memory_region.h"
     23 #include "leb128.h"
     24 
     25 namespace art {
     26 
     27 class VariableIndentationOutputStream;
     28 
     29 // Size of a frame slot, in bytes.  This constant is a signed value,
     30 // to please the compiler in arithmetic operations involving int32_t
     31 // (signed) values.
     32 static constexpr ssize_t kFrameSlotSize = 4;
     33 
     34 // Size of Dex virtual registers.
     35 static constexpr size_t kVRegSize = 4;
     36 
     37 class CodeInfo;
     38 class StackMapEncoding;
     39 struct CodeInfoEncoding;
     40 
     41 /**
     42  * Classes in the following file are wrapper on stack map information backed
     43  * by a MemoryRegion. As such they read and write to the region, they don't have
     44  * their own fields.
     45  */
     46 
     47 // Dex register location container used by DexRegisterMap and StackMapStream.
     48 class DexRegisterLocation {
     49  public:
     50   /*
     51    * The location kind used to populate the Dex register information in a
     52    * StackMapStream can either be:
     53    * - kStack: vreg stored on the stack, value holds the stack offset;
     54    * - kInRegister: vreg stored in low 32 bits of a core physical register,
     55    *                value holds the register number;
     56    * - kInRegisterHigh: vreg stored in high 32 bits of a core physical register,
     57    *                    value holds the register number;
     58    * - kInFpuRegister: vreg stored in low 32 bits of an FPU register,
     59    *                   value holds the register number;
     60    * - kInFpuRegisterHigh: vreg stored in high 32 bits of an FPU register,
     61    *                       value holds the register number;
     62    * - kConstant: value holds the constant;
     63    *
     64    * In addition, DexRegisterMap also uses these values:
     65    * - kInStackLargeOffset: value holds a "large" stack offset (greater than
     66    *   or equal to 128 bytes);
     67    * - kConstantLargeValue: value holds a "large" constant (lower than 0, or
     68    *   or greater than or equal to 32);
     69    * - kNone: the register has no location, meaning it has not been set.
     70    */
     71   enum class Kind : uint8_t {
     72     // Short location kinds, for entries fitting on one byte (3 bits
     73     // for the kind, 5 bits for the value) in a DexRegisterMap.
     74     kInStack = 0,             // 0b000
     75     kInRegister = 1,          // 0b001
     76     kInRegisterHigh = 2,      // 0b010
     77     kInFpuRegister = 3,       // 0b011
     78     kInFpuRegisterHigh = 4,   // 0b100
     79     kConstant = 5,            // 0b101
     80 
     81     // Large location kinds, requiring a 5-byte encoding (1 byte for the
     82     // kind, 4 bytes for the value).
     83 
     84     // Stack location at a large offset, meaning that the offset value
     85     // divided by the stack frame slot size (4 bytes) cannot fit on a
     86     // 5-bit unsigned integer (i.e., this offset value is greater than
     87     // or equal to 2^5 * 4 = 128 bytes).
     88     kInStackLargeOffset = 6,  // 0b110
     89 
     90     // Large constant, that cannot fit on a 5-bit signed integer (i.e.,
     91     // lower than 0, or greater than or equal to 2^5 = 32).
     92     kConstantLargeValue = 7,  // 0b111
     93 
     94     // Entries with no location are not stored and do not need own marker.
     95     kNone = static_cast<uint8_t>(-1),
     96 
     97     kLastLocationKind = kConstantLargeValue
     98   };
     99 
    100   static_assert(
    101       sizeof(Kind) == 1u,
    102       "art::DexRegisterLocation::Kind has a size different from one byte.");
    103 
    104   static bool IsShortLocationKind(Kind kind) {
    105     switch (kind) {
    106       case Kind::kInStack:
    107       case Kind::kInRegister:
    108       case Kind::kInRegisterHigh:
    109       case Kind::kInFpuRegister:
    110       case Kind::kInFpuRegisterHigh:
    111       case Kind::kConstant:
    112         return true;
    113 
    114       case Kind::kInStackLargeOffset:
    115       case Kind::kConstantLargeValue:
    116         return false;
    117 
    118       case Kind::kNone:
    119         LOG(FATAL) << "Unexpected location kind";
    120     }
    121     UNREACHABLE();
    122   }
    123 
    124   // Convert `kind` to a "surface" kind, i.e. one that doesn't include
    125   // any value with a "large" qualifier.
    126   // TODO: Introduce another enum type for the surface kind?
    127   static Kind ConvertToSurfaceKind(Kind kind) {
    128     switch (kind) {
    129       case Kind::kInStack:
    130       case Kind::kInRegister:
    131       case Kind::kInRegisterHigh:
    132       case Kind::kInFpuRegister:
    133       case Kind::kInFpuRegisterHigh:
    134       case Kind::kConstant:
    135         return kind;
    136 
    137       case Kind::kInStackLargeOffset:
    138         return Kind::kInStack;
    139 
    140       case Kind::kConstantLargeValue:
    141         return Kind::kConstant;
    142 
    143       case Kind::kNone:
    144         return kind;
    145     }
    146     UNREACHABLE();
    147   }
    148 
    149   // Required by art::StackMapStream::LocationCatalogEntriesIndices.
    150   DexRegisterLocation() : kind_(Kind::kNone), value_(0) {}
    151 
    152   DexRegisterLocation(Kind kind, int32_t value) : kind_(kind), value_(value) {}
    153 
    154   static DexRegisterLocation None() {
    155     return DexRegisterLocation(Kind::kNone, 0);
    156   }
    157 
    158   // Get the "surface" kind of the location, i.e., the one that doesn't
    159   // include any value with a "large" qualifier.
    160   Kind GetKind() const {
    161     return ConvertToSurfaceKind(kind_);
    162   }
    163 
    164   // Get the value of the location.
    165   int32_t GetValue() const { return value_; }
    166 
    167   // Get the actual kind of the location.
    168   Kind GetInternalKind() const { return kind_; }
    169 
    170   bool operator==(DexRegisterLocation other) const {
    171     return kind_ == other.kind_ && value_ == other.value_;
    172   }
    173 
    174   bool operator!=(DexRegisterLocation other) const {
    175     return !(*this == other);
    176   }
    177 
    178  private:
    179   Kind kind_;
    180   int32_t value_;
    181 
    182   friend class DexRegisterLocationHashFn;
    183 };
    184 
    185 std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation::Kind& kind);
    186 
    187 /**
    188  * Store information on unique Dex register locations used in a method.
    189  * The information is of the form:
    190  *
    191  *   [DexRegisterLocation+].
    192  *
    193  * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind).
    194  */
    195 class DexRegisterLocationCatalog {
    196  public:
    197   explicit DexRegisterLocationCatalog(MemoryRegion region) : region_(region) {}
    198 
    199   // Short (compressed) location, fitting on one byte.
    200   typedef uint8_t ShortLocation;
    201 
    202   void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) {
    203     DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location);
    204     int32_t value = dex_register_location.GetValue();
    205     if (DexRegisterLocation::IsShortLocationKind(kind)) {
    206       // Short location.  Compress the kind and the value as a single byte.
    207       if (kind == DexRegisterLocation::Kind::kInStack) {
    208         // Instead of storing stack offsets expressed in bytes for
    209         // short stack locations, store slot offsets.  A stack offset
    210         // is a multiple of 4 (kFrameSlotSize).  This means that by
    211         // dividing it by 4, we can fit values from the [0, 128)
    212         // interval in a short stack location, and not just values
    213         // from the [0, 32) interval.
    214         DCHECK_EQ(value % kFrameSlotSize, 0);
    215         value /= kFrameSlotSize;
    216       }
    217       DCHECK(IsShortValue(value)) << value;
    218       region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value));
    219     } else {
    220       // Large location.  Write the location on one byte and the value
    221       // on 4 bytes.
    222       DCHECK(!IsShortValue(value)) << value;
    223       if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
    224         // Also divide large stack offsets by 4 for the sake of consistency.
    225         DCHECK_EQ(value % kFrameSlotSize, 0);
    226         value /= kFrameSlotSize;
    227       }
    228       // Data can be unaligned as the written Dex register locations can
    229       // either be 1-byte or 5-byte wide.  Use
    230       // art::MemoryRegion::StoreUnaligned instead of
    231       // art::MemoryRegion::Store to prevent unligned word accesses on ARM.
    232       region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind);
    233       region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value);
    234     }
    235   }
    236 
    237   // Find the offset of the location catalog entry number `location_catalog_entry_index`.
    238   size_t FindLocationOffset(size_t location_catalog_entry_index) const {
    239     size_t offset = kFixedSize;
    240     // Skip the first `location_catalog_entry_index - 1` entries.
    241     for (uint16_t i = 0; i < location_catalog_entry_index; ++i) {
    242       // Read the first next byte and inspect its first 3 bits to decide
    243       // whether it is a short or a large location.
    244       DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
    245       if (DexRegisterLocation::IsShortLocationKind(kind)) {
    246         // Short location.  Skip the current byte.
    247         offset += SingleShortEntrySize();
    248       } else {
    249         // Large location.  Skip the 5 next bytes.
    250         offset += SingleLargeEntrySize();
    251       }
    252     }
    253     return offset;
    254   }
    255 
    256   // Get the internal kind of entry at `location_catalog_entry_index`.
    257   DexRegisterLocation::Kind GetLocationInternalKind(size_t location_catalog_entry_index) const {
    258     if (location_catalog_entry_index == kNoLocationEntryIndex) {
    259       return DexRegisterLocation::Kind::kNone;
    260     }
    261     return ExtractKindAtOffset(FindLocationOffset(location_catalog_entry_index));
    262   }
    263 
    264   // Get the (surface) kind and value of entry at `location_catalog_entry_index`.
    265   DexRegisterLocation GetDexRegisterLocation(size_t location_catalog_entry_index) const {
    266     if (location_catalog_entry_index == kNoLocationEntryIndex) {
    267       return DexRegisterLocation::None();
    268     }
    269     size_t offset = FindLocationOffset(location_catalog_entry_index);
    270     // Read the first byte and inspect its first 3 bits to get the location.
    271     ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
    272     DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte);
    273     if (DexRegisterLocation::IsShortLocationKind(kind)) {
    274       // Short location.  Extract the value from the remaining 5 bits.
    275       int32_t value = ExtractValueFromShortLocation(first_byte);
    276       if (kind == DexRegisterLocation::Kind::kInStack) {
    277         // Convert the stack slot (short) offset to a byte offset value.
    278         value *= kFrameSlotSize;
    279       }
    280       return DexRegisterLocation(kind, value);
    281     } else {
    282       // Large location.  Read the four next bytes to get the value.
    283       int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind));
    284       if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
    285         // Convert the stack slot (large) offset to a byte offset value.
    286         value *= kFrameSlotSize;
    287       }
    288       return DexRegisterLocation(kind, value);
    289     }
    290   }
    291 
    292   // Compute the compressed kind of `location`.
    293   static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) {
    294     DexRegisterLocation::Kind kind = location.GetInternalKind();
    295     switch (kind) {
    296       case DexRegisterLocation::Kind::kInStack:
    297         return IsShortStackOffsetValue(location.GetValue())
    298             ? DexRegisterLocation::Kind::kInStack
    299             : DexRegisterLocation::Kind::kInStackLargeOffset;
    300 
    301       case DexRegisterLocation::Kind::kInRegister:
    302       case DexRegisterLocation::Kind::kInRegisterHigh:
    303         DCHECK_GE(location.GetValue(), 0);
    304         DCHECK_LT(location.GetValue(), 1 << kValueBits);
    305         return kind;
    306 
    307       case DexRegisterLocation::Kind::kInFpuRegister:
    308       case DexRegisterLocation::Kind::kInFpuRegisterHigh:
    309         DCHECK_GE(location.GetValue(), 0);
    310         DCHECK_LT(location.GetValue(), 1 << kValueBits);
    311         return kind;
    312 
    313       case DexRegisterLocation::Kind::kConstant:
    314         return IsShortConstantValue(location.GetValue())
    315             ? DexRegisterLocation::Kind::kConstant
    316             : DexRegisterLocation::Kind::kConstantLargeValue;
    317 
    318       case DexRegisterLocation::Kind::kConstantLargeValue:
    319       case DexRegisterLocation::Kind::kInStackLargeOffset:
    320       case DexRegisterLocation::Kind::kNone:
    321         LOG(FATAL) << "Unexpected location kind " << kind;
    322     }
    323     UNREACHABLE();
    324   }
    325 
    326   // Can `location` be turned into a short location?
    327   static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) {
    328     DexRegisterLocation::Kind kind = location.GetInternalKind();
    329     switch (kind) {
    330       case DexRegisterLocation::Kind::kInStack:
    331         return IsShortStackOffsetValue(location.GetValue());
    332 
    333       case DexRegisterLocation::Kind::kInRegister:
    334       case DexRegisterLocation::Kind::kInRegisterHigh:
    335       case DexRegisterLocation::Kind::kInFpuRegister:
    336       case DexRegisterLocation::Kind::kInFpuRegisterHigh:
    337         return true;
    338 
    339       case DexRegisterLocation::Kind::kConstant:
    340         return IsShortConstantValue(location.GetValue());
    341 
    342       case DexRegisterLocation::Kind::kConstantLargeValue:
    343       case DexRegisterLocation::Kind::kInStackLargeOffset:
    344       case DexRegisterLocation::Kind::kNone:
    345         LOG(FATAL) << "Unexpected location kind " << kind;
    346     }
    347     UNREACHABLE();
    348   }
    349 
    350   static size_t EntrySize(const DexRegisterLocation& location) {
    351     return CanBeEncodedAsShortLocation(location) ? SingleShortEntrySize() : SingleLargeEntrySize();
    352   }
    353 
    354   static size_t SingleShortEntrySize() {
    355     return sizeof(ShortLocation);
    356   }
    357 
    358   static size_t SingleLargeEntrySize() {
    359     return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t);
    360   }
    361 
    362   size_t Size() const {
    363     return region_.size();
    364   }
    365 
    366   void Dump(VariableIndentationOutputStream* vios, const CodeInfo& code_info);
    367 
    368   // Special (invalid) Dex register location catalog entry index meaning
    369   // that there is no location for a given Dex register (i.e., it is
    370   // mapped to a DexRegisterLocation::Kind::kNone location).
    371   static constexpr size_t kNoLocationEntryIndex = -1;
    372 
    373  private:
    374   static constexpr int kFixedSize = 0;
    375 
    376   // Width of the kind "field" in a short location, in bits.
    377   static constexpr size_t kKindBits = 3;
    378   // Width of the value "field" in a short location, in bits.
    379   static constexpr size_t kValueBits = 5;
    380 
    381   static constexpr uint8_t kKindMask = (1 << kKindBits) - 1;
    382   static constexpr int32_t kValueMask = (1 << kValueBits) - 1;
    383   static constexpr size_t kKindOffset = 0;
    384   static constexpr size_t kValueOffset = kKindBits;
    385 
    386   static bool IsShortStackOffsetValue(int32_t value) {
    387     DCHECK_EQ(value % kFrameSlotSize, 0);
    388     return IsShortValue(value / kFrameSlotSize);
    389   }
    390 
    391   static bool IsShortConstantValue(int32_t value) {
    392     return IsShortValue(value);
    393   }
    394 
    395   static bool IsShortValue(int32_t value) {
    396     return IsUint<kValueBits>(value);
    397   }
    398 
    399   static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) {
    400     uint8_t kind_integer_value = static_cast<uint8_t>(kind);
    401     DCHECK(IsUint<kKindBits>(kind_integer_value)) << kind_integer_value;
    402     DCHECK(IsShortValue(value)) << value;
    403     return (kind_integer_value & kKindMask) << kKindOffset
    404         | (value & kValueMask) << kValueOffset;
    405   }
    406 
    407   static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) {
    408     uint8_t kind = (location >> kKindOffset) & kKindMask;
    409     DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind));
    410     // We do not encode kNone locations in the stack map.
    411     DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone));
    412     return static_cast<DexRegisterLocation::Kind>(kind);
    413   }
    414 
    415   static int32_t ExtractValueFromShortLocation(ShortLocation location) {
    416     return (location >> kValueOffset) & kValueMask;
    417   }
    418 
    419   // Extract a location kind from the byte at position `offset`.
    420   DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const {
    421     ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
    422     return ExtractKindFromShortLocation(first_byte);
    423   }
    424 
    425   MemoryRegion region_;
    426 
    427   friend class CodeInfo;
    428   friend class StackMapStream;
    429 };
    430 
    431 /* Information on Dex register locations for a specific PC, mapping a
    432  * stack map's Dex register to a location entry in a DexRegisterLocationCatalog.
    433  * The information is of the form:
    434  *
    435  *   [live_bit_mask, entries*]
    436  *
    437  * where entries are concatenated unsigned integer values encoded on a number
    438  * of bits (fixed per DexRegisterMap instances of a CodeInfo object) depending
    439  * on the number of entries in the Dex register location catalog
    440  * (see DexRegisterMap::SingleEntrySizeInBits).  The map is 1-byte aligned.
    441  */
    442 class DexRegisterMap {
    443  public:
    444   explicit DexRegisterMap(MemoryRegion region) : region_(region) {}
    445   DexRegisterMap() {}
    446 
    447   bool IsValid() const { return region_.pointer() != nullptr; }
    448 
    449   // Get the surface kind of Dex register `dex_register_number`.
    450   DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number,
    451                                             uint16_t number_of_dex_registers,
    452                                             const CodeInfo& code_info,
    453                                             const CodeInfoEncoding& enc) const {
    454     return DexRegisterLocation::ConvertToSurfaceKind(
    455         GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info, enc));
    456   }
    457 
    458   // Get the internal kind of Dex register `dex_register_number`.
    459   DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number,
    460                                                     uint16_t number_of_dex_registers,
    461                                                     const CodeInfo& code_info,
    462                                                     const CodeInfoEncoding& enc) const;
    463 
    464   // Get the Dex register location `dex_register_number`.
    465   DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number,
    466                                              uint16_t number_of_dex_registers,
    467                                              const CodeInfo& code_info,
    468                                              const CodeInfoEncoding& enc) const;
    469 
    470   int32_t GetStackOffsetInBytes(uint16_t dex_register_number,
    471                                 uint16_t number_of_dex_registers,
    472                                 const CodeInfo& code_info,
    473                                 const CodeInfoEncoding& enc) const {
    474     DexRegisterLocation location =
    475         GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
    476     DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
    477     // GetDexRegisterLocation returns the offset in bytes.
    478     return location.GetValue();
    479   }
    480 
    481   int32_t GetConstant(uint16_t dex_register_number,
    482                       uint16_t number_of_dex_registers,
    483                       const CodeInfo& code_info,
    484                       const CodeInfoEncoding& enc) const {
    485     DexRegisterLocation location =
    486         GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
    487     DCHECK_EQ(location.GetKind(), DexRegisterLocation::Kind::kConstant);
    488     return location.GetValue();
    489   }
    490 
    491   int32_t GetMachineRegister(uint16_t dex_register_number,
    492                              uint16_t number_of_dex_registers,
    493                              const CodeInfo& code_info,
    494                              const CodeInfoEncoding& enc) const {
    495     DexRegisterLocation location =
    496         GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
    497     DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister ||
    498            location.GetInternalKind() == DexRegisterLocation::Kind::kInRegisterHigh ||
    499            location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister ||
    500            location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegisterHigh)
    501         << location.GetInternalKind();
    502     return location.GetValue();
    503   }
    504 
    505   // Get the index of the entry in the Dex register location catalog
    506   // corresponding to `dex_register_number`.
    507   size_t GetLocationCatalogEntryIndex(uint16_t dex_register_number,
    508                                       uint16_t number_of_dex_registers,
    509                                       size_t number_of_location_catalog_entries) const {
    510     if (!IsDexRegisterLive(dex_register_number)) {
    511       return DexRegisterLocationCatalog::kNoLocationEntryIndex;
    512     }
    513 
    514     if (number_of_location_catalog_entries == 1) {
    515       // We do not allocate space for location maps in the case of a
    516       // single-entry location catalog, as it is useless.  The only valid
    517       // entry index is 0;
    518       return 0;
    519     }
    520 
    521     // The bit offset of the beginning of the map locations.
    522     size_t map_locations_offset_in_bits =
    523         GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
    524     size_t index_in_dex_register_map = GetIndexInDexRegisterMap(dex_register_number);
    525     DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
    526     // The bit size of an entry.
    527     size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
    528     // The bit offset where `index_in_dex_register_map` is located.
    529     size_t entry_offset_in_bits =
    530         map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
    531     size_t location_catalog_entry_index =
    532         region_.LoadBits(entry_offset_in_bits, map_entry_size_in_bits);
    533     DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
    534     return location_catalog_entry_index;
    535   }
    536 
    537   // Map entry at `index_in_dex_register_map` to `location_catalog_entry_index`.
    538   void SetLocationCatalogEntryIndex(size_t index_in_dex_register_map,
    539                                     size_t location_catalog_entry_index,
    540                                     uint16_t number_of_dex_registers,
    541                                     size_t number_of_location_catalog_entries) {
    542     DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
    543     DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
    544 
    545     if (number_of_location_catalog_entries == 1) {
    546       // We do not allocate space for location maps in the case of a
    547       // single-entry location catalog, as it is useless.
    548       return;
    549     }
    550 
    551     // The bit offset of the beginning of the map locations.
    552     size_t map_locations_offset_in_bits =
    553         GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
    554     // The bit size of an entry.
    555     size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
    556     // The bit offset where `index_in_dex_register_map` is located.
    557     size_t entry_offset_in_bits =
    558         map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
    559     region_.StoreBits(entry_offset_in_bits, location_catalog_entry_index, map_entry_size_in_bits);
    560   }
    561 
    562   void SetLiveBitMask(uint16_t number_of_dex_registers,
    563                       const BitVector& live_dex_registers_mask) {
    564     size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
    565     for (uint16_t i = 0; i < number_of_dex_registers; ++i) {
    566       region_.StoreBit(live_bit_mask_offset_in_bits + i, live_dex_registers_mask.IsBitSet(i));
    567     }
    568   }
    569 
    570   bool IsDexRegisterLive(uint16_t dex_register_number) const {
    571     size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
    572     return region_.LoadBit(live_bit_mask_offset_in_bits + dex_register_number);
    573   }
    574 
    575   size_t GetNumberOfLiveDexRegisters(uint16_t number_of_dex_registers) const {
    576     size_t number_of_live_dex_registers = 0;
    577     for (size_t i = 0; i < number_of_dex_registers; ++i) {
    578       if (IsDexRegisterLive(i)) {
    579         ++number_of_live_dex_registers;
    580       }
    581     }
    582     return number_of_live_dex_registers;
    583   }
    584 
    585   static size_t GetLiveBitMaskOffset() {
    586     return kFixedSize;
    587   }
    588 
    589   // Compute the size of the live register bit mask (in bytes), for a
    590   // method having `number_of_dex_registers` Dex registers.
    591   static size_t GetLiveBitMaskSize(uint16_t number_of_dex_registers) {
    592     return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte;
    593   }
    594 
    595   static size_t GetLocationMappingDataOffset(uint16_t number_of_dex_registers) {
    596     return GetLiveBitMaskOffset() + GetLiveBitMaskSize(number_of_dex_registers);
    597   }
    598 
    599   size_t GetLocationMappingDataSize(uint16_t number_of_dex_registers,
    600                                     size_t number_of_location_catalog_entries) const {
    601     size_t location_mapping_data_size_in_bits =
    602         GetNumberOfLiveDexRegisters(number_of_dex_registers)
    603         * SingleEntrySizeInBits(number_of_location_catalog_entries);
    604     return RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
    605   }
    606 
    607   // Return the size of a map entry in bits.  Note that if
    608   // `number_of_location_catalog_entries` equals 1, this function returns 0,
    609   // which is fine, as there is no need to allocate a map for a
    610   // single-entry location catalog; the only valid location catalog entry index
    611   // for a live register in this case is 0 and there is no need to
    612   // store it.
    613   static size_t SingleEntrySizeInBits(size_t number_of_location_catalog_entries) {
    614     // Handle the case of 0, as we cannot pass 0 to art::WhichPowerOf2.
    615     return number_of_location_catalog_entries == 0
    616         ? 0u
    617         : WhichPowerOf2(RoundUpToPowerOfTwo(number_of_location_catalog_entries));
    618   }
    619 
    620   // Return the size of the DexRegisterMap object, in bytes.
    621   size_t Size() const {
    622     return region_.size();
    623   }
    624 
    625   void Dump(VariableIndentationOutputStream* vios,
    626             const CodeInfo& code_info, uint16_t number_of_dex_registers) const;
    627 
    628  private:
    629   // Return the index in the Dex register map corresponding to the Dex
    630   // register number `dex_register_number`.
    631   size_t GetIndexInDexRegisterMap(uint16_t dex_register_number) const {
    632     if (!IsDexRegisterLive(dex_register_number)) {
    633       return kInvalidIndexInDexRegisterMap;
    634     }
    635     return GetNumberOfLiveDexRegisters(dex_register_number);
    636   }
    637 
    638   // Special (invalid) Dex register map entry index meaning that there
    639   // is no index in the map for a given Dex register (i.e., it must
    640   // have been mapped to a DexRegisterLocation::Kind::kNone location).
    641   static constexpr size_t kInvalidIndexInDexRegisterMap = -1;
    642 
    643   static constexpr int kFixedSize = 0;
    644 
    645   MemoryRegion region_;
    646 
    647   friend class CodeInfo;
    648   friend class StackMapStream;
    649 };
    650 
    651 // Represents bit range of bit-packed integer field.
    652 // We reuse the idea from ULEB128p1 to support encoding of -1 (aka 0xFFFFFFFF).
    653 // If min_value is set to -1, we implicitly subtract one from any loaded value,
    654 // and add one to any stored value. This is generalized to any negative values.
    655 // In other words, min_value acts as a base and the stored value is added to it.
    656 struct FieldEncoding {
    657   FieldEncoding(size_t start_offset, size_t end_offset, int32_t min_value = 0)
    658       : start_offset_(start_offset), end_offset_(end_offset), min_value_(min_value) {
    659     DCHECK_LE(start_offset_, end_offset_);
    660     DCHECK_LE(BitSize(), 32u);
    661   }
    662 
    663   ALWAYS_INLINE size_t BitSize() const { return end_offset_ - start_offset_; }
    664 
    665   ALWAYS_INLINE int32_t Load(const MemoryRegion& region) const {
    666     DCHECK_LE(end_offset_, region.size_in_bits());
    667     const size_t bit_count = BitSize();
    668     if (bit_count == 0) {
    669       // Do not touch any memory if the range is empty.
    670       return min_value_;
    671     }
    672     uint8_t* address = region.start() + start_offset_ / kBitsPerByte;
    673     const uint32_t shift = start_offset_ & (kBitsPerByte - 1);
    674     // Load the value (reading only the strictly needed bytes).
    675     const uint32_t load_bit_count = shift + bit_count;
    676     uint32_t value = *address++ >> shift;
    677     if (load_bit_count > 8) {
    678       value |= static_cast<uint32_t>(*address++) << (8 - shift);
    679       if (load_bit_count > 16) {
    680         value |= static_cast<uint32_t>(*address++) << (16 - shift);
    681         if (load_bit_count > 24) {
    682           value |= static_cast<uint32_t>(*address++) << (24 - shift);
    683           if (load_bit_count > 32) {
    684             value |= static_cast<uint32_t>(*address++) << (32 - shift);
    685           }
    686         }
    687       }
    688     }
    689     // Clear unwanted most significant bits.
    690     uint32_t clear_bit_count = 32 - bit_count;
    691     value = (value << clear_bit_count) >> clear_bit_count;
    692     return value + min_value_;
    693   }
    694 
    695   ALWAYS_INLINE void Store(MemoryRegion region, int32_t value) const {
    696     region.StoreBits(start_offset_, value - min_value_, BitSize());
    697     DCHECK_EQ(Load(region), value);
    698   }
    699 
    700  private:
    701   size_t start_offset_;
    702   size_t end_offset_;
    703   int32_t min_value_;
    704 };
    705 
    706 class StackMapEncoding {
    707  public:
    708   StackMapEncoding() {}
    709 
    710   // Set stack map bit layout based on given sizes.
    711   // Returns the size of stack map in bytes.
    712   size_t SetFromSizes(size_t native_pc_max,
    713                       size_t dex_pc_max,
    714                       size_t dex_register_map_size,
    715                       size_t inline_info_size,
    716                       size_t register_mask_max,
    717                       size_t stack_mask_bit_size) {
    718     size_t bit_offset = 0;
    719     DCHECK_EQ(kNativePcBitOffset, bit_offset);
    720     bit_offset += MinimumBitsToStore(native_pc_max);
    721 
    722     dex_pc_bit_offset_ = dchecked_integral_cast<uint8_t>(bit_offset);
    723     bit_offset += MinimumBitsToStore(1 /* kNoDexPc */ + dex_pc_max);
    724 
    725     // We also need +1 for kNoDexRegisterMap, but since the size is strictly
    726     // greater than any offset we might try to encode, we already implicitly have it.
    727     dex_register_map_bit_offset_ = dchecked_integral_cast<uint8_t>(bit_offset);
    728     bit_offset += MinimumBitsToStore(dex_register_map_size);
    729 
    730     // We also need +1 for kNoInlineInfo, but since the inline_info_size is strictly
    731     // greater than the offset we might try to encode, we already implicitly have it.
    732     // If inline_info_size is zero, we can encode only kNoInlineInfo (in zero bits).
    733     inline_info_bit_offset_ = dchecked_integral_cast<uint8_t>(bit_offset);
    734     if (inline_info_size != 0) {
    735       bit_offset += MinimumBitsToStore(dex_register_map_size + inline_info_size);
    736     }
    737 
    738     register_mask_bit_offset_ = dchecked_integral_cast<uint8_t>(bit_offset);
    739     bit_offset += MinimumBitsToStore(register_mask_max);
    740 
    741     stack_mask_bit_offset_ = dchecked_integral_cast<uint8_t>(bit_offset);
    742     bit_offset += stack_mask_bit_size;
    743 
    744     return RoundUp(bit_offset, kBitsPerByte) / kBitsPerByte;
    745   }
    746 
    747   ALWAYS_INLINE FieldEncoding GetNativePcEncoding() const {
    748     return FieldEncoding(kNativePcBitOffset, dex_pc_bit_offset_);
    749   }
    750   ALWAYS_INLINE FieldEncoding GetDexPcEncoding() const {
    751     return FieldEncoding(dex_pc_bit_offset_, dex_register_map_bit_offset_, -1 /* min_value */);
    752   }
    753   ALWAYS_INLINE FieldEncoding GetDexRegisterMapEncoding() const {
    754     return FieldEncoding(dex_register_map_bit_offset_, inline_info_bit_offset_, -1 /* min_value */);
    755   }
    756   ALWAYS_INLINE FieldEncoding GetInlineInfoEncoding() const {
    757     return FieldEncoding(inline_info_bit_offset_, register_mask_bit_offset_, -1 /* min_value */);
    758   }
    759   ALWAYS_INLINE FieldEncoding GetRegisterMaskEncoding() const {
    760     return FieldEncoding(register_mask_bit_offset_, stack_mask_bit_offset_);
    761   }
    762   ALWAYS_INLINE size_t GetStackMaskBitOffset() const {
    763     // The end offset is not encoded. It is implicitly the end of stack map entry.
    764     return stack_mask_bit_offset_;
    765   }
    766 
    767   void Dump(VariableIndentationOutputStream* vios) const;
    768 
    769  private:
    770   static constexpr size_t kNativePcBitOffset = 0;
    771   uint8_t dex_pc_bit_offset_;
    772   uint8_t dex_register_map_bit_offset_;
    773   uint8_t inline_info_bit_offset_;
    774   uint8_t register_mask_bit_offset_;
    775   uint8_t stack_mask_bit_offset_;
    776 };
    777 
    778 /**
    779  * A Stack Map holds compilation information for a specific PC necessary for:
    780  * - Mapping it to a dex PC,
    781  * - Knowing which stack entries are objects,
    782  * - Knowing which registers hold objects,
    783  * - Knowing the inlining information,
    784  * - Knowing the values of dex registers.
    785  *
    786  * The information is of the form:
    787  *
    788  *   [native_pc_offset, dex_pc, dex_register_map_offset, inlining_info_offset, register_mask,
    789  *   stack_mask].
    790  */
    791 class StackMap {
    792  public:
    793   StackMap() {}
    794   explicit StackMap(MemoryRegion region) : region_(region) {}
    795 
    796   ALWAYS_INLINE bool IsValid() const { return region_.pointer() != nullptr; }
    797 
    798   ALWAYS_INLINE uint32_t GetDexPc(const StackMapEncoding& encoding) const {
    799     return encoding.GetDexPcEncoding().Load(region_);
    800   }
    801 
    802   ALWAYS_INLINE void SetDexPc(const StackMapEncoding& encoding, uint32_t dex_pc) {
    803     encoding.GetDexPcEncoding().Store(region_, dex_pc);
    804   }
    805 
    806   ALWAYS_INLINE uint32_t GetNativePcOffset(const StackMapEncoding& encoding) const {
    807     return encoding.GetNativePcEncoding().Load(region_);
    808   }
    809 
    810   ALWAYS_INLINE void SetNativePcOffset(const StackMapEncoding& encoding, uint32_t native_pc_offset) {
    811     encoding.GetNativePcEncoding().Store(region_, native_pc_offset);
    812   }
    813 
    814   ALWAYS_INLINE uint32_t GetDexRegisterMapOffset(const StackMapEncoding& encoding) const {
    815     return encoding.GetDexRegisterMapEncoding().Load(region_);
    816   }
    817 
    818   ALWAYS_INLINE void SetDexRegisterMapOffset(const StackMapEncoding& encoding, uint32_t offset) {
    819     encoding.GetDexRegisterMapEncoding().Store(region_, offset);
    820   }
    821 
    822   ALWAYS_INLINE uint32_t GetInlineDescriptorOffset(const StackMapEncoding& encoding) const {
    823     return encoding.GetInlineInfoEncoding().Load(region_);
    824   }
    825 
    826   ALWAYS_INLINE void SetInlineDescriptorOffset(const StackMapEncoding& encoding, uint32_t offset) {
    827     encoding.GetInlineInfoEncoding().Store(region_, offset);
    828   }
    829 
    830   ALWAYS_INLINE uint32_t GetRegisterMask(const StackMapEncoding& encoding) const {
    831     return encoding.GetRegisterMaskEncoding().Load(region_);
    832   }
    833 
    834   ALWAYS_INLINE void SetRegisterMask(const StackMapEncoding& encoding, uint32_t mask) {
    835     encoding.GetRegisterMaskEncoding().Store(region_, mask);
    836   }
    837 
    838   ALWAYS_INLINE size_t GetNumberOfStackMaskBits(const StackMapEncoding& encoding) const {
    839     return region_.size_in_bits() - encoding.GetStackMaskBitOffset();
    840   }
    841 
    842   ALWAYS_INLINE bool GetStackMaskBit(const StackMapEncoding& encoding, size_t index) const {
    843     return region_.LoadBit(encoding.GetStackMaskBitOffset() + index);
    844   }
    845 
    846   ALWAYS_INLINE void SetStackMaskBit(const StackMapEncoding& encoding, size_t index, bool value) {
    847     region_.StoreBit(encoding.GetStackMaskBitOffset() + index, value);
    848   }
    849 
    850   ALWAYS_INLINE bool HasDexRegisterMap(const StackMapEncoding& encoding) const {
    851     return GetDexRegisterMapOffset(encoding) != kNoDexRegisterMap;
    852   }
    853 
    854   ALWAYS_INLINE bool HasInlineInfo(const StackMapEncoding& encoding) const {
    855     return GetInlineDescriptorOffset(encoding) != kNoInlineInfo;
    856   }
    857 
    858   ALWAYS_INLINE bool Equals(const StackMap& other) const {
    859     return region_.pointer() == other.region_.pointer() && region_.size() == other.region_.size();
    860   }
    861 
    862   void Dump(VariableIndentationOutputStream* vios,
    863             const CodeInfo& code_info,
    864             const CodeInfoEncoding& encoding,
    865             uint32_t code_offset,
    866             uint16_t number_of_dex_registers,
    867             const std::string& header_suffix = "") const;
    868 
    869   // Special (invalid) offset for the DexRegisterMapOffset field meaning
    870   // that there is no Dex register map for this stack map.
    871   static constexpr uint32_t kNoDexRegisterMap = -1;
    872 
    873   // Special (invalid) offset for the InlineDescriptorOffset field meaning
    874   // that there is no inline info for this stack map.
    875   static constexpr uint32_t kNoInlineInfo = -1;
    876 
    877  private:
    878   static constexpr int kFixedSize = 0;
    879 
    880   MemoryRegion region_;
    881 
    882   friend class StackMapStream;
    883 };
    884 
    885 class InlineInfoEncoding {
    886  public:
    887   void SetFromSizes(size_t method_index_max,
    888                     size_t dex_pc_max,
    889                     size_t invoke_type_max,
    890                     size_t dex_register_map_size) {
    891     total_bit_size_ = kMethodIndexBitOffset;
    892     total_bit_size_ += MinimumBitsToStore(method_index_max);
    893 
    894     dex_pc_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
    895     total_bit_size_ += MinimumBitsToStore(1 /* kNoDexPc */ + dex_pc_max);
    896 
    897     invoke_type_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
    898     total_bit_size_ += MinimumBitsToStore(invoke_type_max);
    899 
    900     // We also need +1 for kNoDexRegisterMap, but since the size is strictly
    901     // greater than any offset we might try to encode, we already implicitly have it.
    902     dex_register_map_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
    903     total_bit_size_ += MinimumBitsToStore(dex_register_map_size);
    904   }
    905 
    906   ALWAYS_INLINE FieldEncoding GetMethodIndexEncoding() const {
    907     return FieldEncoding(kMethodIndexBitOffset, dex_pc_bit_offset_);
    908   }
    909   ALWAYS_INLINE FieldEncoding GetDexPcEncoding() const {
    910     return FieldEncoding(dex_pc_bit_offset_, invoke_type_bit_offset_, -1 /* min_value */);
    911   }
    912   ALWAYS_INLINE FieldEncoding GetInvokeTypeEncoding() const {
    913     return FieldEncoding(invoke_type_bit_offset_, dex_register_map_bit_offset_);
    914   }
    915   ALWAYS_INLINE FieldEncoding GetDexRegisterMapEncoding() const {
    916     return FieldEncoding(dex_register_map_bit_offset_, total_bit_size_, -1 /* min_value */);
    917   }
    918   ALWAYS_INLINE size_t GetEntrySize() const {
    919     return RoundUp(total_bit_size_, kBitsPerByte) / kBitsPerByte;
    920   }
    921 
    922   void Dump(VariableIndentationOutputStream* vios) const;
    923 
    924  private:
    925   static constexpr uint8_t kIsLastBitOffset = 0;
    926   static constexpr uint8_t kMethodIndexBitOffset = 1;
    927   uint8_t dex_pc_bit_offset_;
    928   uint8_t invoke_type_bit_offset_;
    929   uint8_t dex_register_map_bit_offset_;
    930   uint8_t total_bit_size_;
    931 };
    932 
    933 /**
    934  * Inline information for a specific PC. The information is of the form:
    935  *
    936  *   [is_last, method_index, dex_pc, invoke_type, dex_register_map_offset]+.
    937  */
    938 class InlineInfo {
    939  public:
    940   explicit InlineInfo(MemoryRegion region) : region_(region) {
    941   }
    942 
    943   ALWAYS_INLINE uint32_t GetDepth(const InlineInfoEncoding& encoding) const {
    944     size_t depth = 0;
    945     while (!GetRegionAtDepth(encoding, depth++).LoadBit(0)) { }  // Check is_last bit.
    946     return depth;
    947   }
    948 
    949   ALWAYS_INLINE void SetDepth(const InlineInfoEncoding& encoding, uint32_t depth) {
    950     DCHECK_GT(depth, 0u);
    951     for (size_t d = 0; d < depth; ++d) {
    952       GetRegionAtDepth(encoding, d).StoreBit(0, d == depth - 1);  // Set is_last bit.
    953     }
    954   }
    955 
    956   ALWAYS_INLINE uint32_t GetMethodIndexAtDepth(const InlineInfoEncoding& encoding,
    957                                                uint32_t depth) const {
    958     return encoding.GetMethodIndexEncoding().Load(GetRegionAtDepth(encoding, depth));
    959   }
    960 
    961   ALWAYS_INLINE void SetMethodIndexAtDepth(const InlineInfoEncoding& encoding,
    962                                            uint32_t depth,
    963                                            uint32_t index) {
    964     encoding.GetMethodIndexEncoding().Store(GetRegionAtDepth(encoding, depth), index);
    965   }
    966 
    967   ALWAYS_INLINE uint32_t GetDexPcAtDepth(const InlineInfoEncoding& encoding,
    968                                          uint32_t depth) const {
    969     return encoding.GetDexPcEncoding().Load(GetRegionAtDepth(encoding, depth));
    970   }
    971 
    972   ALWAYS_INLINE void SetDexPcAtDepth(const InlineInfoEncoding& encoding,
    973                                      uint32_t depth,
    974                                      uint32_t dex_pc) {
    975     encoding.GetDexPcEncoding().Store(GetRegionAtDepth(encoding, depth), dex_pc);
    976   }
    977 
    978   ALWAYS_INLINE uint32_t GetInvokeTypeAtDepth(const InlineInfoEncoding& encoding,
    979                                               uint32_t depth) const {
    980     return encoding.GetInvokeTypeEncoding().Load(GetRegionAtDepth(encoding, depth));
    981   }
    982 
    983   ALWAYS_INLINE void SetInvokeTypeAtDepth(const InlineInfoEncoding& encoding,
    984                                           uint32_t depth,
    985                                           uint32_t invoke_type) {
    986     encoding.GetInvokeTypeEncoding().Store(GetRegionAtDepth(encoding, depth), invoke_type);
    987   }
    988 
    989   ALWAYS_INLINE uint32_t GetDexRegisterMapOffsetAtDepth(const InlineInfoEncoding& encoding,
    990                                                         uint32_t depth) const {
    991     return encoding.GetDexRegisterMapEncoding().Load(GetRegionAtDepth(encoding, depth));
    992   }
    993 
    994   ALWAYS_INLINE void SetDexRegisterMapOffsetAtDepth(const InlineInfoEncoding& encoding,
    995                                                     uint32_t depth,
    996                                                     uint32_t offset) {
    997     encoding.GetDexRegisterMapEncoding().Store(GetRegionAtDepth(encoding, depth), offset);
    998   }
    999 
   1000   ALWAYS_INLINE bool HasDexRegisterMapAtDepth(const InlineInfoEncoding& encoding,
   1001                                               uint32_t depth) const {
   1002     return GetDexRegisterMapOffsetAtDepth(encoding, depth) != StackMap::kNoDexRegisterMap;
   1003   }
   1004 
   1005   void Dump(VariableIndentationOutputStream* vios,
   1006             const CodeInfo& info,
   1007             uint16_t* number_of_dex_registers) const;
   1008 
   1009  private:
   1010   ALWAYS_INLINE MemoryRegion GetRegionAtDepth(const InlineInfoEncoding& encoding,
   1011                                               uint32_t depth) const {
   1012     size_t entry_size = encoding.GetEntrySize();
   1013     DCHECK_GT(entry_size, 0u);
   1014     return region_.Subregion(depth * entry_size, entry_size);
   1015   }
   1016 
   1017   MemoryRegion region_;
   1018 };
   1019 
   1020 // Most of the fields are encoded as ULEB128 to save space.
   1021 struct CodeInfoEncoding {
   1022   uint32_t non_header_size;
   1023   uint32_t number_of_stack_maps;
   1024   uint32_t stack_map_size_in_bytes;
   1025   uint32_t number_of_location_catalog_entries;
   1026   StackMapEncoding stack_map_encoding;
   1027   InlineInfoEncoding inline_info_encoding;
   1028   uint8_t header_size;
   1029 
   1030   CodeInfoEncoding() { }
   1031 
   1032   explicit CodeInfoEncoding(const void* data) {
   1033     const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
   1034     non_header_size = DecodeUnsignedLeb128(&ptr);
   1035     number_of_stack_maps = DecodeUnsignedLeb128(&ptr);
   1036     stack_map_size_in_bytes = DecodeUnsignedLeb128(&ptr);
   1037     number_of_location_catalog_entries = DecodeUnsignedLeb128(&ptr);
   1038     static_assert(alignof(StackMapEncoding) == 1,
   1039                   "StackMapEncoding should not require alignment");
   1040     stack_map_encoding = *reinterpret_cast<const StackMapEncoding*>(ptr);
   1041     ptr += sizeof(StackMapEncoding);
   1042     if (stack_map_encoding.GetInlineInfoEncoding().BitSize() > 0) {
   1043       static_assert(alignof(InlineInfoEncoding) == 1,
   1044                     "InlineInfoEncoding should not require alignment");
   1045       inline_info_encoding = *reinterpret_cast<const InlineInfoEncoding*>(ptr);
   1046       ptr += sizeof(InlineInfoEncoding);
   1047     } else {
   1048       inline_info_encoding = InlineInfoEncoding{}; // NOLINT.
   1049     }
   1050     header_size = dchecked_integral_cast<uint8_t>(ptr - reinterpret_cast<const uint8_t*>(data));
   1051   }
   1052 
   1053   template<typename Vector>
   1054   void Compress(Vector* dest) const {
   1055     EncodeUnsignedLeb128(dest, non_header_size);
   1056     EncodeUnsignedLeb128(dest, number_of_stack_maps);
   1057     EncodeUnsignedLeb128(dest, stack_map_size_in_bytes);
   1058     EncodeUnsignedLeb128(dest, number_of_location_catalog_entries);
   1059     const uint8_t* stack_map_ptr = reinterpret_cast<const uint8_t*>(&stack_map_encoding);
   1060     dest->insert(dest->end(), stack_map_ptr, stack_map_ptr + sizeof(StackMapEncoding));
   1061     if (stack_map_encoding.GetInlineInfoEncoding().BitSize() > 0) {
   1062       const uint8_t* inline_info_ptr = reinterpret_cast<const uint8_t*>(&inline_info_encoding);
   1063       dest->insert(dest->end(), inline_info_ptr, inline_info_ptr + sizeof(InlineInfoEncoding));
   1064     }
   1065   }
   1066 };
   1067 
   1068 /**
   1069  * Wrapper around all compiler information collected for a method.
   1070  * The information is of the form:
   1071  *
   1072  *   [CodeInfoEncoding, StackMap+, DexRegisterLocationCatalog+, DexRegisterMap+, InlineInfo*]
   1073  *
   1074  * where CodeInfoEncoding is of the form:
   1075  *
   1076  *   [non_header_size, number_of_stack_maps, stack_map_size_in_bytes,
   1077  *    number_of_location_catalog_entries, StackMapEncoding]
   1078  */
   1079 class CodeInfo {
   1080  public:
   1081   explicit CodeInfo(MemoryRegion region) : region_(region) {
   1082   }
   1083 
   1084   explicit CodeInfo(const void* data) {
   1085     CodeInfoEncoding encoding = CodeInfoEncoding(data);
   1086     region_ = MemoryRegion(const_cast<void*>(data),
   1087                            encoding.header_size + encoding.non_header_size);
   1088   }
   1089 
   1090   CodeInfoEncoding ExtractEncoding() const {
   1091     return CodeInfoEncoding(region_.start());
   1092   }
   1093 
   1094   bool HasInlineInfo(const CodeInfoEncoding& encoding) const {
   1095     return encoding.stack_map_encoding.GetInlineInfoEncoding().BitSize() > 0;
   1096   }
   1097 
   1098   DexRegisterLocationCatalog GetDexRegisterLocationCatalog(const CodeInfoEncoding& encoding) const {
   1099     return DexRegisterLocationCatalog(region_.Subregion(
   1100         GetDexRegisterLocationCatalogOffset(encoding),
   1101         GetDexRegisterLocationCatalogSize(encoding)));
   1102   }
   1103 
   1104   StackMap GetStackMapAt(size_t i, const CodeInfoEncoding& encoding) const {
   1105     size_t stack_map_size = encoding.stack_map_size_in_bytes;
   1106     return StackMap(GetStackMaps(encoding).Subregion(i * stack_map_size, stack_map_size));
   1107   }
   1108 
   1109   uint32_t GetNumberOfLocationCatalogEntries(const CodeInfoEncoding& encoding) const {
   1110     return encoding.number_of_location_catalog_entries;
   1111   }
   1112 
   1113   uint32_t GetDexRegisterLocationCatalogSize(const CodeInfoEncoding& encoding) const {
   1114     return ComputeDexRegisterLocationCatalogSize(GetDexRegisterLocationCatalogOffset(encoding),
   1115                                                  GetNumberOfLocationCatalogEntries(encoding));
   1116   }
   1117 
   1118   uint32_t GetNumberOfStackMaps(const CodeInfoEncoding& encoding) const {
   1119     return encoding.number_of_stack_maps;
   1120   }
   1121 
   1122   // Get the size of all the stack maps of this CodeInfo object, in bytes.
   1123   size_t GetStackMapsSize(const CodeInfoEncoding& encoding) const {
   1124     return encoding.stack_map_size_in_bytes * GetNumberOfStackMaps(encoding);
   1125   }
   1126 
   1127   uint32_t GetDexRegisterLocationCatalogOffset(const CodeInfoEncoding& encoding) const {
   1128     return GetStackMapsOffset(encoding) + GetStackMapsSize(encoding);
   1129   }
   1130 
   1131   size_t GetDexRegisterMapsOffset(const CodeInfoEncoding& encoding) const {
   1132     return GetDexRegisterLocationCatalogOffset(encoding)
   1133          + GetDexRegisterLocationCatalogSize(encoding);
   1134   }
   1135 
   1136   uint32_t GetStackMapsOffset(const CodeInfoEncoding& encoding) const {
   1137     return encoding.header_size;
   1138   }
   1139 
   1140   DexRegisterMap GetDexRegisterMapOf(StackMap stack_map,
   1141                                      const CodeInfoEncoding& encoding,
   1142                                      uint32_t number_of_dex_registers) const {
   1143     if (!stack_map.HasDexRegisterMap(encoding.stack_map_encoding)) {
   1144       return DexRegisterMap();
   1145     } else {
   1146       uint32_t offset = GetDexRegisterMapsOffset(encoding)
   1147                         + stack_map.GetDexRegisterMapOffset(encoding.stack_map_encoding);
   1148       size_t size = ComputeDexRegisterMapSizeOf(encoding, offset, number_of_dex_registers);
   1149       return DexRegisterMap(region_.Subregion(offset, size));
   1150     }
   1151   }
   1152 
   1153   // Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`.
   1154   DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth,
   1155                                           InlineInfo inline_info,
   1156                                           const CodeInfoEncoding& encoding,
   1157                                           uint32_t number_of_dex_registers) const {
   1158     if (!inline_info.HasDexRegisterMapAtDepth(encoding.inline_info_encoding, depth)) {
   1159       return DexRegisterMap();
   1160     } else {
   1161       uint32_t offset = GetDexRegisterMapsOffset(encoding) +
   1162           inline_info.GetDexRegisterMapOffsetAtDepth(encoding.inline_info_encoding, depth);
   1163       size_t size = ComputeDexRegisterMapSizeOf(encoding, offset, number_of_dex_registers);
   1164       return DexRegisterMap(region_.Subregion(offset, size));
   1165     }
   1166   }
   1167 
   1168   InlineInfo GetInlineInfoOf(StackMap stack_map, const CodeInfoEncoding& encoding) const {
   1169     DCHECK(stack_map.HasInlineInfo(encoding.stack_map_encoding));
   1170     uint32_t offset = stack_map.GetInlineDescriptorOffset(encoding.stack_map_encoding)
   1171                       + GetDexRegisterMapsOffset(encoding);
   1172     return InlineInfo(region_.Subregion(offset, region_.size() - offset));
   1173   }
   1174 
   1175   StackMap GetStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const {
   1176     for (size_t i = 0, e = GetNumberOfStackMaps(encoding); i < e; ++i) {
   1177       StackMap stack_map = GetStackMapAt(i, encoding);
   1178       if (stack_map.GetDexPc(encoding.stack_map_encoding) == dex_pc) {
   1179         return stack_map;
   1180       }
   1181     }
   1182     return StackMap();
   1183   }
   1184 
   1185   // Searches the stack map list backwards because catch stack maps are stored
   1186   // at the end.
   1187   StackMap GetCatchStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const {
   1188     for (size_t i = GetNumberOfStackMaps(encoding); i > 0; --i) {
   1189       StackMap stack_map = GetStackMapAt(i - 1, encoding);
   1190       if (stack_map.GetDexPc(encoding.stack_map_encoding) == dex_pc) {
   1191         return stack_map;
   1192       }
   1193     }
   1194     return StackMap();
   1195   }
   1196 
   1197   StackMap GetOsrStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const {
   1198     size_t e = GetNumberOfStackMaps(encoding);
   1199     if (e == 0) {
   1200       // There cannot be OSR stack map if there is no stack map.
   1201       return StackMap();
   1202     }
   1203     // Walk over all stack maps. If two consecutive stack maps are identical, then we
   1204     // have found a stack map suitable for OSR.
   1205     const StackMapEncoding& stack_map_encoding = encoding.stack_map_encoding;
   1206     for (size_t i = 0; i < e - 1; ++i) {
   1207       StackMap stack_map = GetStackMapAt(i, encoding);
   1208       if (stack_map.GetDexPc(stack_map_encoding) == dex_pc) {
   1209         StackMap other = GetStackMapAt(i + 1, encoding);
   1210         if (other.GetDexPc(stack_map_encoding) == dex_pc &&
   1211             other.GetNativePcOffset(stack_map_encoding) ==
   1212                 stack_map.GetNativePcOffset(stack_map_encoding)) {
   1213           DCHECK_EQ(other.GetDexRegisterMapOffset(stack_map_encoding),
   1214                     stack_map.GetDexRegisterMapOffset(stack_map_encoding));
   1215           DCHECK(!stack_map.HasInlineInfo(stack_map_encoding));
   1216           if (i < e - 2) {
   1217             // Make sure there are not three identical stack maps following each other.
   1218             DCHECK_NE(stack_map.GetNativePcOffset(stack_map_encoding),
   1219                       GetStackMapAt(i + 2, encoding).GetNativePcOffset(stack_map_encoding));
   1220           }
   1221           return stack_map;
   1222         }
   1223       }
   1224     }
   1225     return StackMap();
   1226   }
   1227 
   1228   StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset,
   1229                                         const CodeInfoEncoding& encoding) const {
   1230     // TODO: Safepoint stack maps are sorted by native_pc_offset but catch stack
   1231     //       maps are not. If we knew that the method does not have try/catch,
   1232     //       we could do binary search.
   1233     for (size_t i = 0, e = GetNumberOfStackMaps(encoding); i < e; ++i) {
   1234       StackMap stack_map = GetStackMapAt(i, encoding);
   1235       if (stack_map.GetNativePcOffset(encoding.stack_map_encoding) == native_pc_offset) {
   1236         return stack_map;
   1237       }
   1238     }
   1239     return StackMap();
   1240   }
   1241 
   1242   // Dump this CodeInfo object on `os`.  `code_offset` is the (absolute)
   1243   // native PC of the compiled method and `number_of_dex_registers` the
   1244   // number of Dex virtual registers used in this method.  If
   1245   // `dump_stack_maps` is true, also dump the stack maps and the
   1246   // associated Dex register maps.
   1247   void Dump(VariableIndentationOutputStream* vios,
   1248             uint32_t code_offset,
   1249             uint16_t number_of_dex_registers,
   1250             bool dump_stack_maps) const;
   1251 
   1252  private:
   1253   MemoryRegion GetStackMaps(const CodeInfoEncoding& encoding) const {
   1254     return region_.size() == 0
   1255         ? MemoryRegion()
   1256         : region_.Subregion(GetStackMapsOffset(encoding), GetStackMapsSize(encoding));
   1257   }
   1258 
   1259   // Compute the size of the Dex register map associated to the stack map at
   1260   // `dex_register_map_offset_in_code_info`.
   1261   size_t ComputeDexRegisterMapSizeOf(const CodeInfoEncoding& encoding,
   1262                                      uint32_t dex_register_map_offset_in_code_info,
   1263                                      uint16_t number_of_dex_registers) const {
   1264     // Offset where the actual mapping data starts within art::DexRegisterMap.
   1265     size_t location_mapping_data_offset_in_dex_register_map =
   1266         DexRegisterMap::GetLocationMappingDataOffset(number_of_dex_registers);
   1267     // Create a temporary art::DexRegisterMap to be able to call
   1268     // art::DexRegisterMap::GetNumberOfLiveDexRegisters and
   1269     DexRegisterMap dex_register_map_without_locations(
   1270         MemoryRegion(region_.Subregion(dex_register_map_offset_in_code_info,
   1271                                        location_mapping_data_offset_in_dex_register_map)));
   1272     size_t number_of_live_dex_registers =
   1273         dex_register_map_without_locations.GetNumberOfLiveDexRegisters(number_of_dex_registers);
   1274     size_t location_mapping_data_size_in_bits =
   1275         DexRegisterMap::SingleEntrySizeInBits(GetNumberOfLocationCatalogEntries(encoding))
   1276         * number_of_live_dex_registers;
   1277     size_t location_mapping_data_size_in_bytes =
   1278         RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
   1279     size_t dex_register_map_size =
   1280         location_mapping_data_offset_in_dex_register_map + location_mapping_data_size_in_bytes;
   1281     return dex_register_map_size;
   1282   }
   1283 
   1284   // Compute the size of a Dex register location catalog starting at offset `origin`
   1285   // in `region_` and containing `number_of_dex_locations` entries.
   1286   size_t ComputeDexRegisterLocationCatalogSize(uint32_t origin,
   1287                                                uint32_t number_of_dex_locations) const {
   1288     // TODO: Ideally, we would like to use art::DexRegisterLocationCatalog::Size or
   1289     // art::DexRegisterLocationCatalog::FindLocationOffset, but the
   1290     // DexRegisterLocationCatalog is not yet built.  Try to factor common code.
   1291     size_t offset = origin + DexRegisterLocationCatalog::kFixedSize;
   1292 
   1293     // Skip the first `number_of_dex_locations - 1` entries.
   1294     for (uint16_t i = 0; i < number_of_dex_locations; ++i) {
   1295       // Read the first next byte and inspect its first 3 bits to decide
   1296       // whether it is a short or a large location.
   1297       DexRegisterLocationCatalog::ShortLocation first_byte =
   1298           region_.LoadUnaligned<DexRegisterLocationCatalog::ShortLocation>(offset);
   1299       DexRegisterLocation::Kind kind =
   1300           DexRegisterLocationCatalog::ExtractKindFromShortLocation(first_byte);
   1301       if (DexRegisterLocation::IsShortLocationKind(kind)) {
   1302         // Short location.  Skip the current byte.
   1303         offset += DexRegisterLocationCatalog::SingleShortEntrySize();
   1304       } else {
   1305         // Large location.  Skip the 5 next bytes.
   1306         offset += DexRegisterLocationCatalog::SingleLargeEntrySize();
   1307       }
   1308     }
   1309     size_t size = offset - origin;
   1310     return size;
   1311   }
   1312 
   1313   MemoryRegion region_;
   1314   friend class StackMapStream;
   1315 };
   1316 
   1317 #undef ELEMENT_BYTE_OFFSET_AFTER
   1318 #undef ELEMENT_BIT_OFFSET_AFTER
   1319 
   1320 }  // namespace art
   1321 
   1322 #endif  // ART_RUNTIME_STACK_MAP_H_
   1323