Home | History | Annotate | Download | only in optimizing
      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 #include "stack_map.h"
     18 
     19 #include "art_method.h"
     20 #include "base/arena_bit_vector.h"
     21 #include "stack_map_stream.h"
     22 
     23 #include "gtest/gtest.h"
     24 
     25 namespace art {
     26 
     27 // Check that the stack mask of given stack map is identical
     28 // to the given bit vector. Returns true if they are same.
     29 static bool CheckStackMask(
     30     const CodeInfo& code_info,
     31     const CodeInfoEncoding& encoding,
     32     const StackMap& stack_map,
     33     const BitVector& bit_vector) {
     34   BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, stack_map);
     35   if (bit_vector.GetNumberOfBits() > encoding.stack_mask.encoding.BitSize()) {
     36     return false;
     37   }
     38   for (size_t i = 0; i < encoding.stack_mask.encoding.BitSize(); ++i) {
     39     if (stack_mask.LoadBit(i) != bit_vector.IsBitSet(i)) {
     40       return false;
     41     }
     42   }
     43   return true;
     44 }
     45 
     46 using Kind = DexRegisterLocation::Kind;
     47 
     48 TEST(StackMapTest, Test1) {
     49   ArenaPool pool;
     50   ArenaAllocator arena(&pool);
     51   StackMapStream stream(&arena, kRuntimeISA);
     52 
     53   ArenaBitVector sp_mask(&arena, 0, false);
     54   size_t number_of_dex_registers = 2;
     55   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
     56   stream.AddDexRegisterEntry(Kind::kInStack, 0);         // Short location.
     57   stream.AddDexRegisterEntry(Kind::kConstant, -2);       // Short location.
     58   stream.EndStackMapEntry();
     59 
     60   size_t size = stream.PrepareForFillIn();
     61   void* memory = arena.Alloc(size, kArenaAllocMisc);
     62   MemoryRegion region(memory, size);
     63   stream.FillInCodeInfo(region);
     64 
     65   CodeInfo code_info(region);
     66   CodeInfoEncoding encoding = code_info.ExtractEncoding();
     67   ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
     68 
     69   uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
     70   ASSERT_EQ(2u, number_of_catalog_entries);
     71   DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
     72   // The Dex register location catalog contains:
     73   // - one 1-byte short Dex register location, and
     74   // - one 5-byte large Dex register location.
     75   size_t expected_location_catalog_size = 1u + 5u;
     76   ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
     77 
     78   StackMap stack_map = code_info.GetStackMapAt(0, encoding);
     79   ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
     80   ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
     81   ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
     82   ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
     83   ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
     84 
     85   ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask));
     86 
     87   ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
     88   DexRegisterMap dex_register_map =
     89       code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
     90   ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
     91   ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
     92   ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
     93   // The Dex register map contains:
     94   // - one 1-byte live bit mask, and
     95   // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
     96   size_t expected_dex_register_map_size = 1u + 1u;
     97   ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
     98 
     99   ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(
    100                 0, number_of_dex_registers, code_info, encoding));
    101   ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
    102                 1, number_of_dex_registers, code_info, encoding));
    103   ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
    104                 0, number_of_dex_registers, code_info, encoding));
    105   ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
    106                 1, number_of_dex_registers, code_info, encoding));
    107   ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
    108                 0, number_of_dex_registers, code_info, encoding));
    109   ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
    110 
    111   size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
    112       0, number_of_dex_registers, number_of_catalog_entries);
    113   size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
    114       1, number_of_dex_registers, number_of_catalog_entries);
    115   ASSERT_EQ(0u, index0);
    116   ASSERT_EQ(1u, index1);
    117   DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
    118   DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
    119   ASSERT_EQ(Kind::kInStack, location0.GetKind());
    120   ASSERT_EQ(Kind::kConstant, location1.GetKind());
    121   ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
    122   ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
    123   ASSERT_EQ(0, location0.GetValue());
    124   ASSERT_EQ(-2, location1.GetValue());
    125 
    126   ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
    127 }
    128 
    129 TEST(StackMapTest, Test2) {
    130   ArenaPool pool;
    131   ArenaAllocator arena(&pool);
    132   StackMapStream stream(&arena, kRuntimeISA);
    133   ArtMethod art_method;
    134 
    135   ArenaBitVector sp_mask1(&arena, 0, true);
    136   sp_mask1.SetBit(2);
    137   sp_mask1.SetBit(4);
    138   size_t number_of_dex_registers = 2;
    139   size_t number_of_dex_registers_in_inline_info = 0;
    140   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 2);
    141   stream.AddDexRegisterEntry(Kind::kInStack, 0);         // Short location.
    142   stream.AddDexRegisterEntry(Kind::kConstant, -2);       // Large location.
    143   stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info);
    144   stream.EndInlineInfoEntry();
    145   stream.BeginInlineInfoEntry(&art_method, 2, number_of_dex_registers_in_inline_info);
    146   stream.EndInlineInfoEntry();
    147   stream.EndStackMapEntry();
    148 
    149   ArenaBitVector sp_mask2(&arena, 0, true);
    150   sp_mask2.SetBit(3);
    151   sp_mask2.SetBit(8);
    152   stream.BeginStackMapEntry(1, 128, 0xFF, &sp_mask2, number_of_dex_registers, 0);
    153   stream.AddDexRegisterEntry(Kind::kInRegister, 18);     // Short location.
    154   stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3);   // Short location.
    155   stream.EndStackMapEntry();
    156 
    157   ArenaBitVector sp_mask3(&arena, 0, true);
    158   sp_mask3.SetBit(1);
    159   sp_mask3.SetBit(5);
    160   stream.BeginStackMapEntry(2, 192, 0xAB, &sp_mask3, number_of_dex_registers, 0);
    161   stream.AddDexRegisterEntry(Kind::kInRegister, 6);       // Short location.
    162   stream.AddDexRegisterEntry(Kind::kInRegisterHigh, 8);   // Short location.
    163   stream.EndStackMapEntry();
    164 
    165   ArenaBitVector sp_mask4(&arena, 0, true);
    166   sp_mask4.SetBit(6);
    167   sp_mask4.SetBit(7);
    168   stream.BeginStackMapEntry(3, 256, 0xCD, &sp_mask4, number_of_dex_registers, 0);
    169   stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3);      // Short location, same in stack map 2.
    170   stream.AddDexRegisterEntry(Kind::kInFpuRegisterHigh, 1);  // Short location.
    171   stream.EndStackMapEntry();
    172 
    173   size_t size = stream.PrepareForFillIn();
    174   void* memory = arena.Alloc(size, kArenaAllocMisc);
    175   MemoryRegion region(memory, size);
    176   stream.FillInCodeInfo(region);
    177 
    178   CodeInfo code_info(region);
    179   CodeInfoEncoding encoding = code_info.ExtractEncoding();
    180   ASSERT_EQ(4u, code_info.GetNumberOfStackMaps(encoding));
    181 
    182   uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
    183   ASSERT_EQ(7u, number_of_catalog_entries);
    184   DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
    185   // The Dex register location catalog contains:
    186   // - six 1-byte short Dex register locations, and
    187   // - one 5-byte large Dex register location.
    188   size_t expected_location_catalog_size = 6u * 1u + 5u;
    189   ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
    190 
    191   // First stack map.
    192   {
    193     StackMap stack_map = code_info.GetStackMapAt(0, encoding);
    194     ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
    195     ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
    196     ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
    197     ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
    198     ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
    199 
    200     ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask1));
    201 
    202     ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
    203     DexRegisterMap dex_register_map =
    204         code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
    205     ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
    206     ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
    207     ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
    208     // The Dex register map contains:
    209     // - one 1-byte live bit mask, and
    210     // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
    211     size_t expected_dex_register_map_size = 1u + 1u;
    212     ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
    213 
    214     ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(
    215                   0, number_of_dex_registers, code_info, encoding));
    216     ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
    217                   1, number_of_dex_registers, code_info, encoding));
    218     ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
    219                   0, number_of_dex_registers, code_info, encoding));
    220     ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
    221                   1, number_of_dex_registers, code_info, encoding));
    222     ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
    223                   0, number_of_dex_registers, code_info, encoding));
    224     ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
    225 
    226     size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
    227         0, number_of_dex_registers, number_of_catalog_entries);
    228     size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
    229         1, number_of_dex_registers, number_of_catalog_entries);
    230     ASSERT_EQ(0u, index0);
    231     ASSERT_EQ(1u, index1);
    232     DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
    233     DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
    234     ASSERT_EQ(Kind::kInStack, location0.GetKind());
    235     ASSERT_EQ(Kind::kConstant, location1.GetKind());
    236     ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
    237     ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
    238     ASSERT_EQ(0, location0.GetValue());
    239     ASSERT_EQ(-2, location1.GetValue());
    240 
    241     ASSERT_TRUE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
    242     InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
    243     ASSERT_EQ(2u, inline_info.GetDepth(encoding.inline_info.encoding));
    244     ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
    245     ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
    246     ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
    247     ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
    248   }
    249 
    250   // Second stack map.
    251   {
    252     StackMap stack_map = code_info.GetStackMapAt(1, encoding);
    253     ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1u, encoding)));
    254     ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(128u, encoding)));
    255     ASSERT_EQ(1u, stack_map.GetDexPc(encoding.stack_map.encoding));
    256     ASSERT_EQ(128u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
    257     ASSERT_EQ(0xFFu, code_info.GetRegisterMaskOf(encoding, stack_map));
    258 
    259     ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask2));
    260 
    261     ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
    262     DexRegisterMap dex_register_map =
    263         code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
    264     ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
    265     ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
    266     ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
    267     // The Dex register map contains:
    268     // - one 1-byte live bit mask, and
    269     // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
    270     size_t expected_dex_register_map_size = 1u + 1u;
    271     ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
    272 
    273     ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(
    274                   0, number_of_dex_registers, code_info, encoding));
    275     ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
    276                   1, number_of_dex_registers, code_info, encoding));
    277     ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
    278                   0, number_of_dex_registers, code_info, encoding));
    279     ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
    280                   1, number_of_dex_registers, code_info, encoding));
    281     ASSERT_EQ(18, dex_register_map.GetMachineRegister(
    282                   0, number_of_dex_registers, code_info, encoding));
    283     ASSERT_EQ(3, dex_register_map.GetMachineRegister(
    284                   1, number_of_dex_registers, code_info, encoding));
    285 
    286     size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
    287         0, number_of_dex_registers, number_of_catalog_entries);
    288     size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
    289         1, number_of_dex_registers, number_of_catalog_entries);
    290     ASSERT_EQ(2u, index0);
    291     ASSERT_EQ(3u, index1);
    292     DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
    293     DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
    294     ASSERT_EQ(Kind::kInRegister, location0.GetKind());
    295     ASSERT_EQ(Kind::kInFpuRegister, location1.GetKind());
    296     ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
    297     ASSERT_EQ(Kind::kInFpuRegister, location1.GetInternalKind());
    298     ASSERT_EQ(18, location0.GetValue());
    299     ASSERT_EQ(3, location1.GetValue());
    300 
    301     ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
    302   }
    303 
    304   // Third stack map.
    305   {
    306     StackMap stack_map = code_info.GetStackMapAt(2, encoding);
    307     ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(2u, encoding)));
    308     ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(192u, encoding)));
    309     ASSERT_EQ(2u, stack_map.GetDexPc(encoding.stack_map.encoding));
    310     ASSERT_EQ(192u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
    311     ASSERT_EQ(0xABu, code_info.GetRegisterMaskOf(encoding, stack_map));
    312 
    313     ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask3));
    314 
    315     ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
    316     DexRegisterMap dex_register_map =
    317         code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
    318     ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
    319     ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
    320     ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
    321     // The Dex register map contains:
    322     // - one 1-byte live bit mask, and
    323     // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
    324     size_t expected_dex_register_map_size = 1u + 1u;
    325     ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
    326 
    327     ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(
    328                   0, number_of_dex_registers, code_info, encoding));
    329     ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationKind(
    330                   1, number_of_dex_registers, code_info, encoding));
    331     ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
    332                   0, number_of_dex_registers, code_info, encoding));
    333     ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationInternalKind(
    334                   1, number_of_dex_registers, code_info, encoding));
    335     ASSERT_EQ(6, dex_register_map.GetMachineRegister(
    336                   0, number_of_dex_registers, code_info, encoding));
    337     ASSERT_EQ(8, dex_register_map.GetMachineRegister(
    338                   1, number_of_dex_registers, code_info, encoding));
    339 
    340     size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
    341         0, number_of_dex_registers, number_of_catalog_entries);
    342     size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
    343         1, number_of_dex_registers, number_of_catalog_entries);
    344     ASSERT_EQ(4u, index0);
    345     ASSERT_EQ(5u, index1);
    346     DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
    347     DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
    348     ASSERT_EQ(Kind::kInRegister, location0.GetKind());
    349     ASSERT_EQ(Kind::kInRegisterHigh, location1.GetKind());
    350     ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
    351     ASSERT_EQ(Kind::kInRegisterHigh, location1.GetInternalKind());
    352     ASSERT_EQ(6, location0.GetValue());
    353     ASSERT_EQ(8, location1.GetValue());
    354 
    355     ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
    356   }
    357 
    358   // Fourth stack map.
    359   {
    360     StackMap stack_map = code_info.GetStackMapAt(3, encoding);
    361     ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(3u, encoding)));
    362     ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(256u, encoding)));
    363     ASSERT_EQ(3u, stack_map.GetDexPc(encoding.stack_map.encoding));
    364     ASSERT_EQ(256u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
    365     ASSERT_EQ(0xCDu, code_info.GetRegisterMaskOf(encoding, stack_map));
    366 
    367     ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask4));
    368 
    369     ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
    370     DexRegisterMap dex_register_map =
    371         code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
    372     ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
    373     ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
    374     ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
    375     // The Dex register map contains:
    376     // - one 1-byte live bit mask, and
    377     // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
    378     size_t expected_dex_register_map_size = 1u + 1u;
    379     ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
    380 
    381     ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
    382                   0, number_of_dex_registers, code_info, encoding));
    383     ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationKind(
    384                   1, number_of_dex_registers, code_info, encoding));
    385     ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
    386                   0, number_of_dex_registers, code_info, encoding));
    387     ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationInternalKind(
    388                   1, number_of_dex_registers, code_info, encoding));
    389     ASSERT_EQ(3, dex_register_map.GetMachineRegister(
    390                   0, number_of_dex_registers, code_info, encoding));
    391     ASSERT_EQ(1, dex_register_map.GetMachineRegister(
    392                   1, number_of_dex_registers, code_info, encoding));
    393 
    394     size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
    395         0, number_of_dex_registers, number_of_catalog_entries);
    396     size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
    397         1, number_of_dex_registers, number_of_catalog_entries);
    398     ASSERT_EQ(3u, index0);  // Shared with second stack map.
    399     ASSERT_EQ(6u, index1);
    400     DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
    401     DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
    402     ASSERT_EQ(Kind::kInFpuRegister, location0.GetKind());
    403     ASSERT_EQ(Kind::kInFpuRegisterHigh, location1.GetKind());
    404     ASSERT_EQ(Kind::kInFpuRegister, location0.GetInternalKind());
    405     ASSERT_EQ(Kind::kInFpuRegisterHigh, location1.GetInternalKind());
    406     ASSERT_EQ(3, location0.GetValue());
    407     ASSERT_EQ(1, location1.GetValue());
    408 
    409     ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
    410   }
    411 }
    412 
    413 TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
    414   ArenaPool pool;
    415   ArenaAllocator arena(&pool);
    416   StackMapStream stream(&arena, kRuntimeISA);
    417   ArtMethod art_method;
    418 
    419   ArenaBitVector sp_mask1(&arena, 0, true);
    420   sp_mask1.SetBit(2);
    421   sp_mask1.SetBit(4);
    422   const size_t number_of_dex_registers = 2;
    423   const size_t number_of_dex_registers_in_inline_info = 2;
    424   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 1);
    425   stream.AddDexRegisterEntry(Kind::kInStack, 0);         // Short location.
    426   stream.AddDexRegisterEntry(Kind::kConstant, -2);       // Large location.
    427   stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info);
    428   stream.AddDexRegisterEntry(Kind::kInStack, 0);         // Short location.
    429   stream.AddDexRegisterEntry(Kind::kConstant, -2);       // Large location.
    430   stream.EndInlineInfoEntry();
    431   stream.EndStackMapEntry();
    432 
    433   size_t size = stream.PrepareForFillIn();
    434   void* memory = arena.Alloc(size, kArenaAllocMisc);
    435   MemoryRegion region(memory, size);
    436   stream.FillInCodeInfo(region);
    437 
    438   CodeInfo code_info(region);
    439   CodeInfoEncoding encoding = code_info.ExtractEncoding();
    440   ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
    441 
    442   uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
    443   ASSERT_EQ(2u, number_of_catalog_entries);
    444   DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
    445   // The Dex register location catalog contains:
    446   // - one 1-byte short Dex register locations, and
    447   // - one 5-byte large Dex register location.
    448   const size_t expected_location_catalog_size = 1u + 5u;
    449   ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
    450 
    451   // First stack map.
    452   {
    453     StackMap stack_map = code_info.GetStackMapAt(0, encoding);
    454     ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
    455     ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
    456     ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
    457     ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
    458     ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
    459 
    460     ASSERT_TRUE(CheckStackMask(code_info, encoding, stack_map, sp_mask1));
    461 
    462     ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
    463     DexRegisterMap map(code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers));
    464     ASSERT_TRUE(map.IsDexRegisterLive(0));
    465     ASSERT_TRUE(map.IsDexRegisterLive(1));
    466     ASSERT_EQ(2u, map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
    467     // The Dex register map contains:
    468     // - one 1-byte live bit mask, and
    469     // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
    470     size_t expected_map_size = 1u + 1u;
    471     ASSERT_EQ(expected_map_size, map.Size());
    472 
    473     ASSERT_EQ(Kind::kInStack, map.GetLocationKind(0, number_of_dex_registers, code_info, encoding));
    474     ASSERT_EQ(Kind::kConstant,
    475               map.GetLocationKind(1, number_of_dex_registers, code_info, encoding));
    476     ASSERT_EQ(Kind::kInStack,
    477               map.GetLocationInternalKind(0, number_of_dex_registers, code_info, encoding));
    478     ASSERT_EQ(Kind::kConstantLargeValue,
    479               map.GetLocationInternalKind(1, number_of_dex_registers, code_info, encoding));
    480     ASSERT_EQ(0, map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info, encoding));
    481     ASSERT_EQ(-2, map.GetConstant(1, number_of_dex_registers, code_info, encoding));
    482 
    483     const size_t index0 =
    484         map.GetLocationCatalogEntryIndex(0, number_of_dex_registers, number_of_catalog_entries);
    485     const size_t index1 =
    486         map.GetLocationCatalogEntryIndex(1, number_of_dex_registers, number_of_catalog_entries);
    487     ASSERT_EQ(0u, index0);
    488     ASSERT_EQ(1u, index1);
    489     DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
    490     DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
    491     ASSERT_EQ(Kind::kInStack, location0.GetKind());
    492     ASSERT_EQ(Kind::kConstant, location1.GetKind());
    493     ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
    494     ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
    495     ASSERT_EQ(0, location0.GetValue());
    496     ASSERT_EQ(-2, location1.GetValue());
    497 
    498     // Test that the inline info dex register map deduplicated to the same offset as the stack map
    499     // one.
    500     ASSERT_TRUE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
    501     InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
    502     EXPECT_EQ(inline_info.GetDexRegisterMapOffsetAtDepth(encoding.inline_info.encoding, 0),
    503               stack_map.GetDexRegisterMapOffset(encoding.stack_map.encoding));
    504   }
    505 }
    506 
    507 TEST(StackMapTest, TestNonLiveDexRegisters) {
    508   ArenaPool pool;
    509   ArenaAllocator arena(&pool);
    510   StackMapStream stream(&arena, kRuntimeISA);
    511 
    512   ArenaBitVector sp_mask(&arena, 0, false);
    513   uint32_t number_of_dex_registers = 2;
    514   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
    515   stream.AddDexRegisterEntry(Kind::kNone, 0);            // No location.
    516   stream.AddDexRegisterEntry(Kind::kConstant, -2);       // Large location.
    517   stream.EndStackMapEntry();
    518 
    519   size_t size = stream.PrepareForFillIn();
    520   void* memory = arena.Alloc(size, kArenaAllocMisc);
    521   MemoryRegion region(memory, size);
    522   stream.FillInCodeInfo(region);
    523 
    524   CodeInfo code_info(region);
    525   CodeInfoEncoding encoding = code_info.ExtractEncoding();
    526   ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
    527 
    528   uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
    529   ASSERT_EQ(1u, number_of_catalog_entries);
    530   DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
    531   // The Dex register location catalog contains:
    532   // - one 5-byte large Dex register location.
    533   size_t expected_location_catalog_size = 5u;
    534   ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
    535 
    536   StackMap stack_map = code_info.GetStackMapAt(0, encoding);
    537   ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
    538   ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
    539   ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
    540   ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
    541   ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
    542 
    543   ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
    544   DexRegisterMap dex_register_map =
    545       code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
    546   ASSERT_FALSE(dex_register_map.IsDexRegisterLive(0));
    547   ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
    548   ASSERT_EQ(1u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
    549   // The Dex register map contains:
    550   // - one 1-byte live bit mask.
    551   // No space is allocated for the sole location catalog entry index, as it is useless.
    552   size_t expected_dex_register_map_size = 1u + 0u;
    553   ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
    554 
    555   ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationKind(
    556                 0, number_of_dex_registers, code_info, encoding));
    557   ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
    558                 1, number_of_dex_registers, code_info, encoding));
    559   ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationInternalKind(
    560                 0, number_of_dex_registers, code_info, encoding));
    561   ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
    562                 1, number_of_dex_registers, code_info, encoding));
    563   ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
    564 
    565   size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
    566       0, number_of_dex_registers, number_of_catalog_entries);
    567   size_t index1 =  dex_register_map.GetLocationCatalogEntryIndex(
    568       1, number_of_dex_registers, number_of_catalog_entries);
    569   ASSERT_EQ(DexRegisterLocationCatalog::kNoLocationEntryIndex, index0);
    570   ASSERT_EQ(0u, index1);
    571   DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
    572   DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
    573   ASSERT_EQ(Kind::kNone, location0.GetKind());
    574   ASSERT_EQ(Kind::kConstant, location1.GetKind());
    575   ASSERT_EQ(Kind::kNone, location0.GetInternalKind());
    576   ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
    577   ASSERT_EQ(0, location0.GetValue());
    578   ASSERT_EQ(-2, location1.GetValue());
    579 
    580   ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
    581 }
    582 
    583 // Generate a stack map whose dex register offset is
    584 // StackMap::kNoDexRegisterMapSmallEncoding, and ensure we do
    585 // not treat it as kNoDexRegisterMap.
    586 TEST(StackMapTest, DexRegisterMapOffsetOverflow) {
    587   ArenaPool pool;
    588   ArenaAllocator arena(&pool);
    589   StackMapStream stream(&arena, kRuntimeISA);
    590 
    591   ArenaBitVector sp_mask(&arena, 0, false);
    592   uint32_t number_of_dex_registers = 1024;
    593   // Create the first stack map (and its Dex register map).
    594   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
    595   uint32_t number_of_dex_live_registers_in_dex_register_map_0 = number_of_dex_registers - 8;
    596   for (uint32_t i = 0; i < number_of_dex_live_registers_in_dex_register_map_0; ++i) {
    597     // Use two different Dex register locations to populate this map,
    598     // as using a single value (in the whole CodeInfo object) would
    599     // make this Dex register mapping data empty (see
    600     // art::DexRegisterMap::SingleEntrySizeInBits).
    601     stream.AddDexRegisterEntry(Kind::kConstant, i % 2);  // Short location.
    602   }
    603   stream.EndStackMapEntry();
    604   // Create the second stack map (and its Dex register map).
    605   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
    606   for (uint32_t i = 0; i < number_of_dex_registers; ++i) {
    607     stream.AddDexRegisterEntry(Kind::kConstant, 0);  // Short location.
    608   }
    609   stream.EndStackMapEntry();
    610 
    611   size_t size = stream.PrepareForFillIn();
    612   void* memory = arena.Alloc(size, kArenaAllocMisc);
    613   MemoryRegion region(memory, size);
    614   stream.FillInCodeInfo(region);
    615 
    616   CodeInfo code_info(region);
    617   CodeInfoEncoding encoding = code_info.ExtractEncoding();
    618   // The location catalog contains two entries (DexRegisterLocation(kConstant, 0)
    619   // and DexRegisterLocation(kConstant, 1)), therefore the location catalog index
    620   // has a size of 1 bit.
    621   uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
    622   ASSERT_EQ(2u, number_of_catalog_entries);
    623   ASSERT_EQ(1u, DexRegisterMap::SingleEntrySizeInBits(number_of_catalog_entries));
    624 
    625   // The first Dex register map contains:
    626   // - a live register bit mask for 1024 registers (that is, 128 bytes of
    627   //   data); and
    628   // - Dex register mapping information for 1016 1-bit Dex (live) register
    629   //   locations (that is, 127 bytes of data).
    630   // Hence it has a size of 255 bytes, and therefore...
    631   ASSERT_EQ(128u, DexRegisterMap::GetLiveBitMaskSize(number_of_dex_registers));
    632   StackMap stack_map0 = code_info.GetStackMapAt(0, encoding);
    633   DexRegisterMap dex_register_map0 =
    634       code_info.GetDexRegisterMapOf(stack_map0, encoding, number_of_dex_registers);
    635   ASSERT_EQ(127u, dex_register_map0.GetLocationMappingDataSize(number_of_dex_registers,
    636                                                                number_of_catalog_entries));
    637   ASSERT_EQ(255u, dex_register_map0.Size());
    638 
    639   StackMap stack_map1 = code_info.GetStackMapAt(1, encoding);
    640   ASSERT_TRUE(stack_map1.HasDexRegisterMap(encoding.stack_map.encoding));
    641   // ...the offset of the second Dex register map (relative to the
    642   // beginning of the Dex register maps region) is 255 (i.e.,
    643   // kNoDexRegisterMapSmallEncoding).
    644   ASSERT_NE(stack_map1.GetDexRegisterMapOffset(encoding.stack_map.encoding),
    645             StackMap::kNoDexRegisterMap);
    646   ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(encoding.stack_map.encoding), 0xFFu);
    647 }
    648 
    649 TEST(StackMapTest, TestShareDexRegisterMap) {
    650   ArenaPool pool;
    651   ArenaAllocator arena(&pool);
    652   StackMapStream stream(&arena, kRuntimeISA);
    653 
    654   ArenaBitVector sp_mask(&arena, 0, false);
    655   uint32_t number_of_dex_registers = 2;
    656   // First stack map.
    657   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
    658   stream.AddDexRegisterEntry(Kind::kInRegister, 0);  // Short location.
    659   stream.AddDexRegisterEntry(Kind::kConstant, -2);   // Large location.
    660   stream.EndStackMapEntry();
    661   // Second stack map, which should share the same dex register map.
    662   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
    663   stream.AddDexRegisterEntry(Kind::kInRegister, 0);  // Short location.
    664   stream.AddDexRegisterEntry(Kind::kConstant, -2);   // Large location.
    665   stream.EndStackMapEntry();
    666   // Third stack map (doesn't share the dex register map).
    667   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
    668   stream.AddDexRegisterEntry(Kind::kInRegister, 2);  // Short location.
    669   stream.AddDexRegisterEntry(Kind::kConstant, -2);   // Large location.
    670   stream.EndStackMapEntry();
    671 
    672   size_t size = stream.PrepareForFillIn();
    673   void* memory = arena.Alloc(size, kArenaAllocMisc);
    674   MemoryRegion region(memory, size);
    675   stream.FillInCodeInfo(region);
    676 
    677   CodeInfo ci(region);
    678   CodeInfoEncoding encoding = ci.ExtractEncoding();
    679 
    680   // Verify first stack map.
    681   StackMap sm0 = ci.GetStackMapAt(0, encoding);
    682   DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, encoding, number_of_dex_registers);
    683   ASSERT_EQ(0, dex_registers0.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
    684   ASSERT_EQ(-2, dex_registers0.GetConstant(1, number_of_dex_registers, ci, encoding));
    685 
    686   // Verify second stack map.
    687   StackMap sm1 = ci.GetStackMapAt(1, encoding);
    688   DexRegisterMap dex_registers1 = ci.GetDexRegisterMapOf(sm1, encoding, number_of_dex_registers);
    689   ASSERT_EQ(0, dex_registers1.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
    690   ASSERT_EQ(-2, dex_registers1.GetConstant(1, number_of_dex_registers, ci, encoding));
    691 
    692   // Verify third stack map.
    693   StackMap sm2 = ci.GetStackMapAt(2, encoding);
    694   DexRegisterMap dex_registers2 = ci.GetDexRegisterMapOf(sm2, encoding, number_of_dex_registers);
    695   ASSERT_EQ(2, dex_registers2.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
    696   ASSERT_EQ(-2, dex_registers2.GetConstant(1, number_of_dex_registers, ci, encoding));
    697 
    698   // Verify dex register map offsets.
    699   ASSERT_EQ(sm0.GetDexRegisterMapOffset(encoding.stack_map.encoding),
    700             sm1.GetDexRegisterMapOffset(encoding.stack_map.encoding));
    701   ASSERT_NE(sm0.GetDexRegisterMapOffset(encoding.stack_map.encoding),
    702             sm2.GetDexRegisterMapOffset(encoding.stack_map.encoding));
    703   ASSERT_NE(sm1.GetDexRegisterMapOffset(encoding.stack_map.encoding),
    704             sm2.GetDexRegisterMapOffset(encoding.stack_map.encoding));
    705 }
    706 
    707 TEST(StackMapTest, TestNoDexRegisterMap) {
    708   ArenaPool pool;
    709   ArenaAllocator arena(&pool);
    710   StackMapStream stream(&arena, kRuntimeISA);
    711 
    712   ArenaBitVector sp_mask(&arena, 0, false);
    713   uint32_t number_of_dex_registers = 0;
    714   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
    715   stream.EndStackMapEntry();
    716 
    717   number_of_dex_registers = 1;
    718   stream.BeginStackMapEntry(1, 68, 0x4, &sp_mask, number_of_dex_registers, 0);
    719   stream.EndStackMapEntry();
    720 
    721   size_t size = stream.PrepareForFillIn();
    722   void* memory = arena.Alloc(size, kArenaAllocMisc);
    723   MemoryRegion region(memory, size);
    724   stream.FillInCodeInfo(region);
    725 
    726   CodeInfo code_info(region);
    727   CodeInfoEncoding encoding = code_info.ExtractEncoding();
    728   ASSERT_EQ(2u, code_info.GetNumberOfStackMaps(encoding));
    729 
    730   uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
    731   ASSERT_EQ(0u, number_of_catalog_entries);
    732   DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
    733   ASSERT_EQ(0u, location_catalog.Size());
    734 
    735   StackMap stack_map = code_info.GetStackMapAt(0, encoding);
    736   ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
    737   ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
    738   ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map.encoding));
    739   ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
    740   ASSERT_EQ(0x3u, code_info.GetRegisterMaskOf(encoding, stack_map));
    741 
    742   ASSERT_FALSE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
    743   ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
    744 
    745   stack_map = code_info.GetStackMapAt(1, encoding);
    746   ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1, encoding)));
    747   ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(68, encoding)));
    748   ASSERT_EQ(1u, stack_map.GetDexPc(encoding.stack_map.encoding));
    749   ASSERT_EQ(68u, stack_map.GetNativePcOffset(encoding.stack_map.encoding, kRuntimeISA));
    750   ASSERT_EQ(0x4u, code_info.GetRegisterMaskOf(encoding, stack_map));
    751 
    752   ASSERT_FALSE(stack_map.HasDexRegisterMap(encoding.stack_map.encoding));
    753   ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map.encoding));
    754 }
    755 
    756 TEST(StackMapTest, InlineTest) {
    757   ArenaPool pool;
    758   ArenaAllocator arena(&pool);
    759   StackMapStream stream(&arena, kRuntimeISA);
    760   ArtMethod art_method;
    761 
    762   ArenaBitVector sp_mask1(&arena, 0, true);
    763   sp_mask1.SetBit(2);
    764   sp_mask1.SetBit(4);
    765 
    766   // First stack map.
    767   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, 2, 2);
    768   stream.AddDexRegisterEntry(Kind::kInStack, 0);
    769   stream.AddDexRegisterEntry(Kind::kConstant, 4);
    770 
    771   stream.BeginInlineInfoEntry(&art_method, 2, 1);
    772   stream.AddDexRegisterEntry(Kind::kInStack, 8);
    773   stream.EndInlineInfoEntry();
    774   stream.BeginInlineInfoEntry(&art_method, 3, 3);
    775   stream.AddDexRegisterEntry(Kind::kInStack, 16);
    776   stream.AddDexRegisterEntry(Kind::kConstant, 20);
    777   stream.AddDexRegisterEntry(Kind::kInRegister, 15);
    778   stream.EndInlineInfoEntry();
    779 
    780   stream.EndStackMapEntry();
    781 
    782   // Second stack map.
    783   stream.BeginStackMapEntry(2, 22, 0x3, &sp_mask1, 2, 3);
    784   stream.AddDexRegisterEntry(Kind::kInStack, 56);
    785   stream.AddDexRegisterEntry(Kind::kConstant, 0);
    786 
    787   stream.BeginInlineInfoEntry(&art_method, 2, 1);
    788   stream.AddDexRegisterEntry(Kind::kInStack, 12);
    789   stream.EndInlineInfoEntry();
    790   stream.BeginInlineInfoEntry(&art_method, 3, 3);
    791   stream.AddDexRegisterEntry(Kind::kInStack, 80);
    792   stream.AddDexRegisterEntry(Kind::kConstant, 10);
    793   stream.AddDexRegisterEntry(Kind::kInRegister, 5);
    794   stream.EndInlineInfoEntry();
    795   stream.BeginInlineInfoEntry(&art_method, 5, 0);
    796   stream.EndInlineInfoEntry();
    797 
    798   stream.EndStackMapEntry();
    799 
    800   // Third stack map.
    801   stream.BeginStackMapEntry(4, 56, 0x3, &sp_mask1, 2, 0);
    802   stream.AddDexRegisterEntry(Kind::kNone, 0);
    803   stream.AddDexRegisterEntry(Kind::kConstant, 4);
    804   stream.EndStackMapEntry();
    805 
    806   // Fourth stack map.
    807   stream.BeginStackMapEntry(6, 78, 0x3, &sp_mask1, 2, 3);
    808   stream.AddDexRegisterEntry(Kind::kInStack, 56);
    809   stream.AddDexRegisterEntry(Kind::kConstant, 0);
    810 
    811   stream.BeginInlineInfoEntry(&art_method, 2, 0);
    812   stream.EndInlineInfoEntry();
    813   stream.BeginInlineInfoEntry(&art_method, 5, 1);
    814   stream.AddDexRegisterEntry(Kind::kInRegister, 2);
    815   stream.EndInlineInfoEntry();
    816   stream.BeginInlineInfoEntry(&art_method, 10, 2);
    817   stream.AddDexRegisterEntry(Kind::kNone, 0);
    818   stream.AddDexRegisterEntry(Kind::kInRegister, 3);
    819   stream.EndInlineInfoEntry();
    820 
    821   stream.EndStackMapEntry();
    822 
    823   size_t size = stream.PrepareForFillIn();
    824   void* memory = arena.Alloc(size, kArenaAllocMisc);
    825   MemoryRegion region(memory, size);
    826   stream.FillInCodeInfo(region);
    827 
    828   CodeInfo ci(region);
    829   CodeInfoEncoding encoding = ci.ExtractEncoding();
    830 
    831   {
    832     // Verify first stack map.
    833     StackMap sm0 = ci.GetStackMapAt(0, encoding);
    834 
    835     DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, encoding, 2);
    836     ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
    837     ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding));
    838 
    839     InlineInfo if0 = ci.GetInlineInfoOf(sm0, encoding);
    840     ASSERT_EQ(2u, if0.GetDepth(encoding.inline_info.encoding));
    841     ASSERT_EQ(2u, if0.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
    842     ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
    843     ASSERT_EQ(3u, if0.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
    844     ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
    845 
    846     DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, encoding, 1);
    847     ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding));
    848 
    849     DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if0, encoding, 3);
    850     ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0, 3, ci, encoding));
    851     ASSERT_EQ(20, dex_registers2.GetConstant(1, 3, ci, encoding));
    852     ASSERT_EQ(15, dex_registers2.GetMachineRegister(2, 3, ci, encoding));
    853   }
    854 
    855   {
    856     // Verify second stack map.
    857     StackMap sm1 = ci.GetStackMapAt(1, encoding);
    858 
    859     DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm1, encoding, 2);
    860     ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
    861     ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding));
    862 
    863     InlineInfo if1 = ci.GetInlineInfoOf(sm1, encoding);
    864     ASSERT_EQ(3u, if1.GetDepth(encoding.inline_info.encoding));
    865     ASSERT_EQ(2u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
    866     ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
    867     ASSERT_EQ(3u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
    868     ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
    869     ASSERT_EQ(5u, if1.GetDexPcAtDepth(encoding.inline_info.encoding, 2));
    870     ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 2));
    871 
    872     DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, encoding, 1);
    873     ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding));
    874 
    875     DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if1, encoding, 3);
    876     ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0, 3, ci, encoding));
    877     ASSERT_EQ(10, dex_registers2.GetConstant(1, 3, ci, encoding));
    878     ASSERT_EQ(5, dex_registers2.GetMachineRegister(2, 3, ci, encoding));
    879 
    880     ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(encoding.inline_info.encoding, 2));
    881   }
    882 
    883   {
    884     // Verify third stack map.
    885     StackMap sm2 = ci.GetStackMapAt(2, encoding);
    886 
    887     DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2, encoding, 2);
    888     ASSERT_FALSE(dex_registers0.IsDexRegisterLive(0));
    889     ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding));
    890     ASSERT_FALSE(sm2.HasInlineInfo(encoding.stack_map.encoding));
    891   }
    892 
    893   {
    894     // Verify fourth stack map.
    895     StackMap sm3 = ci.GetStackMapAt(3, encoding);
    896 
    897     DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm3, encoding, 2);
    898     ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
    899     ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding));
    900 
    901     InlineInfo if2 = ci.GetInlineInfoOf(sm3, encoding);
    902     ASSERT_EQ(3u, if2.GetDepth(encoding.inline_info.encoding));
    903     ASSERT_EQ(2u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 0));
    904     ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 0));
    905     ASSERT_EQ(5u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 1));
    906     ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 1));
    907     ASSERT_EQ(10u, if2.GetDexPcAtDepth(encoding.inline_info.encoding, 2));
    908     ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info.encoding, 2));
    909 
    910     ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(encoding.inline_info.encoding, 0));
    911 
    912     DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, encoding, 1);
    913     ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci, encoding));
    914 
    915     DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, encoding, 2);
    916     ASSERT_FALSE(dex_registers2.IsDexRegisterLive(0));
    917     ASSERT_EQ(3, dex_registers2.GetMachineRegister(1, 2, ci, encoding));
    918   }
    919 }
    920 
    921 TEST(StackMapTest, CodeOffsetTest) {
    922   // Test minimum alignments, encoding, and decoding.
    923   CodeOffset offset_thumb2 = CodeOffset::FromOffset(kThumb2InstructionAlignment, kThumb2);
    924   CodeOffset offset_arm64 = CodeOffset::FromOffset(kArm64InstructionAlignment, kArm64);
    925   CodeOffset offset_x86 = CodeOffset::FromOffset(kX86InstructionAlignment, kX86);
    926   CodeOffset offset_x86_64 = CodeOffset::FromOffset(kX86_64InstructionAlignment, kX86_64);
    927   CodeOffset offset_mips = CodeOffset::FromOffset(kMipsInstructionAlignment, kMips);
    928   CodeOffset offset_mips64 = CodeOffset::FromOffset(kMips64InstructionAlignment, kMips64);
    929   EXPECT_EQ(offset_thumb2.Uint32Value(kThumb2), kThumb2InstructionAlignment);
    930   EXPECT_EQ(offset_arm64.Uint32Value(kArm64), kArm64InstructionAlignment);
    931   EXPECT_EQ(offset_x86.Uint32Value(kX86), kX86InstructionAlignment);
    932   EXPECT_EQ(offset_x86_64.Uint32Value(kX86_64), kX86_64InstructionAlignment);
    933   EXPECT_EQ(offset_mips.Uint32Value(kMips), kMipsInstructionAlignment);
    934   EXPECT_EQ(offset_mips64.Uint32Value(kMips64), kMips64InstructionAlignment);
    935 }
    936 
    937 TEST(StackMapTest, TestDeduplicateStackMask) {
    938   ArenaPool pool;
    939   ArenaAllocator arena(&pool);
    940   StackMapStream stream(&arena, kRuntimeISA);
    941 
    942   ArenaBitVector sp_mask(&arena, 0, true);
    943   sp_mask.SetBit(1);
    944   sp_mask.SetBit(4);
    945   stream.BeginStackMapEntry(0, 4, 0x3, &sp_mask, 0, 0);
    946   stream.EndStackMapEntry();
    947   stream.BeginStackMapEntry(0, 8, 0x3, &sp_mask, 0, 0);
    948   stream.EndStackMapEntry();
    949 
    950   size_t size = stream.PrepareForFillIn();
    951   void* memory = arena.Alloc(size, kArenaAllocMisc);
    952   MemoryRegion region(memory, size);
    953   stream.FillInCodeInfo(region);
    954 
    955   CodeInfo code_info(region);
    956   CodeInfoEncoding encoding = code_info.ExtractEncoding();
    957   ASSERT_EQ(2u, code_info.GetNumberOfStackMaps(encoding));
    958 
    959   StackMap stack_map1 = code_info.GetStackMapForNativePcOffset(4, encoding);
    960   StackMap stack_map2 = code_info.GetStackMapForNativePcOffset(8, encoding);
    961   EXPECT_EQ(stack_map1.GetStackMaskIndex(encoding.stack_map.encoding),
    962             stack_map2.GetStackMaskIndex(encoding.stack_map.encoding));
    963 }
    964 
    965 TEST(StackMapTest, TestInvokeInfo) {
    966   ArenaPool pool;
    967   ArenaAllocator arena(&pool);
    968   StackMapStream stream(&arena, kRuntimeISA);
    969 
    970   ArenaBitVector sp_mask(&arena, 0, true);
    971   sp_mask.SetBit(1);
    972   stream.BeginStackMapEntry(0, 4, 0x3, &sp_mask, 0, 0);
    973   stream.AddInvoke(kSuper, 1);
    974   stream.EndStackMapEntry();
    975   stream.BeginStackMapEntry(0, 8, 0x3, &sp_mask, 0, 0);
    976   stream.AddInvoke(kStatic, 3);
    977   stream.EndStackMapEntry();
    978   stream.BeginStackMapEntry(0, 16, 0x3, &sp_mask, 0, 0);
    979   stream.AddInvoke(kDirect, 65535);
    980   stream.EndStackMapEntry();
    981 
    982   const size_t code_info_size = stream.PrepareForFillIn();
    983   MemoryRegion code_info_region(arena.Alloc(code_info_size, kArenaAllocMisc), code_info_size);
    984   stream.FillInCodeInfo(code_info_region);
    985 
    986   const size_t method_info_size = stream.ComputeMethodInfoSize();
    987   MemoryRegion method_info_region(arena.Alloc(method_info_size, kArenaAllocMisc), method_info_size);
    988   stream.FillInMethodInfo(method_info_region);
    989 
    990   CodeInfo code_info(code_info_region);
    991   MethodInfo method_info(method_info_region.begin());
    992   CodeInfoEncoding encoding = code_info.ExtractEncoding();
    993   ASSERT_EQ(3u, code_info.GetNumberOfStackMaps(encoding));
    994 
    995   InvokeInfo invoke1(code_info.GetInvokeInfoForNativePcOffset(4, encoding));
    996   InvokeInfo invoke2(code_info.GetInvokeInfoForNativePcOffset(8, encoding));
    997   InvokeInfo invoke3(code_info.GetInvokeInfoForNativePcOffset(16, encoding));
    998   InvokeInfo invoke_invalid(code_info.GetInvokeInfoForNativePcOffset(12, encoding));
    999   EXPECT_FALSE(invoke_invalid.IsValid());  // No entry for that index.
   1000   EXPECT_TRUE(invoke1.IsValid());
   1001   EXPECT_TRUE(invoke2.IsValid());
   1002   EXPECT_TRUE(invoke3.IsValid());
   1003   EXPECT_EQ(invoke1.GetInvokeType(encoding.invoke_info.encoding), kSuper);
   1004   EXPECT_EQ(invoke1.GetMethodIndex(encoding.invoke_info.encoding, method_info), 1u);
   1005   EXPECT_EQ(invoke1.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 4u);
   1006   EXPECT_EQ(invoke2.GetInvokeType(encoding.invoke_info.encoding), kStatic);
   1007   EXPECT_EQ(invoke2.GetMethodIndex(encoding.invoke_info.encoding, method_info), 3u);
   1008   EXPECT_EQ(invoke2.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 8u);
   1009   EXPECT_EQ(invoke3.GetInvokeType(encoding.invoke_info.encoding), kDirect);
   1010   EXPECT_EQ(invoke3.GetMethodIndex(encoding.invoke_info.encoding, method_info), 65535u);
   1011   EXPECT_EQ(invoke3.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 16u);
   1012 }
   1013 
   1014 }  // namespace art
   1015