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
24namespace 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.
28static 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
44using Kind = DexRegisterLocation::Kind;
45
46TEST(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
127TEST(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
412TEST(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.
491TEST(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
554TEST(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
612TEST(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
661TEST(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