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 "arch/code_offset.h"
     21 #include "base/bit_vector.h"
     22 #include "base/bit_utils.h"
     23 #include "bit_memory_region.h"
     24 #include "dex_file.h"
     25 #include "memory_region.h"
     26 #include "method_info.h"
     27 #include "leb128.h"
     28 
     29 namespace art {
     30 
     31 class VariableIndentationOutputStream;
     32 
     33 // Size of a frame slot, in bytes.  This constant is a signed value,
     34 // to please the compiler in arithmetic operations involving int32_t
     35 // (signed) values.
     36 static constexpr ssize_t kFrameSlotSize = 4;
     37 
     38 // Size of Dex virtual registers.
     39 static constexpr size_t kVRegSize = 4;
     40 
     41 class ArtMethod;
     42 class CodeInfo;
     43 class StackMapEncoding;
     44 struct CodeInfoEncoding;
     45 
     46 /**
     47  * Classes in the following file are wrapper on stack map information backed
     48  * by a MemoryRegion. As such they read and write to the region, they don't have
     49  * their own fields.
     50  */
     51 
     52 // Dex register location container used by DexRegisterMap and StackMapStream.
     53 class DexRegisterLocation {
     54  public:
     55   /*
     56    * The location kind used to populate the Dex register information in a
     57    * StackMapStream can either be:
     58    * - kStack: vreg stored on the stack, value holds the stack offset;
     59    * - kInRegister: vreg stored in low 32 bits of a core physical register,
     60    *                value holds the register number;
     61    * - kInRegisterHigh: vreg stored in high 32 bits of a core physical register,
     62    *                    value holds the register number;
     63    * - kInFpuRegister: vreg stored in low 32 bits of an FPU register,
     64    *                   value holds the register number;
     65    * - kInFpuRegisterHigh: vreg stored in high 32 bits of an FPU register,
     66    *                       value holds the register number;
     67    * - kConstant: value holds the constant;
     68    *
     69    * In addition, DexRegisterMap also uses these values:
     70    * - kInStackLargeOffset: value holds a "large" stack offset (greater than
     71    *   or equal to 128 bytes);
     72    * - kConstantLargeValue: value holds a "large" constant (lower than 0, or
     73    *   or greater than or equal to 32);
     74    * - kNone: the register has no location, meaning it has not been set.
     75    */
     76   enum class Kind : uint8_t {
     77     // Short location kinds, for entries fitting on one byte (3 bits
     78     // for the kind, 5 bits for the value) in a DexRegisterMap.
     79     kInStack = 0,             // 0b000
     80     kInRegister = 1,          // 0b001
     81     kInRegisterHigh = 2,      // 0b010
     82     kInFpuRegister = 3,       // 0b011
     83     kInFpuRegisterHigh = 4,   // 0b100
     84     kConstant = 5,            // 0b101
     85 
     86     // Large location kinds, requiring a 5-byte encoding (1 byte for the
     87     // kind, 4 bytes for the value).
     88 
     89     // Stack location at a large offset, meaning that the offset value
     90     // divided by the stack frame slot size (4 bytes) cannot fit on a
     91     // 5-bit unsigned integer (i.e., this offset value is greater than
     92     // or equal to 2^5 * 4 = 128 bytes).
     93     kInStackLargeOffset = 6,  // 0b110
     94 
     95     // Large constant, that cannot fit on a 5-bit signed integer (i.e.,
     96     // lower than 0, or greater than or equal to 2^5 = 32).
     97     kConstantLargeValue = 7,  // 0b111
     98 
     99     // Entries with no location are not stored and do not need own marker.
    100     kNone = static_cast<uint8_t>(-1),
    101 
    102     kLastLocationKind = kConstantLargeValue
    103   };
    104 
    105   static_assert(
    106       sizeof(Kind) == 1u,
    107       "art::DexRegisterLocation::Kind has a size different from one byte.");
    108 
    109   static bool IsShortLocationKind(Kind kind) {
    110     switch (kind) {
    111       case Kind::kInStack:
    112       case Kind::kInRegister:
    113       case Kind::kInRegisterHigh:
    114       case Kind::kInFpuRegister:
    115       case Kind::kInFpuRegisterHigh:
    116       case Kind::kConstant:
    117         return true;
    118 
    119       case Kind::kInStackLargeOffset:
    120       case Kind::kConstantLargeValue:
    121         return false;
    122 
    123       case Kind::kNone:
    124         LOG(FATAL) << "Unexpected location kind";
    125     }
    126     UNREACHABLE();
    127   }
    128 
    129   // Convert `kind` to a "surface" kind, i.e. one that doesn't include
    130   // any value with a "large" qualifier.
    131   // TODO: Introduce another enum type for the surface kind?
    132   static Kind ConvertToSurfaceKind(Kind kind) {
    133     switch (kind) {
    134       case Kind::kInStack:
    135       case Kind::kInRegister:
    136       case Kind::kInRegisterHigh:
    137       case Kind::kInFpuRegister:
    138       case Kind::kInFpuRegisterHigh:
    139       case Kind::kConstant:
    140         return kind;
    141 
    142       case Kind::kInStackLargeOffset:
    143         return Kind::kInStack;
    144 
    145       case Kind::kConstantLargeValue:
    146         return Kind::kConstant;
    147 
    148       case Kind::kNone:
    149         return kind;
    150     }
    151     UNREACHABLE();
    152   }
    153 
    154   // Required by art::StackMapStream::LocationCatalogEntriesIndices.
    155   DexRegisterLocation() : kind_(Kind::kNone), value_(0) {}
    156 
    157   DexRegisterLocation(Kind kind, int32_t value) : kind_(kind), value_(value) {}
    158 
    159   static DexRegisterLocation None() {
    160     return DexRegisterLocation(Kind::kNone, 0);
    161   }
    162 
    163   // Get the "surface" kind of the location, i.e., the one that doesn't
    164   // include any value with a "large" qualifier.
    165   Kind GetKind() const {
    166     return ConvertToSurfaceKind(kind_);
    167   }
    168 
    169   // Get the value of the location.
    170   int32_t GetValue() const { return value_; }
    171 
    172   // Get the actual kind of the location.
    173   Kind GetInternalKind() const { return kind_; }
    174 
    175   bool operator==(DexRegisterLocation other) const {
    176     return kind_ == other.kind_ && value_ == other.value_;
    177   }
    178 
    179   bool operator!=(DexRegisterLocation other) const {
    180     return !(*this == other);
    181   }
    182 
    183  private:
    184   Kind kind_;
    185   int32_t value_;
    186 
    187   friend class DexRegisterLocationHashFn;
    188 };
    189 
    190 std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation::Kind& kind);
    191 
    192 /**
    193  * Store information on unique Dex register locations used in a method.
    194  * The information is of the form:
    195  *
    196  *   [DexRegisterLocation+].
    197  *
    198  * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind).
    199  */
    200 class DexRegisterLocationCatalog {
    201  public:
    202   explicit DexRegisterLocationCatalog(MemoryRegion region) : region_(region) {}
    203 
    204   // Short (compressed) location, fitting on one byte.
    205   typedef uint8_t ShortLocation;
    206 
    207   void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) {
    208     DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location);
    209     int32_t value = dex_register_location.GetValue();
    210     if (DexRegisterLocation::IsShortLocationKind(kind)) {
    211       // Short location.  Compress the kind and the value as a single byte.
    212       if (kind == DexRegisterLocation::Kind::kInStack) {
    213         // Instead of storing stack offsets expressed in bytes for
    214         // short stack locations, store slot offsets.  A stack offset
    215         // is a multiple of 4 (kFrameSlotSize).  This means that by
    216         // dividing it by 4, we can fit values from the [0, 128)
    217         // interval in a short stack location, and not just values
    218         // from the [0, 32) interval.
    219         DCHECK_EQ(value % kFrameSlotSize, 0);
    220         value /= kFrameSlotSize;
    221       }
    222       DCHECK(IsShortValue(value)) << value;
    223       region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value));
    224     } else {
    225       // Large location.  Write the location on one byte and the value
    226       // on 4 bytes.
    227       DCHECK(!IsShortValue(value)) << value;
    228       if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
    229         // Also divide large stack offsets by 4 for the sake of consistency.
    230         DCHECK_EQ(value % kFrameSlotSize, 0);
    231         value /= kFrameSlotSize;
    232       }
    233       // Data can be unaligned as the written Dex register locations can
    234       // either be 1-byte or 5-byte wide.  Use
    235       // art::MemoryRegion::StoreUnaligned instead of
    236       // art::MemoryRegion::Store to prevent unligned word accesses on ARM.
    237       region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind);
    238       region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value);
    239     }
    240   }
    241 
    242   // Find the offset of the location catalog entry number `location_catalog_entry_index`.
    243   size_t FindLocationOffset(size_t location_catalog_entry_index) const {
    244     size_t offset = kFixedSize;
    245     // Skip the first `location_catalog_entry_index - 1` entries.
    246     for (uint16_t i = 0; i < location_catalog_entry_index; ++i) {
    247       // Read the first next byte and inspect its first 3 bits to decide
    248       // whether it is a short or a large location.
    249       DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset);
    250       if (DexRegisterLocation::IsShortLocationKind(kind)) {
    251         // Short location.  Skip the current byte.
    252         offset += SingleShortEntrySize();
    253       } else {
    254         // Large location.  Skip the 5 next bytes.
    255         offset += SingleLargeEntrySize();
    256       }
    257     }
    258     return offset;
    259   }
    260 
    261   // Get the internal kind of entry at `location_catalog_entry_index`.
    262   DexRegisterLocation::Kind GetLocationInternalKind(size_t location_catalog_entry_index) const {
    263     if (location_catalog_entry_index == kNoLocationEntryIndex) {
    264       return DexRegisterLocation::Kind::kNone;
    265     }
    266     return ExtractKindAtOffset(FindLocationOffset(location_catalog_entry_index));
    267   }
    268 
    269   // Get the (surface) kind and value of entry at `location_catalog_entry_index`.
    270   DexRegisterLocation GetDexRegisterLocation(size_t location_catalog_entry_index) const {
    271     if (location_catalog_entry_index == kNoLocationEntryIndex) {
    272       return DexRegisterLocation::None();
    273     }
    274     size_t offset = FindLocationOffset(location_catalog_entry_index);
    275     // Read the first byte and inspect its first 3 bits to get the location.
    276     ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
    277     DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte);
    278     if (DexRegisterLocation::IsShortLocationKind(kind)) {
    279       // Short location.  Extract the value from the remaining 5 bits.
    280       int32_t value = ExtractValueFromShortLocation(first_byte);
    281       if (kind == DexRegisterLocation::Kind::kInStack) {
    282         // Convert the stack slot (short) offset to a byte offset value.
    283         value *= kFrameSlotSize;
    284       }
    285       return DexRegisterLocation(kind, value);
    286     } else {
    287       // Large location.  Read the four next bytes to get the value.
    288       int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind));
    289       if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) {
    290         // Convert the stack slot (large) offset to a byte offset value.
    291         value *= kFrameSlotSize;
    292       }
    293       return DexRegisterLocation(kind, value);
    294     }
    295   }
    296 
    297   // Compute the compressed kind of `location`.
    298   static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) {
    299     DexRegisterLocation::Kind kind = location.GetInternalKind();
    300     switch (kind) {
    301       case DexRegisterLocation::Kind::kInStack:
    302         return IsShortStackOffsetValue(location.GetValue())
    303             ? DexRegisterLocation::Kind::kInStack
    304             : DexRegisterLocation::Kind::kInStackLargeOffset;
    305 
    306       case DexRegisterLocation::Kind::kInRegister:
    307       case DexRegisterLocation::Kind::kInRegisterHigh:
    308         DCHECK_GE(location.GetValue(), 0);
    309         DCHECK_LT(location.GetValue(), 1 << kValueBits);
    310         return kind;
    311 
    312       case DexRegisterLocation::Kind::kInFpuRegister:
    313       case DexRegisterLocation::Kind::kInFpuRegisterHigh:
    314         DCHECK_GE(location.GetValue(), 0);
    315         DCHECK_LT(location.GetValue(), 1 << kValueBits);
    316         return kind;
    317 
    318       case DexRegisterLocation::Kind::kConstant:
    319         return IsShortConstantValue(location.GetValue())
    320             ? DexRegisterLocation::Kind::kConstant
    321             : DexRegisterLocation::Kind::kConstantLargeValue;
    322 
    323       case DexRegisterLocation::Kind::kConstantLargeValue:
    324       case DexRegisterLocation::Kind::kInStackLargeOffset:
    325       case DexRegisterLocation::Kind::kNone:
    326         LOG(FATAL) << "Unexpected location kind " << kind;
    327     }
    328     UNREACHABLE();
    329   }
    330 
    331   // Can `location` be turned into a short location?
    332   static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) {
    333     DexRegisterLocation::Kind kind = location.GetInternalKind();
    334     switch (kind) {
    335       case DexRegisterLocation::Kind::kInStack:
    336         return IsShortStackOffsetValue(location.GetValue());
    337 
    338       case DexRegisterLocation::Kind::kInRegister:
    339       case DexRegisterLocation::Kind::kInRegisterHigh:
    340       case DexRegisterLocation::Kind::kInFpuRegister:
    341       case DexRegisterLocation::Kind::kInFpuRegisterHigh:
    342         return true;
    343 
    344       case DexRegisterLocation::Kind::kConstant:
    345         return IsShortConstantValue(location.GetValue());
    346 
    347       case DexRegisterLocation::Kind::kConstantLargeValue:
    348       case DexRegisterLocation::Kind::kInStackLargeOffset:
    349       case DexRegisterLocation::Kind::kNone:
    350         LOG(FATAL) << "Unexpected location kind " << kind;
    351     }
    352     UNREACHABLE();
    353   }
    354 
    355   static size_t EntrySize(const DexRegisterLocation& location) {
    356     return CanBeEncodedAsShortLocation(location) ? SingleShortEntrySize() : SingleLargeEntrySize();
    357   }
    358 
    359   static size_t SingleShortEntrySize() {
    360     return sizeof(ShortLocation);
    361   }
    362 
    363   static size_t SingleLargeEntrySize() {
    364     return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t);
    365   }
    366 
    367   size_t Size() const {
    368     return region_.size();
    369   }
    370 
    371   void Dump(VariableIndentationOutputStream* vios,
    372             const CodeInfo& code_info);
    373 
    374   // Special (invalid) Dex register location catalog entry index meaning
    375   // that there is no location for a given Dex register (i.e., it is
    376   // mapped to a DexRegisterLocation::Kind::kNone location).
    377   static constexpr size_t kNoLocationEntryIndex = -1;
    378 
    379  private:
    380   static constexpr int kFixedSize = 0;
    381 
    382   // Width of the kind "field" in a short location, in bits.
    383   static constexpr size_t kKindBits = 3;
    384   // Width of the value "field" in a short location, in bits.
    385   static constexpr size_t kValueBits = 5;
    386 
    387   static constexpr uint8_t kKindMask = (1 << kKindBits) - 1;
    388   static constexpr int32_t kValueMask = (1 << kValueBits) - 1;
    389   static constexpr size_t kKindOffset = 0;
    390   static constexpr size_t kValueOffset = kKindBits;
    391 
    392   static bool IsShortStackOffsetValue(int32_t value) {
    393     DCHECK_EQ(value % kFrameSlotSize, 0);
    394     return IsShortValue(value / kFrameSlotSize);
    395   }
    396 
    397   static bool IsShortConstantValue(int32_t value) {
    398     return IsShortValue(value);
    399   }
    400 
    401   static bool IsShortValue(int32_t value) {
    402     return IsUint<kValueBits>(value);
    403   }
    404 
    405   static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) {
    406     uint8_t kind_integer_value = static_cast<uint8_t>(kind);
    407     DCHECK(IsUint<kKindBits>(kind_integer_value)) << kind_integer_value;
    408     DCHECK(IsShortValue(value)) << value;
    409     return (kind_integer_value & kKindMask) << kKindOffset
    410         | (value & kValueMask) << kValueOffset;
    411   }
    412 
    413   static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) {
    414     uint8_t kind = (location >> kKindOffset) & kKindMask;
    415     DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind));
    416     // We do not encode kNone locations in the stack map.
    417     DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone));
    418     return static_cast<DexRegisterLocation::Kind>(kind);
    419   }
    420 
    421   static int32_t ExtractValueFromShortLocation(ShortLocation location) {
    422     return (location >> kValueOffset) & kValueMask;
    423   }
    424 
    425   // Extract a location kind from the byte at position `offset`.
    426   DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const {
    427     ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset);
    428     return ExtractKindFromShortLocation(first_byte);
    429   }
    430 
    431   MemoryRegion region_;
    432 
    433   friend class CodeInfo;
    434   friend class StackMapStream;
    435 };
    436 
    437 /* Information on Dex register locations for a specific PC, mapping a
    438  * stack map's Dex register to a location entry in a DexRegisterLocationCatalog.
    439  * The information is of the form:
    440  *
    441  *   [live_bit_mask, entries*]
    442  *
    443  * where entries are concatenated unsigned integer values encoded on a number
    444  * of bits (fixed per DexRegisterMap instances of a CodeInfo object) depending
    445  * on the number of entries in the Dex register location catalog
    446  * (see DexRegisterMap::SingleEntrySizeInBits).  The map is 1-byte aligned.
    447  */
    448 class DexRegisterMap {
    449  public:
    450   explicit DexRegisterMap(MemoryRegion region) : region_(region) {}
    451   DexRegisterMap() {}
    452 
    453   bool IsValid() const { return region_.pointer() != nullptr; }
    454 
    455   // Get the surface kind of Dex register `dex_register_number`.
    456   DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number,
    457                                             uint16_t number_of_dex_registers,
    458                                             const CodeInfo& code_info,
    459                                             const CodeInfoEncoding& enc) const {
    460     return DexRegisterLocation::ConvertToSurfaceKind(
    461         GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info, enc));
    462   }
    463 
    464   // Get the internal kind of Dex register `dex_register_number`.
    465   DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number,
    466                                                     uint16_t number_of_dex_registers,
    467                                                     const CodeInfo& code_info,
    468                                                     const CodeInfoEncoding& enc) const;
    469 
    470   // Get the Dex register location `dex_register_number`.
    471   DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number,
    472                                              uint16_t number_of_dex_registers,
    473                                              const CodeInfo& code_info,
    474                                              const CodeInfoEncoding& enc) const;
    475 
    476   int32_t GetStackOffsetInBytes(uint16_t dex_register_number,
    477                                 uint16_t number_of_dex_registers,
    478                                 const CodeInfo& code_info,
    479                                 const CodeInfoEncoding& enc) const {
    480     DexRegisterLocation location =
    481         GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
    482     DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
    483     // GetDexRegisterLocation returns the offset in bytes.
    484     return location.GetValue();
    485   }
    486 
    487   int32_t GetConstant(uint16_t dex_register_number,
    488                       uint16_t number_of_dex_registers,
    489                       const CodeInfo& code_info,
    490                       const CodeInfoEncoding& enc) const {
    491     DexRegisterLocation location =
    492         GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
    493     DCHECK_EQ(location.GetKind(), DexRegisterLocation::Kind::kConstant);
    494     return location.GetValue();
    495   }
    496 
    497   int32_t GetMachineRegister(uint16_t dex_register_number,
    498                              uint16_t number_of_dex_registers,
    499                              const CodeInfo& code_info,
    500                              const CodeInfoEncoding& enc) const {
    501     DexRegisterLocation location =
    502         GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc);
    503     DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister ||
    504            location.GetInternalKind() == DexRegisterLocation::Kind::kInRegisterHigh ||
    505            location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister ||
    506            location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegisterHigh)
    507         << location.GetInternalKind();
    508     return location.GetValue();
    509   }
    510 
    511   // Get the index of the entry in the Dex register location catalog
    512   // corresponding to `dex_register_number`.
    513   size_t GetLocationCatalogEntryIndex(uint16_t dex_register_number,
    514                                       uint16_t number_of_dex_registers,
    515                                       size_t number_of_location_catalog_entries) const {
    516     if (!IsDexRegisterLive(dex_register_number)) {
    517       return DexRegisterLocationCatalog::kNoLocationEntryIndex;
    518     }
    519 
    520     if (number_of_location_catalog_entries == 1) {
    521       // We do not allocate space for location maps in the case of a
    522       // single-entry location catalog, as it is useless.  The only valid
    523       // entry index is 0;
    524       return 0;
    525     }
    526 
    527     // The bit offset of the beginning of the map locations.
    528     size_t map_locations_offset_in_bits =
    529         GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
    530     size_t index_in_dex_register_map = GetIndexInDexRegisterMap(dex_register_number);
    531     DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
    532     // The bit size of an entry.
    533     size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
    534     // The bit offset where `index_in_dex_register_map` is located.
    535     size_t entry_offset_in_bits =
    536         map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
    537     size_t location_catalog_entry_index =
    538         region_.LoadBits(entry_offset_in_bits, map_entry_size_in_bits);
    539     DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
    540     return location_catalog_entry_index;
    541   }
    542 
    543   // Map entry at `index_in_dex_register_map` to `location_catalog_entry_index`.
    544   void SetLocationCatalogEntryIndex(size_t index_in_dex_register_map,
    545                                     size_t location_catalog_entry_index,
    546                                     uint16_t number_of_dex_registers,
    547                                     size_t number_of_location_catalog_entries) {
    548     DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers));
    549     DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries);
    550 
    551     if (number_of_location_catalog_entries == 1) {
    552       // We do not allocate space for location maps in the case of a
    553       // single-entry location catalog, as it is useless.
    554       return;
    555     }
    556 
    557     // The bit offset of the beginning of the map locations.
    558     size_t map_locations_offset_in_bits =
    559         GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte;
    560     // The bit size of an entry.
    561     size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries);
    562     // The bit offset where `index_in_dex_register_map` is located.
    563     size_t entry_offset_in_bits =
    564         map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits;
    565     region_.StoreBits(entry_offset_in_bits, location_catalog_entry_index, map_entry_size_in_bits);
    566   }
    567 
    568   void SetLiveBitMask(uint16_t number_of_dex_registers,
    569                       const BitVector& live_dex_registers_mask) {
    570     size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
    571     for (uint16_t i = 0; i < number_of_dex_registers; ++i) {
    572       region_.StoreBit(live_bit_mask_offset_in_bits + i, live_dex_registers_mask.IsBitSet(i));
    573     }
    574   }
    575 
    576   ALWAYS_INLINE bool IsDexRegisterLive(uint16_t dex_register_number) const {
    577     size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte;
    578     return region_.LoadBit(live_bit_mask_offset_in_bits + dex_register_number);
    579   }
    580 
    581   size_t GetNumberOfLiveDexRegisters(uint16_t number_of_dex_registers) const {
    582     size_t number_of_live_dex_registers = 0;
    583     for (size_t i = 0; i < number_of_dex_registers; ++i) {
    584       if (IsDexRegisterLive(i)) {
    585         ++number_of_live_dex_registers;
    586       }
    587     }
    588     return number_of_live_dex_registers;
    589   }
    590 
    591   static size_t GetLiveBitMaskOffset() {
    592     return kFixedSize;
    593   }
    594 
    595   // Compute the size of the live register bit mask (in bytes), for a
    596   // method having `number_of_dex_registers` Dex registers.
    597   static size_t GetLiveBitMaskSize(uint16_t number_of_dex_registers) {
    598     return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte;
    599   }
    600 
    601   static size_t GetLocationMappingDataOffset(uint16_t number_of_dex_registers) {
    602     return GetLiveBitMaskOffset() + GetLiveBitMaskSize(number_of_dex_registers);
    603   }
    604 
    605   size_t GetLocationMappingDataSize(uint16_t number_of_dex_registers,
    606                                     size_t number_of_location_catalog_entries) const {
    607     size_t location_mapping_data_size_in_bits =
    608         GetNumberOfLiveDexRegisters(number_of_dex_registers)
    609         * SingleEntrySizeInBits(number_of_location_catalog_entries);
    610     return RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
    611   }
    612 
    613   // Return the size of a map entry in bits.  Note that if
    614   // `number_of_location_catalog_entries` equals 1, this function returns 0,
    615   // which is fine, as there is no need to allocate a map for a
    616   // single-entry location catalog; the only valid location catalog entry index
    617   // for a live register in this case is 0 and there is no need to
    618   // store it.
    619   static size_t SingleEntrySizeInBits(size_t number_of_location_catalog_entries) {
    620     // Handle the case of 0, as we cannot pass 0 to art::WhichPowerOf2.
    621     return number_of_location_catalog_entries == 0
    622         ? 0u
    623         : WhichPowerOf2(RoundUpToPowerOfTwo(number_of_location_catalog_entries));
    624   }
    625 
    626   // Return the size of the DexRegisterMap object, in bytes.
    627   size_t Size() const {
    628     return region_.size();
    629   }
    630 
    631   void Dump(VariableIndentationOutputStream* vios,
    632             const CodeInfo& code_info, uint16_t number_of_dex_registers) const;
    633 
    634  private:
    635   // Return the index in the Dex register map corresponding to the Dex
    636   // register number `dex_register_number`.
    637   size_t GetIndexInDexRegisterMap(uint16_t dex_register_number) const {
    638     if (!IsDexRegisterLive(dex_register_number)) {
    639       return kInvalidIndexInDexRegisterMap;
    640     }
    641     return GetNumberOfLiveDexRegisters(dex_register_number);
    642   }
    643 
    644   // Special (invalid) Dex register map entry index meaning that there
    645   // is no index in the map for a given Dex register (i.e., it must
    646   // have been mapped to a DexRegisterLocation::Kind::kNone location).
    647   static constexpr size_t kInvalidIndexInDexRegisterMap = -1;
    648 
    649   static constexpr int kFixedSize = 0;
    650 
    651   MemoryRegion region_;
    652 
    653   friend class CodeInfo;
    654   friend class StackMapStream;
    655 };
    656 
    657 // Represents bit range of bit-packed integer field.
    658 // We reuse the idea from ULEB128p1 to support encoding of -1 (aka 0xFFFFFFFF).
    659 // If min_value is set to -1, we implicitly subtract one from any loaded value,
    660 // and add one to any stored value. This is generalized to any negative values.
    661 // In other words, min_value acts as a base and the stored value is added to it.
    662 struct FieldEncoding {
    663   FieldEncoding(size_t start_offset, size_t end_offset, int32_t min_value = 0)
    664       : start_offset_(start_offset), end_offset_(end_offset), min_value_(min_value) {
    665     DCHECK_LE(start_offset_, end_offset_);
    666     DCHECK_LE(BitSize(), 32u);
    667   }
    668 
    669   ALWAYS_INLINE size_t BitSize() const { return end_offset_ - start_offset_; }
    670 
    671   template <typename Region>
    672   ALWAYS_INLINE int32_t Load(const Region& region) const {
    673     DCHECK_LE(end_offset_, region.size_in_bits());
    674     return static_cast<int32_t>(region.LoadBits(start_offset_, BitSize())) + min_value_;
    675   }
    676 
    677   template <typename Region>
    678   ALWAYS_INLINE void Store(Region region, int32_t value) const {
    679     region.StoreBits(start_offset_, value - min_value_, BitSize());
    680     DCHECK_EQ(Load(region), value);
    681   }
    682 
    683  private:
    684   size_t start_offset_;
    685   size_t end_offset_;
    686   int32_t min_value_;
    687 };
    688 
    689 class StackMapEncoding {
    690  public:
    691   StackMapEncoding()
    692       : dex_pc_bit_offset_(0),
    693         dex_register_map_bit_offset_(0),
    694         inline_info_bit_offset_(0),
    695         register_mask_index_bit_offset_(0),
    696         stack_mask_index_bit_offset_(0),
    697         total_bit_size_(0) {}
    698 
    699   // Set stack map bit layout based on given sizes.
    700   // Returns the size of stack map in bits.
    701   size_t SetFromSizes(size_t native_pc_max,
    702                       size_t dex_pc_max,
    703                       size_t dex_register_map_size,
    704                       size_t number_of_inline_info,
    705                       size_t number_of_register_masks,
    706                       size_t number_of_stack_masks) {
    707     total_bit_size_ = 0;
    708     DCHECK_EQ(kNativePcBitOffset, total_bit_size_);
    709     total_bit_size_ += MinimumBitsToStore(native_pc_max);
    710 
    711     dex_pc_bit_offset_ = total_bit_size_;
    712     total_bit_size_ += MinimumBitsToStore(1 /* kNoDexPc */ + dex_pc_max);
    713 
    714     // We also need +1 for kNoDexRegisterMap, but since the size is strictly
    715     // greater than any offset we might try to encode, we already implicitly have it.
    716     dex_register_map_bit_offset_ = total_bit_size_;
    717     total_bit_size_ += MinimumBitsToStore(dex_register_map_size);
    718 
    719     // We also need +1 for kNoInlineInfo, but since the inline_info_size is strictly
    720     // greater than the offset we might try to encode, we already implicitly have it.
    721     // If inline_info_size is zero, we can encode only kNoInlineInfo (in zero bits).
    722     inline_info_bit_offset_ = total_bit_size_;
    723     total_bit_size_ += MinimumBitsToStore(number_of_inline_info);
    724 
    725     register_mask_index_bit_offset_ = total_bit_size_;
    726     total_bit_size_ += MinimumBitsToStore(number_of_register_masks);
    727 
    728     stack_mask_index_bit_offset_ = total_bit_size_;
    729     total_bit_size_ += MinimumBitsToStore(number_of_stack_masks);
    730 
    731     return total_bit_size_;
    732   }
    733 
    734   ALWAYS_INLINE FieldEncoding GetNativePcEncoding() const {
    735     return FieldEncoding(kNativePcBitOffset, dex_pc_bit_offset_);
    736   }
    737   ALWAYS_INLINE FieldEncoding GetDexPcEncoding() const {
    738     return FieldEncoding(dex_pc_bit_offset_, dex_register_map_bit_offset_, -1 /* min_value */);
    739   }
    740   ALWAYS_INLINE FieldEncoding GetDexRegisterMapEncoding() const {
    741     return FieldEncoding(dex_register_map_bit_offset_, inline_info_bit_offset_, -1 /* min_value */);
    742   }
    743   ALWAYS_INLINE FieldEncoding GetInlineInfoEncoding() const {
    744     return FieldEncoding(inline_info_bit_offset_,
    745                          register_mask_index_bit_offset_,
    746                          -1 /* min_value */);
    747   }
    748   ALWAYS_INLINE FieldEncoding GetRegisterMaskIndexEncoding() const {
    749     return FieldEncoding(register_mask_index_bit_offset_, stack_mask_index_bit_offset_);
    750   }
    751   ALWAYS_INLINE FieldEncoding GetStackMaskIndexEncoding() const {
    752     return FieldEncoding(stack_mask_index_bit_offset_, total_bit_size_);
    753   }
    754   ALWAYS_INLINE size_t BitSize() const {
    755     return total_bit_size_;
    756   }
    757 
    758   // Encode the encoding into the vector.
    759   template<typename Vector>
    760   void Encode(Vector* dest) const {
    761     static_assert(alignof(StackMapEncoding) == 1, "Should not require alignment");
    762     const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
    763     dest->insert(dest->end(), ptr, ptr + sizeof(*this));
    764   }
    765 
    766   // Decode the encoding from a pointer, updates the pointer.
    767   void Decode(const uint8_t** ptr) {
    768     *this = *reinterpret_cast<const StackMapEncoding*>(*ptr);
    769     *ptr += sizeof(*this);
    770   }
    771 
    772   void Dump(VariableIndentationOutputStream* vios) const;
    773 
    774  private:
    775   static constexpr size_t kNativePcBitOffset = 0;
    776   uint8_t dex_pc_bit_offset_;
    777   uint8_t dex_register_map_bit_offset_;
    778   uint8_t inline_info_bit_offset_;
    779   uint8_t register_mask_index_bit_offset_;
    780   uint8_t stack_mask_index_bit_offset_;
    781   uint8_t total_bit_size_;
    782 };
    783 
    784 /**
    785  * A Stack Map holds compilation information for a specific PC necessary for:
    786  * - Mapping it to a dex PC,
    787  * - Knowing which stack entries are objects,
    788  * - Knowing which registers hold objects,
    789  * - Knowing the inlining information,
    790  * - Knowing the values of dex registers.
    791  *
    792  * The information is of the form:
    793  *
    794  *   [native_pc_offset, dex_pc, dex_register_map_offset, inlining_info_index, register_mask_index,
    795  *   stack_mask_index].
    796  */
    797 class StackMap {
    798  public:
    799   StackMap() {}
    800   explicit StackMap(BitMemoryRegion region) : region_(region) {}
    801 
    802   ALWAYS_INLINE bool IsValid() const { return region_.pointer() != nullptr; }
    803 
    804   ALWAYS_INLINE uint32_t GetDexPc(const StackMapEncoding& encoding) const {
    805     return encoding.GetDexPcEncoding().Load(region_);
    806   }
    807 
    808   ALWAYS_INLINE void SetDexPc(const StackMapEncoding& encoding, uint32_t dex_pc) {
    809     encoding.GetDexPcEncoding().Store(region_, dex_pc);
    810   }
    811 
    812   ALWAYS_INLINE uint32_t GetNativePcOffset(const StackMapEncoding& encoding,
    813                                            InstructionSet instruction_set) const {
    814     CodeOffset offset(
    815         CodeOffset::FromCompressedOffset(encoding.GetNativePcEncoding().Load(region_)));
    816     return offset.Uint32Value(instruction_set);
    817   }
    818 
    819   ALWAYS_INLINE void SetNativePcCodeOffset(const StackMapEncoding& encoding,
    820                                            CodeOffset native_pc_offset) {
    821     encoding.GetNativePcEncoding().Store(region_, native_pc_offset.CompressedValue());
    822   }
    823 
    824   ALWAYS_INLINE uint32_t GetDexRegisterMapOffset(const StackMapEncoding& encoding) const {
    825     return encoding.GetDexRegisterMapEncoding().Load(region_);
    826   }
    827 
    828   ALWAYS_INLINE void SetDexRegisterMapOffset(const StackMapEncoding& encoding, uint32_t offset) {
    829     encoding.GetDexRegisterMapEncoding().Store(region_, offset);
    830   }
    831 
    832   ALWAYS_INLINE uint32_t GetInlineInfoIndex(const StackMapEncoding& encoding) const {
    833     return encoding.GetInlineInfoEncoding().Load(region_);
    834   }
    835 
    836   ALWAYS_INLINE void SetInlineInfoIndex(const StackMapEncoding& encoding, uint32_t index) {
    837     encoding.GetInlineInfoEncoding().Store(region_, index);
    838   }
    839 
    840   ALWAYS_INLINE uint32_t GetRegisterMaskIndex(const StackMapEncoding& encoding) const {
    841     return encoding.GetRegisterMaskIndexEncoding().Load(region_);
    842   }
    843 
    844   ALWAYS_INLINE void SetRegisterMaskIndex(const StackMapEncoding& encoding, uint32_t mask) {
    845     encoding.GetRegisterMaskIndexEncoding().Store(region_, mask);
    846   }
    847 
    848   ALWAYS_INLINE uint32_t GetStackMaskIndex(const StackMapEncoding& encoding) const {
    849     return encoding.GetStackMaskIndexEncoding().Load(region_);
    850   }
    851 
    852   ALWAYS_INLINE void SetStackMaskIndex(const StackMapEncoding& encoding, uint32_t mask) {
    853     encoding.GetStackMaskIndexEncoding().Store(region_, mask);
    854   }
    855 
    856   ALWAYS_INLINE bool HasDexRegisterMap(const StackMapEncoding& encoding) const {
    857     return GetDexRegisterMapOffset(encoding) != kNoDexRegisterMap;
    858   }
    859 
    860   ALWAYS_INLINE bool HasInlineInfo(const StackMapEncoding& encoding) const {
    861     return GetInlineInfoIndex(encoding) != kNoInlineInfo;
    862   }
    863 
    864   ALWAYS_INLINE bool Equals(const StackMap& other) const {
    865     return region_.pointer() == other.region_.pointer() &&
    866            region_.size() == other.region_.size() &&
    867            region_.BitOffset() == other.region_.BitOffset();
    868   }
    869 
    870   void Dump(VariableIndentationOutputStream* vios,
    871             const CodeInfo& code_info,
    872             const CodeInfoEncoding& encoding,
    873             const MethodInfo& method_info,
    874             uint32_t code_offset,
    875             uint16_t number_of_dex_registers,
    876             InstructionSet instruction_set,
    877             const std::string& header_suffix = "") const;
    878 
    879   // Special (invalid) offset for the DexRegisterMapOffset field meaning
    880   // that there is no Dex register map for this stack map.
    881   static constexpr uint32_t kNoDexRegisterMap = -1;
    882 
    883   // Special (invalid) offset for the InlineDescriptorOffset field meaning
    884   // that there is no inline info for this stack map.
    885   static constexpr uint32_t kNoInlineInfo = -1;
    886 
    887  private:
    888   static constexpr int kFixedSize = 0;
    889 
    890   BitMemoryRegion region_;
    891 
    892   friend class StackMapStream;
    893 };
    894 
    895 class InlineInfoEncoding {
    896  public:
    897   void SetFromSizes(size_t method_index_idx_max,
    898                     size_t dex_pc_max,
    899                     size_t extra_data_max,
    900                     size_t dex_register_map_size) {
    901     total_bit_size_ = kMethodIndexBitOffset;
    902     total_bit_size_ += MinimumBitsToStore(method_index_idx_max);
    903 
    904     dex_pc_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
    905     // Note: We're not encoding the dex pc if there is none. That's the case
    906     // for an intrinsified native method, such as String.charAt().
    907     if (dex_pc_max != DexFile::kDexNoIndex) {
    908       total_bit_size_ += MinimumBitsToStore(1 /* kNoDexPc */ + dex_pc_max);
    909     }
    910 
    911     extra_data_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
    912     total_bit_size_ += MinimumBitsToStore(extra_data_max);
    913 
    914     // We also need +1 for kNoDexRegisterMap, but since the size is strictly
    915     // greater than any offset we might try to encode, we already implicitly have it.
    916     dex_register_map_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_);
    917     total_bit_size_ += MinimumBitsToStore(dex_register_map_size);
    918   }
    919 
    920   ALWAYS_INLINE FieldEncoding GetMethodIndexIdxEncoding() const {
    921     return FieldEncoding(kMethodIndexBitOffset, dex_pc_bit_offset_);
    922   }
    923   ALWAYS_INLINE FieldEncoding GetDexPcEncoding() const {
    924     return FieldEncoding(dex_pc_bit_offset_, extra_data_bit_offset_, -1 /* min_value */);
    925   }
    926   ALWAYS_INLINE FieldEncoding GetExtraDataEncoding() const {
    927     return FieldEncoding(extra_data_bit_offset_, dex_register_map_bit_offset_);
    928   }
    929   ALWAYS_INLINE FieldEncoding GetDexRegisterMapEncoding() const {
    930     return FieldEncoding(dex_register_map_bit_offset_, total_bit_size_, -1 /* min_value */);
    931   }
    932   ALWAYS_INLINE size_t BitSize() const {
    933     return total_bit_size_;
    934   }
    935 
    936   void Dump(VariableIndentationOutputStream* vios) const;
    937 
    938   // Encode the encoding into the vector.
    939   template<typename Vector>
    940   void Encode(Vector* dest) const {
    941     static_assert(alignof(InlineInfoEncoding) == 1, "Should not require alignment");
    942     const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
    943     dest->insert(dest->end(), ptr, ptr + sizeof(*this));
    944   }
    945 
    946   // Decode the encoding from a pointer, updates the pointer.
    947   void Decode(const uint8_t** ptr) {
    948     *this = *reinterpret_cast<const InlineInfoEncoding*>(*ptr);
    949     *ptr += sizeof(*this);
    950   }
    951 
    952  private:
    953   static constexpr uint8_t kIsLastBitOffset = 0;
    954   static constexpr uint8_t kMethodIndexBitOffset = 1;
    955   uint8_t dex_pc_bit_offset_;
    956   uint8_t extra_data_bit_offset_;
    957   uint8_t dex_register_map_bit_offset_;
    958   uint8_t total_bit_size_;
    959 };
    960 
    961 /**
    962  * Inline information for a specific PC. The information is of the form:
    963  *
    964  *   [is_last,
    965  *    method_index (or ArtMethod high bits),
    966  *    dex_pc,
    967  *    extra_data (ArtMethod low bits or 1),
    968  *    dex_register_map_offset]+.
    969  */
    970 class InlineInfo {
    971  public:
    972   explicit InlineInfo(BitMemoryRegion region) : region_(region) {}
    973 
    974   ALWAYS_INLINE uint32_t GetDepth(const InlineInfoEncoding& encoding) const {
    975     size_t depth = 0;
    976     while (!GetRegionAtDepth(encoding, depth++).LoadBit(0)) { }  // Check is_last bit.
    977     return depth;
    978   }
    979 
    980   ALWAYS_INLINE void SetDepth(const InlineInfoEncoding& encoding, uint32_t depth) {
    981     DCHECK_GT(depth, 0u);
    982     for (size_t d = 0; d < depth; ++d) {
    983       GetRegionAtDepth(encoding, d).StoreBit(0, d == depth - 1);  // Set is_last bit.
    984     }
    985   }
    986 
    987   ALWAYS_INLINE uint32_t GetMethodIndexIdxAtDepth(const InlineInfoEncoding& encoding,
    988                                                   uint32_t depth) const {
    989     DCHECK(!EncodesArtMethodAtDepth(encoding, depth));
    990     return encoding.GetMethodIndexIdxEncoding().Load(GetRegionAtDepth(encoding, depth));
    991   }
    992 
    993   ALWAYS_INLINE void SetMethodIndexIdxAtDepth(const InlineInfoEncoding& encoding,
    994                                               uint32_t depth,
    995                                               uint32_t index) {
    996     encoding.GetMethodIndexIdxEncoding().Store(GetRegionAtDepth(encoding, depth), index);
    997   }
    998 
    999 
   1000   ALWAYS_INLINE uint32_t GetMethodIndexAtDepth(const InlineInfoEncoding& encoding,
   1001                                                const MethodInfo& method_info,
   1002                                                uint32_t depth) const {
   1003     return method_info.GetMethodIndex(GetMethodIndexIdxAtDepth(encoding, depth));
   1004   }
   1005 
   1006   ALWAYS_INLINE uint32_t GetDexPcAtDepth(const InlineInfoEncoding& encoding,
   1007                                          uint32_t depth) const {
   1008     return encoding.GetDexPcEncoding().Load(GetRegionAtDepth(encoding, depth));
   1009   }
   1010 
   1011   ALWAYS_INLINE void SetDexPcAtDepth(const InlineInfoEncoding& encoding,
   1012                                      uint32_t depth,
   1013                                      uint32_t dex_pc) {
   1014     encoding.GetDexPcEncoding().Store(GetRegionAtDepth(encoding, depth), dex_pc);
   1015   }
   1016 
   1017   ALWAYS_INLINE bool EncodesArtMethodAtDepth(const InlineInfoEncoding& encoding,
   1018                                              uint32_t depth) const {
   1019     return (encoding.GetExtraDataEncoding().Load(GetRegionAtDepth(encoding, depth)) & 1) == 0;
   1020   }
   1021 
   1022   ALWAYS_INLINE void SetExtraDataAtDepth(const InlineInfoEncoding& encoding,
   1023                                          uint32_t depth,
   1024                                          uint32_t extra_data) {
   1025     encoding.GetExtraDataEncoding().Store(GetRegionAtDepth(encoding, depth), extra_data);
   1026   }
   1027 
   1028   ALWAYS_INLINE ArtMethod* GetArtMethodAtDepth(const InlineInfoEncoding& encoding,
   1029                                                uint32_t depth) const {
   1030     uint32_t low_bits = encoding.GetExtraDataEncoding().Load(GetRegionAtDepth(encoding, depth));
   1031     uint32_t high_bits = encoding.GetMethodIndexIdxEncoding().Load(
   1032         GetRegionAtDepth(encoding, depth));
   1033     if (high_bits == 0) {
   1034       return reinterpret_cast<ArtMethod*>(low_bits);
   1035     } else {
   1036       uint64_t address = high_bits;
   1037       address = address << 32;
   1038       return reinterpret_cast<ArtMethod*>(address | low_bits);
   1039     }
   1040   }
   1041 
   1042   ALWAYS_INLINE uint32_t GetDexRegisterMapOffsetAtDepth(const InlineInfoEncoding& encoding,
   1043                                                         uint32_t depth) const {
   1044     return encoding.GetDexRegisterMapEncoding().Load(GetRegionAtDepth(encoding, depth));
   1045   }
   1046 
   1047   ALWAYS_INLINE void SetDexRegisterMapOffsetAtDepth(const InlineInfoEncoding& encoding,
   1048                                                     uint32_t depth,
   1049                                                     uint32_t offset) {
   1050     encoding.GetDexRegisterMapEncoding().Store(GetRegionAtDepth(encoding, depth), offset);
   1051   }
   1052 
   1053   ALWAYS_INLINE bool HasDexRegisterMapAtDepth(const InlineInfoEncoding& encoding,
   1054                                               uint32_t depth) const {
   1055     return GetDexRegisterMapOffsetAtDepth(encoding, depth) != StackMap::kNoDexRegisterMap;
   1056   }
   1057 
   1058   void Dump(VariableIndentationOutputStream* vios,
   1059             const CodeInfo& info,
   1060             const MethodInfo& method_info,
   1061             uint16_t* number_of_dex_registers) const;
   1062 
   1063  private:
   1064   ALWAYS_INLINE BitMemoryRegion GetRegionAtDepth(const InlineInfoEncoding& encoding,
   1065                                                  uint32_t depth) const {
   1066     size_t entry_size = encoding.BitSize();
   1067     DCHECK_GT(entry_size, 0u);
   1068     return region_.Subregion(depth * entry_size, entry_size);
   1069   }
   1070 
   1071   BitMemoryRegion region_;
   1072 };
   1073 
   1074 // Bit sized region encoding, may be more than 255 bits.
   1075 class BitRegionEncoding {
   1076  public:
   1077   uint32_t num_bits = 0;
   1078 
   1079   ALWAYS_INLINE size_t BitSize() const {
   1080     return num_bits;
   1081   }
   1082 
   1083   template<typename Vector>
   1084   void Encode(Vector* dest) const {
   1085     EncodeUnsignedLeb128(dest, num_bits);  // Use leb in case num_bits is greater than 255.
   1086   }
   1087 
   1088   void Decode(const uint8_t** ptr) {
   1089     num_bits = DecodeUnsignedLeb128(ptr);
   1090   }
   1091 };
   1092 
   1093 // A table of bit sized encodings.
   1094 template <typename Encoding>
   1095 struct BitEncodingTable {
   1096   static constexpr size_t kInvalidOffset = static_cast<size_t>(-1);
   1097   // How the encoding is laid out (serialized).
   1098   Encoding encoding;
   1099 
   1100   // Number of entries in the table (serialized).
   1101   size_t num_entries;
   1102 
   1103   // Bit offset for the base of the table (computed).
   1104   size_t bit_offset = kInvalidOffset;
   1105 
   1106   template<typename Vector>
   1107   void Encode(Vector* dest) const {
   1108     EncodeUnsignedLeb128(dest, num_entries);
   1109     encoding.Encode(dest);
   1110   }
   1111 
   1112   ALWAYS_INLINE void Decode(const uint8_t** ptr) {
   1113     num_entries = DecodeUnsignedLeb128(ptr);
   1114     encoding.Decode(ptr);
   1115   }
   1116 
   1117   // Set the bit offset in the table and adds the space used by the table to offset.
   1118   void UpdateBitOffset(size_t* offset) {
   1119     DCHECK(offset != nullptr);
   1120     bit_offset = *offset;
   1121     *offset += encoding.BitSize() * num_entries;
   1122   }
   1123 
   1124   // Return the bit region for the map at index i.
   1125   ALWAYS_INLINE BitMemoryRegion BitRegion(MemoryRegion region, size_t index) const {
   1126     DCHECK_NE(bit_offset, kInvalidOffset) << "Invalid table offset";
   1127     DCHECK_LT(index, num_entries);
   1128     const size_t map_size = encoding.BitSize();
   1129     return BitMemoryRegion(region, bit_offset + index * map_size, map_size);
   1130   }
   1131 };
   1132 
   1133 // A byte sized table of possible variable sized encodings.
   1134 struct ByteSizedTable {
   1135   static constexpr size_t kInvalidOffset = static_cast<size_t>(-1);
   1136 
   1137   // Number of entries in the table (serialized).
   1138   size_t num_entries = 0;
   1139 
   1140   // Number of bytes of the table (serialized).
   1141   size_t num_bytes;
   1142 
   1143   // Bit offset for the base of the table (computed).
   1144   size_t byte_offset = kInvalidOffset;
   1145 
   1146   template<typename Vector>
   1147   void Encode(Vector* dest) const {
   1148     EncodeUnsignedLeb128(dest, num_entries);
   1149     EncodeUnsignedLeb128(dest, num_bytes);
   1150   }
   1151 
   1152   ALWAYS_INLINE void Decode(const uint8_t** ptr) {
   1153     num_entries = DecodeUnsignedLeb128(ptr);
   1154     num_bytes = DecodeUnsignedLeb128(ptr);
   1155   }
   1156 
   1157   // Set the bit offset of the table. Adds the total bit size of the table to offset.
   1158   void UpdateBitOffset(size_t* offset) {
   1159     DCHECK(offset != nullptr);
   1160     DCHECK_ALIGNED(*offset, kBitsPerByte);
   1161     byte_offset = *offset / kBitsPerByte;
   1162     *offset += num_bytes * kBitsPerByte;
   1163   }
   1164 };
   1165 
   1166 // Format is [native pc, invoke type, method index].
   1167 class InvokeInfoEncoding {
   1168  public:
   1169   void SetFromSizes(size_t native_pc_max,
   1170                     size_t invoke_type_max,
   1171                     size_t method_index_max) {
   1172     total_bit_size_ = 0;
   1173     DCHECK_EQ(kNativePcBitOffset, total_bit_size_);
   1174     total_bit_size_ += MinimumBitsToStore(native_pc_max);
   1175     invoke_type_bit_offset_ = total_bit_size_;
   1176     total_bit_size_ += MinimumBitsToStore(invoke_type_max);
   1177     method_index_bit_offset_ = total_bit_size_;
   1178     total_bit_size_ += MinimumBitsToStore(method_index_max);
   1179   }
   1180 
   1181   ALWAYS_INLINE FieldEncoding GetNativePcEncoding() const {
   1182     return FieldEncoding(kNativePcBitOffset, invoke_type_bit_offset_);
   1183   }
   1184 
   1185   ALWAYS_INLINE FieldEncoding GetInvokeTypeEncoding() const {
   1186     return FieldEncoding(invoke_type_bit_offset_, method_index_bit_offset_);
   1187   }
   1188 
   1189   ALWAYS_INLINE FieldEncoding GetMethodIndexEncoding() const {
   1190     return FieldEncoding(method_index_bit_offset_, total_bit_size_);
   1191   }
   1192 
   1193   ALWAYS_INLINE size_t BitSize() const {
   1194     return total_bit_size_;
   1195   }
   1196 
   1197   template<typename Vector>
   1198   void Encode(Vector* dest) const {
   1199     static_assert(alignof(InvokeInfoEncoding) == 1, "Should not require alignment");
   1200     const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
   1201     dest->insert(dest->end(), ptr, ptr + sizeof(*this));
   1202   }
   1203 
   1204   void Decode(const uint8_t** ptr) {
   1205     *this = *reinterpret_cast<const InvokeInfoEncoding*>(*ptr);
   1206     *ptr += sizeof(*this);
   1207   }
   1208 
   1209  private:
   1210   static constexpr uint8_t kNativePcBitOffset = 0;
   1211   uint8_t invoke_type_bit_offset_;
   1212   uint8_t method_index_bit_offset_;
   1213   uint8_t total_bit_size_;
   1214 };
   1215 
   1216 class InvokeInfo {
   1217  public:
   1218   explicit InvokeInfo(BitMemoryRegion region) : region_(region) {}
   1219 
   1220   ALWAYS_INLINE uint32_t GetNativePcOffset(const InvokeInfoEncoding& encoding,
   1221                                            InstructionSet instruction_set) const {
   1222     CodeOffset offset(
   1223         CodeOffset::FromCompressedOffset(encoding.GetNativePcEncoding().Load(region_)));
   1224     return offset.Uint32Value(instruction_set);
   1225   }
   1226 
   1227   ALWAYS_INLINE void SetNativePcCodeOffset(const InvokeInfoEncoding& encoding,
   1228                                            CodeOffset native_pc_offset) {
   1229     encoding.GetNativePcEncoding().Store(region_, native_pc_offset.CompressedValue());
   1230   }
   1231 
   1232   ALWAYS_INLINE uint32_t GetInvokeType(const InvokeInfoEncoding& encoding) const {
   1233     return encoding.GetInvokeTypeEncoding().Load(region_);
   1234   }
   1235 
   1236   ALWAYS_INLINE void SetInvokeType(const InvokeInfoEncoding& encoding, uint32_t invoke_type) {
   1237     encoding.GetInvokeTypeEncoding().Store(region_, invoke_type);
   1238   }
   1239 
   1240   ALWAYS_INLINE uint32_t GetMethodIndexIdx(const InvokeInfoEncoding& encoding) const {
   1241     return encoding.GetMethodIndexEncoding().Load(region_);
   1242   }
   1243 
   1244   ALWAYS_INLINE void SetMethodIndexIdx(const InvokeInfoEncoding& encoding,
   1245                                        uint32_t method_index_idx) {
   1246     encoding.GetMethodIndexEncoding().Store(region_, method_index_idx);
   1247   }
   1248 
   1249   ALWAYS_INLINE uint32_t GetMethodIndex(const InvokeInfoEncoding& encoding,
   1250                                         MethodInfo method_info) const {
   1251     return method_info.GetMethodIndex(GetMethodIndexIdx(encoding));
   1252   }
   1253 
   1254   bool IsValid() const { return region_.pointer() != nullptr; }
   1255 
   1256  private:
   1257   BitMemoryRegion region_;
   1258 };
   1259 
   1260 // Most of the fields are encoded as ULEB128 to save space.
   1261 struct CodeInfoEncoding {
   1262   static constexpr uint32_t kInvalidSize = static_cast<size_t>(-1);
   1263   // Byte sized tables go first to avoid unnecessary alignment bits.
   1264   ByteSizedTable dex_register_map;
   1265   ByteSizedTable location_catalog;
   1266   BitEncodingTable<StackMapEncoding> stack_map;
   1267   BitEncodingTable<BitRegionEncoding> register_mask;
   1268   BitEncodingTable<BitRegionEncoding> stack_mask;
   1269   BitEncodingTable<InvokeInfoEncoding> invoke_info;
   1270   BitEncodingTable<InlineInfoEncoding> inline_info;
   1271 
   1272   CodeInfoEncoding() {}
   1273 
   1274   explicit CodeInfoEncoding(const void* data) {
   1275     const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
   1276     dex_register_map.Decode(&ptr);
   1277     location_catalog.Decode(&ptr);
   1278     stack_map.Decode(&ptr);
   1279     register_mask.Decode(&ptr);
   1280     stack_mask.Decode(&ptr);
   1281     invoke_info.Decode(&ptr);
   1282     if (stack_map.encoding.GetInlineInfoEncoding().BitSize() > 0) {
   1283       inline_info.Decode(&ptr);
   1284     } else {
   1285       inline_info = BitEncodingTable<InlineInfoEncoding>();
   1286     }
   1287     cache_header_size =
   1288         dchecked_integral_cast<uint32_t>(ptr - reinterpret_cast<const uint8_t*>(data));
   1289     ComputeTableOffsets();
   1290   }
   1291 
   1292   // Compress is not const since it calculates cache_header_size. This is used by PrepareForFillIn.
   1293   template<typename Vector>
   1294   void Compress(Vector* dest) {
   1295     dex_register_map.Encode(dest);
   1296     location_catalog.Encode(dest);
   1297     stack_map.Encode(dest);
   1298     register_mask.Encode(dest);
   1299     stack_mask.Encode(dest);
   1300     invoke_info.Encode(dest);
   1301     if (stack_map.encoding.GetInlineInfoEncoding().BitSize() > 0) {
   1302       inline_info.Encode(dest);
   1303     }
   1304     cache_header_size = dest->size();
   1305   }
   1306 
   1307   ALWAYS_INLINE void ComputeTableOffsets() {
   1308     // Skip the header.
   1309     size_t bit_offset = HeaderSize() * kBitsPerByte;
   1310     // The byte tables must be aligned so they must go first.
   1311     dex_register_map.UpdateBitOffset(&bit_offset);
   1312     location_catalog.UpdateBitOffset(&bit_offset);
   1313     // Other tables don't require alignment.
   1314     stack_map.UpdateBitOffset(&bit_offset);
   1315     register_mask.UpdateBitOffset(&bit_offset);
   1316     stack_mask.UpdateBitOffset(&bit_offset);
   1317     invoke_info.UpdateBitOffset(&bit_offset);
   1318     inline_info.UpdateBitOffset(&bit_offset);
   1319     cache_non_header_size = RoundUp(bit_offset, kBitsPerByte) / kBitsPerByte - HeaderSize();
   1320   }
   1321 
   1322   ALWAYS_INLINE size_t HeaderSize() const {
   1323     DCHECK_NE(cache_header_size, kInvalidSize) << "Uninitialized";
   1324     return cache_header_size;
   1325   }
   1326 
   1327   ALWAYS_INLINE size_t NonHeaderSize() const {
   1328     DCHECK_NE(cache_non_header_size, kInvalidSize) << "Uninitialized";
   1329     return cache_non_header_size;
   1330   }
   1331 
   1332  private:
   1333   // Computed fields (not serialized).
   1334   // Header size in bytes, cached to avoid needing to re-decoding the encoding in HeaderSize.
   1335   uint32_t cache_header_size = kInvalidSize;
   1336   // Non header size in bytes, cached to avoid needing to re-decoding the encoding in NonHeaderSize.
   1337   uint32_t cache_non_header_size = kInvalidSize;
   1338 };
   1339 
   1340 /**
   1341  * Wrapper around all compiler information collected for a method.
   1342  * The information is of the form:
   1343  *
   1344  *   [CodeInfoEncoding, DexRegisterMap+, DexLocationCatalog+, StackMap+, RegisterMask+, StackMask+,
   1345  *    InlineInfo*]
   1346  *
   1347  * where CodeInfoEncoding is of the form:
   1348  *
   1349  *   [ByteSizedTable(dex_register_map), ByteSizedTable(location_catalog),
   1350  *    BitEncodingTable<StackMapEncoding>, BitEncodingTable<BitRegionEncoding>,
   1351  *    BitEncodingTable<BitRegionEncoding>, BitEncodingTable<InlineInfoEncoding>]
   1352  */
   1353 class CodeInfo {
   1354  public:
   1355   explicit CodeInfo(MemoryRegion region) : region_(region) {
   1356   }
   1357 
   1358   explicit CodeInfo(const void* data) {
   1359     CodeInfoEncoding encoding = CodeInfoEncoding(data);
   1360     region_ = MemoryRegion(const_cast<void*>(data),
   1361                            encoding.HeaderSize() + encoding.NonHeaderSize());
   1362   }
   1363 
   1364   CodeInfoEncoding ExtractEncoding() const {
   1365     CodeInfoEncoding encoding(region_.begin());
   1366     AssertValidStackMap(encoding);
   1367     return encoding;
   1368   }
   1369 
   1370   bool HasInlineInfo(const CodeInfoEncoding& encoding) const {
   1371     return encoding.stack_map.encoding.GetInlineInfoEncoding().BitSize() > 0;
   1372   }
   1373 
   1374   DexRegisterLocationCatalog GetDexRegisterLocationCatalog(const CodeInfoEncoding& encoding) const {
   1375     return DexRegisterLocationCatalog(region_.Subregion(encoding.location_catalog.byte_offset,
   1376                                                         encoding.location_catalog.num_bytes));
   1377   }
   1378 
   1379   ALWAYS_INLINE size_t GetNumberOfStackMaskBits(const CodeInfoEncoding& encoding) const {
   1380     return encoding.stack_mask.encoding.BitSize();
   1381   }
   1382 
   1383   ALWAYS_INLINE StackMap GetStackMapAt(size_t index, const CodeInfoEncoding& encoding) const {
   1384     return StackMap(encoding.stack_map.BitRegion(region_, index));
   1385   }
   1386 
   1387   BitMemoryRegion GetStackMask(size_t index, const CodeInfoEncoding& encoding) const {
   1388     return encoding.stack_mask.BitRegion(region_, index);
   1389   }
   1390 
   1391   BitMemoryRegion GetStackMaskOf(const CodeInfoEncoding& encoding,
   1392                                  const StackMap& stack_map) const {
   1393     return GetStackMask(stack_map.GetStackMaskIndex(encoding.stack_map.encoding), encoding);
   1394   }
   1395 
   1396   BitMemoryRegion GetRegisterMask(size_t index, const CodeInfoEncoding& encoding) const {
   1397     return encoding.register_mask.BitRegion(region_, index);
   1398   }
   1399 
   1400   uint32_t GetRegisterMaskOf(const CodeInfoEncoding& encoding, const StackMap& stack_map) const {
   1401     size_t index = stack_map.GetRegisterMaskIndex(encoding.stack_map.encoding);
   1402     return GetRegisterMask(index, encoding).LoadBits(0u, encoding.register_mask.encoding.BitSize());
   1403   }
   1404 
   1405   uint32_t GetNumberOfLocationCatalogEntries(const CodeInfoEncoding& encoding) const {
   1406     return encoding.location_catalog.num_entries;
   1407   }
   1408 
   1409   uint32_t GetDexRegisterLocationCatalogSize(const CodeInfoEncoding& encoding) const {
   1410     return encoding.location_catalog.num_bytes;
   1411   }
   1412 
   1413   uint32_t GetNumberOfStackMaps(const CodeInfoEncoding& encoding) const {
   1414     return encoding.stack_map.num_entries;
   1415   }
   1416 
   1417   // Get the size of all the stack maps of this CodeInfo object, in bits. Not byte aligned.
   1418   ALWAYS_INLINE size_t GetStackMapsSizeInBits(const CodeInfoEncoding& encoding) const {
   1419     return encoding.stack_map.encoding.BitSize() * GetNumberOfStackMaps(encoding);
   1420   }
   1421 
   1422   InvokeInfo GetInvokeInfo(const CodeInfoEncoding& encoding, size_t index) const {
   1423     return InvokeInfo(encoding.invoke_info.BitRegion(region_, index));
   1424   }
   1425 
   1426   DexRegisterMap GetDexRegisterMapOf(StackMap stack_map,
   1427                                      const CodeInfoEncoding& encoding,
   1428                                      size_t number_of_dex_registers) const {
   1429     if (!stack_map.HasDexRegisterMap(encoding.stack_map.encoding)) {
   1430       return DexRegisterMap();
   1431     }
   1432     const uint32_t offset = encoding.dex_register_map.byte_offset +
   1433         stack_map.GetDexRegisterMapOffset(encoding.stack_map.encoding);
   1434     size_t size = ComputeDexRegisterMapSizeOf(encoding, offset, number_of_dex_registers);
   1435     return DexRegisterMap(region_.Subregion(offset, size));
   1436   }
   1437 
   1438   size_t GetDexRegisterMapsSize(const CodeInfoEncoding& encoding,
   1439                                 uint32_t number_of_dex_registers) const {
   1440     size_t total = 0;
   1441     for (size_t i = 0, e = GetNumberOfStackMaps(encoding); i < e; ++i) {
   1442       StackMap stack_map = GetStackMapAt(i, encoding);
   1443       DexRegisterMap map(GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers));
   1444       total += map.Size();
   1445     }
   1446     return total;
   1447   }
   1448 
   1449   // Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`.
   1450   DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth,
   1451                                           InlineInfo inline_info,
   1452                                           const CodeInfoEncoding& encoding,
   1453                                           uint32_t number_of_dex_registers) const {
   1454     if (!inline_info.HasDexRegisterMapAtDepth(encoding.inline_info.encoding, depth)) {
   1455       return DexRegisterMap();
   1456     } else {
   1457       uint32_t offset = encoding.dex_register_map.byte_offset +
   1458           inline_info.GetDexRegisterMapOffsetAtDepth(encoding.inline_info.encoding, depth);
   1459       size_t size = ComputeDexRegisterMapSizeOf(encoding, offset, number_of_dex_registers);
   1460       return DexRegisterMap(region_.Subregion(offset, size));
   1461     }
   1462   }
   1463 
   1464   InlineInfo GetInlineInfo(size_t index, const CodeInfoEncoding& encoding) const {
   1465     // Since we do not know the depth, we just return the whole remaining map. The caller may
   1466     // access the inline info for arbitrary depths. To return the precise inline info we would need
   1467     // to count the depth before returning.
   1468     // TODO: Clean this up.
   1469     const size_t bit_offset = encoding.inline_info.bit_offset +
   1470         index * encoding.inline_info.encoding.BitSize();
   1471     return InlineInfo(BitMemoryRegion(region_, bit_offset, region_.size_in_bits() - bit_offset));
   1472   }
   1473 
   1474   InlineInfo GetInlineInfoOf(StackMap stack_map, const CodeInfoEncoding& encoding) const {
   1475     DCHECK(stack_map.HasInlineInfo(encoding.stack_map.encoding));
   1476     uint32_t index = stack_map.GetInlineInfoIndex(encoding.stack_map.encoding);
   1477     return GetInlineInfo(index, encoding);
   1478   }
   1479 
   1480   StackMap GetStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const {
   1481     for (size_t i = 0, e = GetNumberOfStackMaps(encoding); i < e; ++i) {
   1482       StackMap stack_map = GetStackMapAt(i, encoding);
   1483       if (stack_map.GetDexPc(encoding.stack_map.encoding) == dex_pc) {
   1484         return stack_map;
   1485       }
   1486     }
   1487     return StackMap();
   1488   }
   1489 
   1490   // Searches the stack map list backwards because catch stack maps are stored
   1491   // at the end.
   1492   StackMap GetCatchStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const {
   1493     for (size_t i = GetNumberOfStackMaps(encoding); i > 0; --i) {
   1494       StackMap stack_map = GetStackMapAt(i - 1, encoding);
   1495       if (stack_map.GetDexPc(encoding.stack_map.encoding) == dex_pc) {
   1496         return stack_map;
   1497       }
   1498     }
   1499     return StackMap();
   1500   }
   1501 
   1502   StackMap GetOsrStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const {
   1503     size_t e = GetNumberOfStackMaps(encoding);
   1504     if (e == 0) {
   1505       // There cannot be OSR stack map if there is no stack map.
   1506       return StackMap();
   1507     }
   1508     // Walk over all stack maps. If two consecutive stack maps are identical, then we
   1509     // have found a stack map suitable for OSR.
   1510     const StackMapEncoding& stack_map_encoding = encoding.stack_map.encoding;
   1511     for (size_t i = 0; i < e - 1; ++i) {
   1512       StackMap stack_map = GetStackMapAt(i, encoding);
   1513       if (stack_map.GetDexPc(stack_map_encoding) == dex_pc) {
   1514         StackMap other = GetStackMapAt(i + 1, encoding);
   1515         if (other.GetDexPc(stack_map_encoding) == dex_pc &&
   1516             other.GetNativePcOffset(stack_map_encoding, kRuntimeISA) ==
   1517                 stack_map.GetNativePcOffset(stack_map_encoding, kRuntimeISA)) {
   1518           DCHECK_EQ(other.GetDexRegisterMapOffset(stack_map_encoding),
   1519                     stack_map.GetDexRegisterMapOffset(stack_map_encoding));
   1520           DCHECK(!stack_map.HasInlineInfo(stack_map_encoding));
   1521           if (i < e - 2) {
   1522             // Make sure there are not three identical stack maps following each other.
   1523             DCHECK_NE(
   1524                 stack_map.GetNativePcOffset(stack_map_encoding, kRuntimeISA),
   1525                 GetStackMapAt(i + 2, encoding).GetNativePcOffset(stack_map_encoding, kRuntimeISA));
   1526           }
   1527           return stack_map;
   1528         }
   1529       }
   1530     }
   1531     return StackMap();
   1532   }
   1533 
   1534   StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset,
   1535                                         const CodeInfoEncoding& encoding) const {
   1536     // TODO: Safepoint stack maps are sorted by native_pc_offset but catch stack
   1537     //       maps are not. If we knew that the method does not have try/catch,
   1538     //       we could do binary search.
   1539     for (size_t i = 0, e = GetNumberOfStackMaps(encoding); i < e; ++i) {
   1540       StackMap stack_map = GetStackMapAt(i, encoding);
   1541       if (stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA) ==
   1542           native_pc_offset) {
   1543         return stack_map;
   1544       }
   1545     }
   1546     return StackMap();
   1547   }
   1548 
   1549   InvokeInfo GetInvokeInfoForNativePcOffset(uint32_t native_pc_offset,
   1550                                             const CodeInfoEncoding& encoding) {
   1551     for (size_t index = 0; index < encoding.invoke_info.num_entries; index++) {
   1552       InvokeInfo item = GetInvokeInfo(encoding, index);
   1553       if (item.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA) == native_pc_offset) {
   1554         return item;
   1555       }
   1556     }
   1557     return InvokeInfo(BitMemoryRegion());
   1558   }
   1559 
   1560   // Dump this CodeInfo object on `os`.  `code_offset` is the (absolute)
   1561   // native PC of the compiled method and `number_of_dex_registers` the
   1562   // number of Dex virtual registers used in this method.  If
   1563   // `dump_stack_maps` is true, also dump the stack maps and the
   1564   // associated Dex register maps.
   1565   void Dump(VariableIndentationOutputStream* vios,
   1566             uint32_t code_offset,
   1567             uint16_t number_of_dex_registers,
   1568             bool dump_stack_maps,
   1569             InstructionSet instruction_set,
   1570             const MethodInfo& method_info) const;
   1571 
   1572   // Check that the code info has valid stack map and abort if it does not.
   1573   void AssertValidStackMap(const CodeInfoEncoding& encoding) const {
   1574     if (region_.size() != 0 && region_.size_in_bits() < GetStackMapsSizeInBits(encoding)) {
   1575       LOG(FATAL) << region_.size() << "\n"
   1576                  << encoding.HeaderSize() << "\n"
   1577                  << encoding.NonHeaderSize() << "\n"
   1578                  << encoding.location_catalog.num_entries << "\n"
   1579                  << encoding.stack_map.num_entries << "\n"
   1580                  << encoding.stack_map.encoding.BitSize();
   1581     }
   1582   }
   1583 
   1584  private:
   1585   // Compute the size of the Dex register map associated to the stack map at
   1586   // `dex_register_map_offset_in_code_info`.
   1587   size_t ComputeDexRegisterMapSizeOf(const CodeInfoEncoding& encoding,
   1588                                      uint32_t dex_register_map_offset_in_code_info,
   1589                                      uint16_t number_of_dex_registers) const {
   1590     // Offset where the actual mapping data starts within art::DexRegisterMap.
   1591     size_t location_mapping_data_offset_in_dex_register_map =
   1592         DexRegisterMap::GetLocationMappingDataOffset(number_of_dex_registers);
   1593     // Create a temporary art::DexRegisterMap to be able to call
   1594     // art::DexRegisterMap::GetNumberOfLiveDexRegisters and
   1595     DexRegisterMap dex_register_map_without_locations(
   1596         MemoryRegion(region_.Subregion(dex_register_map_offset_in_code_info,
   1597                                        location_mapping_data_offset_in_dex_register_map)));
   1598     size_t number_of_live_dex_registers =
   1599         dex_register_map_without_locations.GetNumberOfLiveDexRegisters(number_of_dex_registers);
   1600     size_t location_mapping_data_size_in_bits =
   1601         DexRegisterMap::SingleEntrySizeInBits(GetNumberOfLocationCatalogEntries(encoding))
   1602         * number_of_live_dex_registers;
   1603     size_t location_mapping_data_size_in_bytes =
   1604         RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte;
   1605     size_t dex_register_map_size =
   1606         location_mapping_data_offset_in_dex_register_map + location_mapping_data_size_in_bytes;
   1607     return dex_register_map_size;
   1608   }
   1609 
   1610   // Compute the size of a Dex register location catalog starting at offset `origin`
   1611   // in `region_` and containing `number_of_dex_locations` entries.
   1612   size_t ComputeDexRegisterLocationCatalogSize(uint32_t origin,
   1613                                                uint32_t number_of_dex_locations) const {
   1614     // TODO: Ideally, we would like to use art::DexRegisterLocationCatalog::Size or
   1615     // art::DexRegisterLocationCatalog::FindLocationOffset, but the
   1616     // DexRegisterLocationCatalog is not yet built.  Try to factor common code.
   1617     size_t offset = origin + DexRegisterLocationCatalog::kFixedSize;
   1618 
   1619     // Skip the first `number_of_dex_locations - 1` entries.
   1620     for (uint16_t i = 0; i < number_of_dex_locations; ++i) {
   1621       // Read the first next byte and inspect its first 3 bits to decide
   1622       // whether it is a short or a large location.
   1623       DexRegisterLocationCatalog::ShortLocation first_byte =
   1624           region_.LoadUnaligned<DexRegisterLocationCatalog::ShortLocation>(offset);
   1625       DexRegisterLocation::Kind kind =
   1626           DexRegisterLocationCatalog::ExtractKindFromShortLocation(first_byte);
   1627       if (DexRegisterLocation::IsShortLocationKind(kind)) {
   1628         // Short location.  Skip the current byte.
   1629         offset += DexRegisterLocationCatalog::SingleShortEntrySize();
   1630       } else {
   1631         // Large location.  Skip the 5 next bytes.
   1632         offset += DexRegisterLocationCatalog::SingleLargeEntrySize();
   1633       }
   1634     }
   1635     size_t size = offset - origin;
   1636     return size;
   1637   }
   1638 
   1639   MemoryRegion region_;
   1640   friend class StackMapStream;
   1641 };
   1642 
   1643 #undef ELEMENT_BYTE_OFFSET_AFTER
   1644 #undef ELEMENT_BIT_OFFSET_AFTER
   1645 
   1646 }  // namespace art
   1647 
   1648 #endif  // ART_RUNTIME_STACK_MAP_H_
   1649