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