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