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