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