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 #include "stack_map_stream.h"
19 #include "utils/arena_bit_vector.h"
20
21 #include "gtest/gtest.h"
22
23 namespace art {
24
SameBits(MemoryRegion region,const BitVector & bit_vector)25 static bool SameBits(MemoryRegion region, const BitVector& bit_vector) {
26 for (size_t i = 0; i < region.size_in_bits(); ++i) {
27 if (region.LoadBit(i) != bit_vector.IsBitSet(i)) {
28 return false;
29 }
30 }
31 return true;
32 }
33
34 using Kind = DexRegisterLocation::Kind;
35
TEST(StackMapTest,Test1)36 TEST(StackMapTest, Test1) {
37 ArenaPool pool;
38 ArenaAllocator arena(&pool);
39 StackMapStream stream(&arena);
40
41 ArenaBitVector sp_mask(&arena, 0, false);
42 size_t number_of_dex_registers = 2;
43 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
44 stream.AddDexRegisterEntry(0, Kind::kInStack, 0); // Short location.
45 stream.AddDexRegisterEntry(1, Kind::kConstant, -2); // Short location.
46 stream.EndStackMapEntry();
47
48 size_t size = stream.PrepareForFillIn();
49 void* memory = arena.Alloc(size, kArenaAllocMisc);
50 MemoryRegion region(memory, size);
51 stream.FillIn(region);
52
53 CodeInfo code_info(region);
54 ASSERT_EQ(0u, code_info.GetStackMaskSize());
55 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
56
57 uint32_t number_of_location_catalog_entries =
58 code_info.GetNumberOfDexRegisterLocationCatalogEntries();
59 ASSERT_EQ(2u, number_of_location_catalog_entries);
60 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
61 // The Dex register location catalog contains:
62 // - one 1-byte short Dex register location, and
63 // - one 5-byte large Dex register location.
64 size_t expected_location_catalog_size = 1u + 5u;
65 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
66
67 StackMap stack_map = code_info.GetStackMapAt(0);
68 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
69 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
70 ASSERT_EQ(0u, stack_map.GetDexPc(code_info));
71 ASSERT_EQ(64u, stack_map.GetNativePcOffset(code_info));
72 ASSERT_EQ(0x3u, stack_map.GetRegisterMask(code_info));
73
74 MemoryRegion stack_mask = stack_map.GetStackMask(code_info);
75 ASSERT_TRUE(SameBits(stack_mask, sp_mask));
76
77 ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info));
78 DexRegisterMap dex_register_map =
79 code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
80 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
81 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
82 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
83 // The Dex register map contains:
84 // - one 1-byte live bit mask, and
85 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
86 size_t expected_dex_register_map_size = 1u + 1u;
87 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
88
89 ASSERT_EQ(Kind::kInStack,
90 dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info));
91 ASSERT_EQ(Kind::kConstant,
92 dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info));
93 ASSERT_EQ(Kind::kInStack,
94 dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info));
95 ASSERT_EQ(Kind::kConstantLargeValue,
96 dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info));
97 ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info));
98 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
99
100 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
101 0, number_of_dex_registers, number_of_location_catalog_entries);
102 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
103 1, number_of_dex_registers, number_of_location_catalog_entries);
104 ASSERT_EQ(0u, index0);
105 ASSERT_EQ(1u, index1);
106 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
107 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
108 ASSERT_EQ(Kind::kInStack, location0.GetKind());
109 ASSERT_EQ(Kind::kConstant, location1.GetKind());
110 ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
111 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
112 ASSERT_EQ(0, location0.GetValue());
113 ASSERT_EQ(-2, location1.GetValue());
114
115 ASSERT_FALSE(stack_map.HasInlineInfo(code_info));
116 }
117
TEST(StackMapTest,Test2)118 TEST(StackMapTest, Test2) {
119 ArenaPool pool;
120 ArenaAllocator arena(&pool);
121 StackMapStream stream(&arena);
122
123 ArenaBitVector sp_mask1(&arena, 0, true);
124 sp_mask1.SetBit(2);
125 sp_mask1.SetBit(4);
126 size_t number_of_dex_registers = 2;
127 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 2);
128 stream.AddDexRegisterEntry(0, Kind::kInStack, 0); // Short location.
129 stream.AddDexRegisterEntry(1, Kind::kConstant, -2); // Large location.
130 stream.AddInlineInfoEntry(42);
131 stream.AddInlineInfoEntry(82);
132 stream.EndStackMapEntry();
133
134 ArenaBitVector sp_mask2(&arena, 0, true);
135 sp_mask2.SetBit(3);
136 sp_mask1.SetBit(8);
137 stream.BeginStackMapEntry(1, 128, 0xFF, &sp_mask2, number_of_dex_registers, 0);
138 stream.AddDexRegisterEntry(0, Kind::kInRegister, 18); // Short location.
139 stream.AddDexRegisterEntry(1, Kind::kInFpuRegister, 3); // Short location.
140 stream.EndStackMapEntry();
141
142 size_t size = stream.PrepareForFillIn();
143 void* memory = arena.Alloc(size, kArenaAllocMisc);
144 MemoryRegion region(memory, size);
145 stream.FillIn(region);
146
147 CodeInfo code_info(region);
148 ASSERT_EQ(1u, code_info.GetStackMaskSize());
149 ASSERT_EQ(2u, code_info.GetNumberOfStackMaps());
150
151 uint32_t number_of_location_catalog_entries =
152 code_info.GetNumberOfDexRegisterLocationCatalogEntries();
153 ASSERT_EQ(4u, number_of_location_catalog_entries);
154 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
155 // The Dex register location catalog contains:
156 // - three 1-byte short Dex register locations, and
157 // - one 5-byte large Dex register location.
158 size_t expected_location_catalog_size = 3u * 1u + 5u;
159 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
160
161 // First stack map.
162 {
163 StackMap stack_map = code_info.GetStackMapAt(0);
164 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
165 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
166 ASSERT_EQ(0u, stack_map.GetDexPc(code_info));
167 ASSERT_EQ(64u, stack_map.GetNativePcOffset(code_info));
168 ASSERT_EQ(0x3u, stack_map.GetRegisterMask(code_info));
169
170 MemoryRegion stack_mask = stack_map.GetStackMask(code_info);
171 ASSERT_TRUE(SameBits(stack_mask, sp_mask1));
172
173 ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info));
174 DexRegisterMap dex_register_map =
175 code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
176 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
177 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
178 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
179 // The Dex register map contains:
180 // - one 1-byte live bit mask, and
181 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
182 size_t expected_dex_register_map_size = 1u + 1u;
183 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
184
185 ASSERT_EQ(Kind::kInStack,
186 dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info));
187 ASSERT_EQ(Kind::kConstant,
188 dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info));
189 ASSERT_EQ(Kind::kInStack,
190 dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info));
191 ASSERT_EQ(Kind::kConstantLargeValue,
192 dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info));
193 ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(0, number_of_dex_registers, code_info));
194 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
195
196 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
197 0, number_of_dex_registers, number_of_location_catalog_entries);
198 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
199 1, number_of_dex_registers, number_of_location_catalog_entries);
200 ASSERT_EQ(0u, index0);
201 ASSERT_EQ(1u, index1);
202 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
203 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
204 ASSERT_EQ(Kind::kInStack, location0.GetKind());
205 ASSERT_EQ(Kind::kConstant, location1.GetKind());
206 ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
207 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
208 ASSERT_EQ(0, location0.GetValue());
209 ASSERT_EQ(-2, location1.GetValue());
210
211 ASSERT_TRUE(stack_map.HasInlineInfo(code_info));
212 InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
213 ASSERT_EQ(2u, inline_info.GetDepth());
214 ASSERT_EQ(42u, inline_info.GetMethodReferenceIndexAtDepth(0));
215 ASSERT_EQ(82u, inline_info.GetMethodReferenceIndexAtDepth(1));
216 }
217
218 // Second stack map.
219 {
220 StackMap stack_map = code_info.GetStackMapAt(1);
221 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1u)));
222 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(128u)));
223 ASSERT_EQ(1u, stack_map.GetDexPc(code_info));
224 ASSERT_EQ(128u, stack_map.GetNativePcOffset(code_info));
225 ASSERT_EQ(0xFFu, stack_map.GetRegisterMask(code_info));
226
227 MemoryRegion stack_mask = stack_map.GetStackMask(code_info);
228 ASSERT_TRUE(SameBits(stack_mask, sp_mask2));
229
230 ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info));
231 DexRegisterMap dex_register_map =
232 code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
233 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
234 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
235 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
236 // The Dex register map contains:
237 // - one 1-byte live bit mask, and
238 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
239 size_t expected_dex_register_map_size = 1u + 1u;
240 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
241
242 ASSERT_EQ(Kind::kInRegister,
243 dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info));
244 ASSERT_EQ(Kind::kInFpuRegister,
245 dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info));
246 ASSERT_EQ(Kind::kInRegister,
247 dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info));
248 ASSERT_EQ(Kind::kInFpuRegister,
249 dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info));
250 ASSERT_EQ(18, dex_register_map.GetMachineRegister(0, number_of_dex_registers, code_info));
251 ASSERT_EQ(3, dex_register_map.GetMachineRegister(1, number_of_dex_registers, code_info));
252
253 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
254 0, number_of_dex_registers, number_of_location_catalog_entries);
255 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
256 1, number_of_dex_registers, number_of_location_catalog_entries);
257 ASSERT_EQ(2u, index0);
258 ASSERT_EQ(3u, index1);
259 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
260 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
261 ASSERT_EQ(Kind::kInRegister, location0.GetKind());
262 ASSERT_EQ(Kind::kInFpuRegister, location1.GetKind());
263 ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
264 ASSERT_EQ(Kind::kInFpuRegister, location1.GetInternalKind());
265 ASSERT_EQ(18, location0.GetValue());
266 ASSERT_EQ(3, location1.GetValue());
267
268 ASSERT_FALSE(stack_map.HasInlineInfo(code_info));
269 }
270 }
271
TEST(StackMapTest,TestNonLiveDexRegisters)272 TEST(StackMapTest, TestNonLiveDexRegisters) {
273 ArenaPool pool;
274 ArenaAllocator arena(&pool);
275 StackMapStream stream(&arena);
276
277 ArenaBitVector sp_mask(&arena, 0, false);
278 uint32_t number_of_dex_registers = 2;
279 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
280 stream.AddDexRegisterEntry(0, Kind::kNone, 0); // No location.
281 stream.AddDexRegisterEntry(1, Kind::kConstant, -2); // Large location.
282 stream.EndStackMapEntry();
283
284 size_t size = stream.PrepareForFillIn();
285 void* memory = arena.Alloc(size, kArenaAllocMisc);
286 MemoryRegion region(memory, size);
287 stream.FillIn(region);
288
289 CodeInfo code_info(region);
290 ASSERT_EQ(0u, code_info.GetStackMaskSize());
291 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
292
293 uint32_t number_of_location_catalog_entries =
294 code_info.GetNumberOfDexRegisterLocationCatalogEntries();
295 ASSERT_EQ(1u, number_of_location_catalog_entries);
296 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
297 // The Dex register location catalog contains:
298 // - one 5-byte large Dex register location.
299 size_t expected_location_catalog_size = 5u;
300 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
301
302 StackMap stack_map = code_info.GetStackMapAt(0);
303 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
304 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
305 ASSERT_EQ(0u, stack_map.GetDexPc(code_info));
306 ASSERT_EQ(64u, stack_map.GetNativePcOffset(code_info));
307 ASSERT_EQ(0x3u, stack_map.GetRegisterMask(code_info));
308
309 ASSERT_TRUE(stack_map.HasDexRegisterMap(code_info));
310 DexRegisterMap dex_register_map =
311 code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
312 ASSERT_FALSE(dex_register_map.IsDexRegisterLive(0));
313 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
314 ASSERT_EQ(1u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
315 // The Dex register map contains:
316 // - one 1-byte live bit mask.
317 // No space is allocated for the sole location catalog entry index, as it is useless.
318 size_t expected_dex_register_map_size = 1u + 0u;
319 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
320
321 ASSERT_EQ(Kind::kNone,
322 dex_register_map.GetLocationKind(0, number_of_dex_registers, code_info));
323 ASSERT_EQ(Kind::kConstant,
324 dex_register_map.GetLocationKind(1, number_of_dex_registers, code_info));
325 ASSERT_EQ(Kind::kNone,
326 dex_register_map.GetLocationInternalKind(0, number_of_dex_registers, code_info));
327 ASSERT_EQ(Kind::kConstantLargeValue,
328 dex_register_map.GetLocationInternalKind(1, number_of_dex_registers, code_info));
329 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info));
330
331 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
332 0, number_of_dex_registers, number_of_location_catalog_entries);
333 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
334 1, number_of_dex_registers, number_of_location_catalog_entries);
335 ASSERT_EQ(DexRegisterLocationCatalog::kNoLocationEntryIndex, index0);
336 ASSERT_EQ(0u, index1);
337 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
338 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
339 ASSERT_EQ(Kind::kNone, location0.GetKind());
340 ASSERT_EQ(Kind::kConstant, location1.GetKind());
341 ASSERT_EQ(Kind::kNone, location0.GetInternalKind());
342 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
343 ASSERT_EQ(0, location0.GetValue());
344 ASSERT_EQ(-2, location1.GetValue());
345
346 ASSERT_FALSE(stack_map.HasInlineInfo(code_info));
347 }
348
349 // Generate a stack map whose dex register offset is
350 // StackMap::kNoDexRegisterMapSmallEncoding, and ensure we do
351 // not treat it as kNoDexRegisterMap.
TEST(StackMapTest,DexRegisterMapOffsetOverflow)352 TEST(StackMapTest, DexRegisterMapOffsetOverflow) {
353 ArenaPool pool;
354 ArenaAllocator arena(&pool);
355 StackMapStream stream(&arena);
356
357 ArenaBitVector sp_mask(&arena, 0, false);
358 uint32_t number_of_dex_registers = 1024;
359 // Create the first stack map (and its Dex register map).
360 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
361 uint32_t number_of_dex_live_registers_in_dex_register_map_0 = number_of_dex_registers - 8;
362 for (uint32_t i = 0; i < number_of_dex_live_registers_in_dex_register_map_0; ++i) {
363 // Use two different Dex register locations to populate this map,
364 // as using a single value (in the whole CodeInfo object) would
365 // make this Dex register mapping data empty (see
366 // art::DexRegisterMap::SingleEntrySizeInBits).
367 stream.AddDexRegisterEntry(i, Kind::kConstant, i % 2); // Short location.
368 }
369 stream.EndStackMapEntry();
370 // Create the second stack map (and its Dex register map).
371 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
372 for (uint32_t i = 0; i < number_of_dex_registers; ++i) {
373 stream.AddDexRegisterEntry(i, Kind::kConstant, 0); // Short location.
374 }
375 stream.EndStackMapEntry();
376
377 size_t size = stream.PrepareForFillIn();
378 void* memory = arena.Alloc(size, kArenaAllocMisc);
379 MemoryRegion region(memory, size);
380 stream.FillIn(region);
381
382 CodeInfo code_info(region);
383 // The location catalog contains two entries (DexRegisterLocation(kConstant, 0)
384 // and DexRegisterLocation(kConstant, 1)), therefore the location catalog index
385 // has a size of 1 bit.
386 uint32_t number_of_location_catalog_entries =
387 code_info.GetNumberOfDexRegisterLocationCatalogEntries();
388 ASSERT_EQ(2u, number_of_location_catalog_entries);
389 ASSERT_EQ(1u, DexRegisterMap::SingleEntrySizeInBits(number_of_location_catalog_entries));
390
391 // The first Dex register map contains:
392 // - a live register bit mask for 1024 registers (that is, 128 bytes of
393 // data); and
394 // - Dex register mapping information for 1016 1-bit Dex (live) register
395 // locations (that is, 127 bytes of data).
396 // Hence it has a size of 255 bytes, and therefore...
397 ASSERT_EQ(128u, DexRegisterMap::GetLiveBitMaskSize(number_of_dex_registers));
398 StackMap stack_map0 = code_info.GetStackMapAt(0);
399 DexRegisterMap dex_register_map0 =
400 code_info.GetDexRegisterMapOf(stack_map0, number_of_dex_registers);
401 ASSERT_EQ(127u, dex_register_map0.GetLocationMappingDataSize(number_of_dex_registers,
402 number_of_location_catalog_entries));
403 ASSERT_EQ(255u, dex_register_map0.Size());
404
405 StackMap stack_map1 = code_info.GetStackMapAt(1);
406 ASSERT_TRUE(stack_map1.HasDexRegisterMap(code_info));
407 // ...the offset of the second Dex register map (relative to the
408 // beginning of the Dex register maps region) is 255 (i.e.,
409 // kNoDexRegisterMapSmallEncoding).
410 ASSERT_NE(stack_map1.GetDexRegisterMapOffset(code_info), StackMap::kNoDexRegisterMap);
411 ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(code_info), 0xFFu);
412 }
413
TEST(StackMapTest,TestShareDexRegisterMap)414 TEST(StackMapTest, TestShareDexRegisterMap) {
415 ArenaPool pool;
416 ArenaAllocator arena(&pool);
417 StackMapStream stream(&arena);
418
419 ArenaBitVector sp_mask(&arena, 0, false);
420 uint32_t number_of_dex_registers = 2;
421 // First stack map.
422 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
423 stream.AddDexRegisterEntry(0, Kind::kInRegister, 0); // Short location.
424 stream.AddDexRegisterEntry(1, Kind::kConstant, -2); // Large location.
425 stream.EndStackMapEntry();
426 // Second stack map, which should share the same dex register map.
427 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
428 stream.AddDexRegisterEntry(0, Kind::kInRegister, 0); // Short location.
429 stream.AddDexRegisterEntry(1, Kind::kConstant, -2); // Large location.
430 stream.EndStackMapEntry();
431 // Third stack map (doesn't share the dex register map).
432 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
433 stream.AddDexRegisterEntry(0, Kind::kInRegister, 2); // Short location.
434 stream.AddDexRegisterEntry(1, Kind::kConstant, -2); // Large location.
435 stream.EndStackMapEntry();
436
437 size_t size = stream.PrepareForFillIn();
438 void* memory = arena.Alloc(size, kArenaAllocMisc);
439 MemoryRegion region(memory, size);
440 stream.FillIn(region);
441
442 CodeInfo ci(region);
443 // Verify first stack map.
444 StackMap sm0 = ci.GetStackMapAt(0);
445 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, number_of_dex_registers);
446 ASSERT_EQ(0, dex_registers0.GetMachineRegister(0, number_of_dex_registers, ci));
447 ASSERT_EQ(-2, dex_registers0.GetConstant(1, number_of_dex_registers, ci));
448
449 // Verify second stack map.
450 StackMap sm1 = ci.GetStackMapAt(1);
451 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapOf(sm1, number_of_dex_registers);
452 ASSERT_EQ(0, dex_registers1.GetMachineRegister(0, number_of_dex_registers, ci));
453 ASSERT_EQ(-2, dex_registers1.GetConstant(1, number_of_dex_registers, ci));
454
455 // Verify third stack map.
456 StackMap sm2 = ci.GetStackMapAt(2);
457 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapOf(sm2, number_of_dex_registers);
458 ASSERT_EQ(2, dex_registers2.GetMachineRegister(0, number_of_dex_registers, ci));
459 ASSERT_EQ(-2, dex_registers2.GetConstant(1, number_of_dex_registers, ci));
460
461 // Verify dex register map offsets.
462 ASSERT_EQ(sm0.GetDexRegisterMapOffset(ci), sm1.GetDexRegisterMapOffset(ci));
463 ASSERT_NE(sm0.GetDexRegisterMapOffset(ci), sm2.GetDexRegisterMapOffset(ci));
464 ASSERT_NE(sm1.GetDexRegisterMapOffset(ci), sm2.GetDexRegisterMapOffset(ci));
465 }
466
TEST(StackMapTest,TestNoDexRegisterMap)467 TEST(StackMapTest, TestNoDexRegisterMap) {
468 ArenaPool pool;
469 ArenaAllocator arena(&pool);
470 StackMapStream stream(&arena);
471
472 ArenaBitVector sp_mask(&arena, 0, false);
473 uint32_t number_of_dex_registers = 0;
474 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
475 stream.EndStackMapEntry();
476
477 size_t size = stream.PrepareForFillIn();
478 void* memory = arena.Alloc(size, kArenaAllocMisc);
479 MemoryRegion region(memory, size);
480 stream.FillIn(region);
481
482 CodeInfo code_info(region);
483 ASSERT_EQ(0u, code_info.GetStackMaskSize());
484 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps());
485
486 uint32_t number_of_location_catalog_entries =
487 code_info.GetNumberOfDexRegisterLocationCatalogEntries();
488 ASSERT_EQ(0u, number_of_location_catalog_entries);
489 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog();
490 ASSERT_EQ(0u, location_catalog.Size());
491
492 StackMap stack_map = code_info.GetStackMapAt(0);
493 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0)));
494 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64)));
495 ASSERT_EQ(0u, stack_map.GetDexPc(code_info));
496 ASSERT_EQ(64u, stack_map.GetNativePcOffset(code_info));
497 ASSERT_EQ(0x3u, stack_map.GetRegisterMask(code_info));
498
499 ASSERT_FALSE(stack_map.HasDexRegisterMap(code_info));
500 ASSERT_FALSE(stack_map.HasInlineInfo(code_info));
501 }
502
503 } // namespace art
504