blob: 22810ea4f7ebc613cc24668e4669e1cbcf630392 [file] [log] [blame]
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +01001/*
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"
Mathieu Chartiere5d80f82015-10-15 17:47:48 -070018
Nicolas Geoffray5d37c152017-01-12 13:25:19 +000019#include "art_method.h"
Mathieu Chartiere5d80f82015-10-15 17:47:48 -070020#include "base/arena_bit_vector.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010021#include "stack_map_stream.h"
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010022
23#include "gtest/gtest.h"
24
25namespace art {
26
David Srbecky09ed0982016-02-12 21:58:43 +000027// Check that the stack mask of given stack map is identical
28// to the given bit vector. Returns true if they are same.
29static bool CheckStackMask(
30 const StackMap& stack_map,
31 StackMapEncoding& encoding,
32 const BitVector& bit_vector) {
33 int number_of_bits = stack_map.GetNumberOfStackMaskBits(encoding);
34 if (bit_vector.GetHighestBitSet() >= number_of_bits) {
35 return false;
36 }
37 for (int i = 0; i < number_of_bits; ++i) {
38 if (stack_map.GetStackMaskBit(encoding, i) != bit_vector.IsBitSet(i)) {
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010039 return false;
40 }
41 }
42 return true;
43}
44
Roland Levillaina552e1c2015-03-26 15:01:03 +000045using Kind = DexRegisterLocation::Kind;
46
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010047TEST(StackMapTest, Test1) {
48 ArenaPool pool;
49 ArenaAllocator arena(&pool);
Nicolas Geoffray39468442014-09-02 15:17:15 +010050 StackMapStream stream(&arena);
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010051
52 ArenaBitVector sp_mask(&arena, 0, false);
Roland Levillain12baf472015-03-05 12:41:42 +000053 size_t number_of_dex_registers = 2;
Calin Juravle4f46ac52015-04-23 18:47:21 +010054 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +010055 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
56 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Short location.
Calin Juravle4f46ac52015-04-23 18:47:21 +010057 stream.EndStackMapEntry();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010058
Calin Juravle4f46ac52015-04-23 18:47:21 +010059 size_t size = stream.PrepareForFillIn();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010060 void* memory = arena.Alloc(size, kArenaAllocMisc);
61 MemoryRegion region(memory, size);
62 stream.FillIn(region);
63
Nicolas Geoffray39468442014-09-02 15:17:15 +010064 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +000065 CodeInfoEncoding encoding = code_info.ExtractEncoding();
66 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010067
David Srbecky09ed0982016-02-12 21:58:43 +000068 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
69 ASSERT_EQ(2u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +010070 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +000071 // The Dex register location catalog contains:
72 // - one 1-byte short Dex register location, and
73 // - one 5-byte large Dex register location.
74 size_t expected_location_catalog_size = 1u + 5u;
75 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
76
David Brazdilf677ebf2015-05-29 16:29:43 +010077 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
78 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
79 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
David Srbecky09ed0982016-02-12 21:58:43 +000080 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map_encoding));
81 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map_encoding));
82 ASSERT_EQ(0x3u, stack_map.GetRegisterMask(encoding.stack_map_encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010083
David Srbecky09ed0982016-02-12 21:58:43 +000084 ASSERT_TRUE(CheckStackMask(stack_map, encoding.stack_map_encoding, sp_mask));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +010085
David Srbecky09ed0982016-02-12 21:58:43 +000086 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +000087 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +010088 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +000089 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
90 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
91 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
92 // The Dex register map contains:
93 // - one 1-byte live bit mask, and
94 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
95 size_t expected_dex_register_map_size = 1u + 1u;
96 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
97
David Brazdilf677ebf2015-05-29 16:29:43 +010098 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(
99 0, number_of_dex_registers, code_info, encoding));
100 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
101 1, number_of_dex_registers, code_info, encoding));
102 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
103 0, number_of_dex_registers, code_info, encoding));
104 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
105 1, number_of_dex_registers, code_info, encoding));
106 ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
107 0, number_of_dex_registers, code_info, encoding));
108 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000109
110 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000111 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000112 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000113 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000114 ASSERT_EQ(0u, index0);
115 ASSERT_EQ(1u, index1);
116 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
117 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
118 ASSERT_EQ(Kind::kInStack, location0.GetKind());
119 ASSERT_EQ(Kind::kConstant, location1.GetKind());
120 ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
121 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000122 ASSERT_EQ(0, location0.GetValue());
123 ASSERT_EQ(-2, location1.GetValue());
Roland Levillain12baf472015-03-05 12:41:42 +0000124
David Srbecky09ed0982016-02-12 21:58:43 +0000125 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map_encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100126}
127
128TEST(StackMapTest, Test2) {
129 ArenaPool pool;
130 ArenaAllocator arena(&pool);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100131 StackMapStream stream(&arena);
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000132 ArtMethod art_method;
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100133
134 ArenaBitVector sp_mask1(&arena, 0, true);
135 sp_mask1.SetBit(2);
136 sp_mask1.SetBit(4);
Roland Levillain12baf472015-03-05 12:41:42 +0000137 size_t number_of_dex_registers = 2;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100138 size_t number_of_dex_registers_in_inline_info = 0;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100139 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100140 stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location.
141 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000142 stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100143 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000144 stream.BeginInlineInfoEntry(&art_method, 2, number_of_dex_registers_in_inline_info);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100145 stream.EndInlineInfoEntry();
Calin Juravle4f46ac52015-04-23 18:47:21 +0100146 stream.EndStackMapEntry();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100147
148 ArenaBitVector sp_mask2(&arena, 0, true);
149 sp_mask2.SetBit(3);
David Brazdilf10a25f2015-06-02 14:29:52 +0100150 sp_mask2.SetBit(8);
Calin Juravle4f46ac52015-04-23 18:47:21 +0100151 stream.BeginStackMapEntry(1, 128, 0xFF, &sp_mask2, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100152 stream.AddDexRegisterEntry(Kind::kInRegister, 18); // Short location.
153 stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3); // Short location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100154 stream.EndStackMapEntry();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100155
David Brazdild9cb68e2015-08-25 13:52:43 +0100156 ArenaBitVector sp_mask3(&arena, 0, true);
157 sp_mask3.SetBit(1);
158 sp_mask3.SetBit(5);
159 stream.BeginStackMapEntry(2, 192, 0xAB, &sp_mask3, number_of_dex_registers, 0);
160 stream.AddDexRegisterEntry(Kind::kInRegister, 6); // Short location.
161 stream.AddDexRegisterEntry(Kind::kInRegisterHigh, 8); // Short location.
162 stream.EndStackMapEntry();
163
164 ArenaBitVector sp_mask4(&arena, 0, true);
165 sp_mask4.SetBit(6);
166 sp_mask4.SetBit(7);
167 stream.BeginStackMapEntry(3, 256, 0xCD, &sp_mask4, number_of_dex_registers, 0);
168 stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3); // Short location, same in stack map 2.
169 stream.AddDexRegisterEntry(Kind::kInFpuRegisterHigh, 1); // Short location.
170 stream.EndStackMapEntry();
171
Calin Juravle4f46ac52015-04-23 18:47:21 +0100172 size_t size = stream.PrepareForFillIn();
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100173 void* memory = arena.Alloc(size, kArenaAllocMisc);
174 MemoryRegion region(memory, size);
175 stream.FillIn(region);
176
Nicolas Geoffray39468442014-09-02 15:17:15 +0100177 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000178 CodeInfoEncoding encoding = code_info.ExtractEncoding();
179 ASSERT_EQ(4u, code_info.GetNumberOfStackMaps(encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100180
David Srbecky09ed0982016-02-12 21:58:43 +0000181 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
182 ASSERT_EQ(7u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100183 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000184 // The Dex register location catalog contains:
David Brazdild9cb68e2015-08-25 13:52:43 +0100185 // - six 1-byte short Dex register locations, and
Roland Levillaina552e1c2015-03-26 15:01:03 +0000186 // - one 5-byte large Dex register location.
David Brazdild9cb68e2015-08-25 13:52:43 +0100187 size_t expected_location_catalog_size = 6u * 1u + 5u;
Roland Levillaina552e1c2015-03-26 15:01:03 +0000188 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
189
Roland Levillain12baf472015-03-05 12:41:42 +0000190 // First stack map.
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000191 {
David Brazdilf677ebf2015-05-29 16:29:43 +0100192 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
193 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
194 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
David Srbecky09ed0982016-02-12 21:58:43 +0000195 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map_encoding));
196 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map_encoding));
197 ASSERT_EQ(0x3u, stack_map.GetRegisterMask(encoding.stack_map_encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100198
David Srbecky09ed0982016-02-12 21:58:43 +0000199 ASSERT_TRUE(CheckStackMask(stack_map, encoding.stack_map_encoding, sp_mask1));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100200
David Srbecky09ed0982016-02-12 21:58:43 +0000201 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000202 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100203 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000204 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
205 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
206 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
207 // The Dex register map contains:
208 // - one 1-byte live bit mask, and
209 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
210 size_t expected_dex_register_map_size = 1u + 1u;
211 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
212
David Brazdilf677ebf2015-05-29 16:29:43 +0100213 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(
214 0, number_of_dex_registers, code_info, encoding));
215 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
216 1, number_of_dex_registers, code_info, encoding));
217 ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationInternalKind(
218 0, number_of_dex_registers, code_info, encoding));
219 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
220 1, number_of_dex_registers, code_info, encoding));
221 ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(
222 0, number_of_dex_registers, code_info, encoding));
223 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000224
225 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000226 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000227 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000228 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000229 ASSERT_EQ(0u, index0);
230 ASSERT_EQ(1u, index1);
231 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
232 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
233 ASSERT_EQ(Kind::kInStack, location0.GetKind());
234 ASSERT_EQ(Kind::kConstant, location1.GetKind());
235 ASSERT_EQ(Kind::kInStack, location0.GetInternalKind());
236 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000237 ASSERT_EQ(0, location0.GetValue());
238 ASSERT_EQ(-2, location1.GetValue());
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100239
David Srbecky09ed0982016-02-12 21:58:43 +0000240 ASSERT_TRUE(stack_map.HasInlineInfo(encoding.stack_map_encoding));
David Brazdilf677ebf2015-05-29 16:29:43 +0100241 InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
David Srbecky61b28a12016-02-25 21:55:03 +0000242 ASSERT_EQ(2u, inline_info.GetDepth(encoding.inline_info_encoding));
David Srbecky61b28a12016-02-25 21:55:03 +0000243 ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(encoding.inline_info_encoding, 0));
244 ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(encoding.inline_info_encoding, 1));
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000245 ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 0));
246 ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 1));
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000247 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100248
Roland Levillain12baf472015-03-05 12:41:42 +0000249 // Second stack map.
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000250 {
David Brazdilf677ebf2015-05-29 16:29:43 +0100251 StackMap stack_map = code_info.GetStackMapAt(1, encoding);
252 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1u, encoding)));
253 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(128u, encoding)));
David Srbecky09ed0982016-02-12 21:58:43 +0000254 ASSERT_EQ(1u, stack_map.GetDexPc(encoding.stack_map_encoding));
255 ASSERT_EQ(128u, stack_map.GetNativePcOffset(encoding.stack_map_encoding));
256 ASSERT_EQ(0xFFu, stack_map.GetRegisterMask(encoding.stack_map_encoding));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100257
David Srbecky09ed0982016-02-12 21:58:43 +0000258 ASSERT_TRUE(CheckStackMask(stack_map, encoding.stack_map_encoding, sp_mask2));
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100259
David Srbecky09ed0982016-02-12 21:58:43 +0000260 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000261 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100262 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000263 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
264 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
265 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
266 // The Dex register map contains:
267 // - one 1-byte live bit mask, and
268 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
269 size_t expected_dex_register_map_size = 1u + 1u;
270 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
271
David Brazdilf677ebf2015-05-29 16:29:43 +0100272 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(
273 0, number_of_dex_registers, code_info, encoding));
274 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
275 1, number_of_dex_registers, code_info, encoding));
276 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
277 0, number_of_dex_registers, code_info, encoding));
278 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
279 1, number_of_dex_registers, code_info, encoding));
280 ASSERT_EQ(18, dex_register_map.GetMachineRegister(
281 0, number_of_dex_registers, code_info, encoding));
282 ASSERT_EQ(3, dex_register_map.GetMachineRegister(
283 1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000284
285 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000286 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000287 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000288 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000289 ASSERT_EQ(2u, index0);
290 ASSERT_EQ(3u, index1);
291 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
292 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
293 ASSERT_EQ(Kind::kInRegister, location0.GetKind());
294 ASSERT_EQ(Kind::kInFpuRegister, location1.GetKind());
295 ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
296 ASSERT_EQ(Kind::kInFpuRegister, location1.GetInternalKind());
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000297 ASSERT_EQ(18, location0.GetValue());
298 ASSERT_EQ(3, location1.GetValue());
Roland Levillain12baf472015-03-05 12:41:42 +0000299
David Srbecky09ed0982016-02-12 21:58:43 +0000300 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map_encoding));
Roland Levillaina2d8ec62015-03-12 15:25:29 +0000301 }
David Brazdild9cb68e2015-08-25 13:52:43 +0100302
303 // Third stack map.
304 {
305 StackMap stack_map = code_info.GetStackMapAt(2, encoding);
306 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(2u, encoding)));
307 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(192u, encoding)));
David Srbecky09ed0982016-02-12 21:58:43 +0000308 ASSERT_EQ(2u, stack_map.GetDexPc(encoding.stack_map_encoding));
309 ASSERT_EQ(192u, stack_map.GetNativePcOffset(encoding.stack_map_encoding));
310 ASSERT_EQ(0xABu, stack_map.GetRegisterMask(encoding.stack_map_encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100311
David Srbecky09ed0982016-02-12 21:58:43 +0000312 ASSERT_TRUE(CheckStackMask(stack_map, encoding.stack_map_encoding, sp_mask3));
David Brazdild9cb68e2015-08-25 13:52:43 +0100313
David Srbecky09ed0982016-02-12 21:58:43 +0000314 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100315 DexRegisterMap dex_register_map =
316 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
317 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
318 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
319 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
320 // The Dex register map contains:
321 // - one 1-byte live bit mask, and
322 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
323 size_t expected_dex_register_map_size = 1u + 1u;
324 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
325
326 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(
327 0, number_of_dex_registers, code_info, encoding));
328 ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationKind(
329 1, number_of_dex_registers, code_info, encoding));
330 ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationInternalKind(
331 0, number_of_dex_registers, code_info, encoding));
332 ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationInternalKind(
333 1, number_of_dex_registers, code_info, encoding));
334 ASSERT_EQ(6, dex_register_map.GetMachineRegister(
335 0, number_of_dex_registers, code_info, encoding));
336 ASSERT_EQ(8, dex_register_map.GetMachineRegister(
337 1, number_of_dex_registers, code_info, encoding));
338
339 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000340 0, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100341 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000342 1, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100343 ASSERT_EQ(4u, index0);
344 ASSERT_EQ(5u, index1);
345 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
346 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
347 ASSERT_EQ(Kind::kInRegister, location0.GetKind());
348 ASSERT_EQ(Kind::kInRegisterHigh, location1.GetKind());
349 ASSERT_EQ(Kind::kInRegister, location0.GetInternalKind());
350 ASSERT_EQ(Kind::kInRegisterHigh, location1.GetInternalKind());
351 ASSERT_EQ(6, location0.GetValue());
352 ASSERT_EQ(8, location1.GetValue());
353
David Srbecky09ed0982016-02-12 21:58:43 +0000354 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map_encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100355 }
356
357 // Fourth stack map.
358 {
359 StackMap stack_map = code_info.GetStackMapAt(3, encoding);
360 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(3u, encoding)));
361 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(256u, encoding)));
David Srbecky09ed0982016-02-12 21:58:43 +0000362 ASSERT_EQ(3u, stack_map.GetDexPc(encoding.stack_map_encoding));
363 ASSERT_EQ(256u, stack_map.GetNativePcOffset(encoding.stack_map_encoding));
364 ASSERT_EQ(0xCDu, stack_map.GetRegisterMask(encoding.stack_map_encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100365
David Srbecky09ed0982016-02-12 21:58:43 +0000366 ASSERT_TRUE(CheckStackMask(stack_map, encoding.stack_map_encoding, sp_mask4));
David Brazdild9cb68e2015-08-25 13:52:43 +0100367
David Srbecky09ed0982016-02-12 21:58:43 +0000368 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100369 DexRegisterMap dex_register_map =
370 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
371 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
372 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
373 ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
374 // The Dex register map contains:
375 // - one 1-byte live bit mask, and
376 // - one 1-byte set of location catalog entry indices composed of two 2-bit values.
377 size_t expected_dex_register_map_size = 1u + 1u;
378 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
379
380 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(
381 0, number_of_dex_registers, code_info, encoding));
382 ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationKind(
383 1, number_of_dex_registers, code_info, encoding));
384 ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationInternalKind(
385 0, number_of_dex_registers, code_info, encoding));
386 ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationInternalKind(
387 1, number_of_dex_registers, code_info, encoding));
388 ASSERT_EQ(3, dex_register_map.GetMachineRegister(
389 0, number_of_dex_registers, code_info, encoding));
390 ASSERT_EQ(1, dex_register_map.GetMachineRegister(
391 1, number_of_dex_registers, code_info, encoding));
392
393 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000394 0, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100395 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000396 1, number_of_dex_registers, number_of_catalog_entries);
David Brazdild9cb68e2015-08-25 13:52:43 +0100397 ASSERT_EQ(3u, index0); // Shared with second stack map.
398 ASSERT_EQ(6u, index1);
399 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
400 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
401 ASSERT_EQ(Kind::kInFpuRegister, location0.GetKind());
402 ASSERT_EQ(Kind::kInFpuRegisterHigh, location1.GetKind());
403 ASSERT_EQ(Kind::kInFpuRegister, location0.GetInternalKind());
404 ASSERT_EQ(Kind::kInFpuRegisterHigh, location1.GetInternalKind());
405 ASSERT_EQ(3, location0.GetValue());
406 ASSERT_EQ(1, location1.GetValue());
407
David Srbecky09ed0982016-02-12 21:58:43 +0000408 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map_encoding));
David Brazdild9cb68e2015-08-25 13:52:43 +0100409 }
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100410}
411
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000412TEST(StackMapTest, TestNonLiveDexRegisters) {
413 ArenaPool pool;
414 ArenaAllocator arena(&pool);
415 StackMapStream stream(&arena);
416
417 ArenaBitVector sp_mask(&arena, 0, false);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000418 uint32_t number_of_dex_registers = 2;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100419 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100420 stream.AddDexRegisterEntry(Kind::kNone, 0); // No location.
421 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100422 stream.EndStackMapEntry();
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000423
Calin Juravle4f46ac52015-04-23 18:47:21 +0100424 size_t size = stream.PrepareForFillIn();
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000425 void* memory = arena.Alloc(size, kArenaAllocMisc);
426 MemoryRegion region(memory, size);
427 stream.FillIn(region);
428
429 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000430 CodeInfoEncoding encoding = code_info.ExtractEncoding();
431 ASSERT_EQ(1u, code_info.GetNumberOfStackMaps(encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000432
David Srbecky09ed0982016-02-12 21:58:43 +0000433 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
434 ASSERT_EQ(1u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100435 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000436 // The Dex register location catalog contains:
437 // - one 5-byte large Dex register location.
438 size_t expected_location_catalog_size = 5u;
439 ASSERT_EQ(expected_location_catalog_size, location_catalog.Size());
440
David Brazdilf677ebf2015-05-29 16:29:43 +0100441 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
442 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
443 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
David Srbecky09ed0982016-02-12 21:58:43 +0000444 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map_encoding));
445 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map_encoding));
446 ASSERT_EQ(0x3u, stack_map.GetRegisterMask(encoding.stack_map_encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000447
David Srbecky09ed0982016-02-12 21:58:43 +0000448 ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000449 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100450 code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000451 ASSERT_FALSE(dex_register_map.IsDexRegisterLive(0));
452 ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
453 ASSERT_EQ(1u, dex_register_map.GetNumberOfLiveDexRegisters(number_of_dex_registers));
454 // The Dex register map contains:
455 // - one 1-byte live bit mask.
456 // No space is allocated for the sole location catalog entry index, as it is useless.
457 size_t expected_dex_register_map_size = 1u + 0u;
458 ASSERT_EQ(expected_dex_register_map_size, dex_register_map.Size());
459
David Brazdilf677ebf2015-05-29 16:29:43 +0100460 ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationKind(
461 0, number_of_dex_registers, code_info, encoding));
462 ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(
463 1, number_of_dex_registers, code_info, encoding));
464 ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationInternalKind(
465 0, number_of_dex_registers, code_info, encoding));
466 ASSERT_EQ(Kind::kConstantLargeValue, dex_register_map.GetLocationInternalKind(
467 1, number_of_dex_registers, code_info, encoding));
468 ASSERT_EQ(-2, dex_register_map.GetConstant(1, number_of_dex_registers, code_info, encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000469
470 size_t index0 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000471 0, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000472 size_t index1 = dex_register_map.GetLocationCatalogEntryIndex(
David Srbecky09ed0982016-02-12 21:58:43 +0000473 1, number_of_dex_registers, number_of_catalog_entries);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000474 ASSERT_EQ(DexRegisterLocationCatalog::kNoLocationEntryIndex, index0);
475 ASSERT_EQ(0u, index1);
476 DexRegisterLocation location0 = location_catalog.GetDexRegisterLocation(index0);
477 DexRegisterLocation location1 = location_catalog.GetDexRegisterLocation(index1);
478 ASSERT_EQ(Kind::kNone, location0.GetKind());
479 ASSERT_EQ(Kind::kConstant, location1.GetKind());
480 ASSERT_EQ(Kind::kNone, location0.GetInternalKind());
481 ASSERT_EQ(Kind::kConstantLargeValue, location1.GetInternalKind());
482 ASSERT_EQ(0, location0.GetValue());
483 ASSERT_EQ(-2, location1.GetValue());
484
David Srbecky09ed0982016-02-12 21:58:43 +0000485 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map_encoding));
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000486}
487
488// Generate a stack map whose dex register offset is
489// StackMap::kNoDexRegisterMapSmallEncoding, and ensure we do
490// not treat it as kNoDexRegisterMap.
491TEST(StackMapTest, DexRegisterMapOffsetOverflow) {
492 ArenaPool pool;
493 ArenaAllocator arena(&pool);
494 StackMapStream stream(&arena);
495
496 ArenaBitVector sp_mask(&arena, 0, false);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000497 uint32_t number_of_dex_registers = 1024;
498 // Create the first stack map (and its Dex register map).
Calin Juravle4f46ac52015-04-23 18:47:21 +0100499 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000500 uint32_t number_of_dex_live_registers_in_dex_register_map_0 = number_of_dex_registers - 8;
501 for (uint32_t i = 0; i < number_of_dex_live_registers_in_dex_register_map_0; ++i) {
502 // Use two different Dex register locations to populate this map,
503 // as using a single value (in the whole CodeInfo object) would
504 // make this Dex register mapping data empty (see
505 // art::DexRegisterMap::SingleEntrySizeInBits).
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100506 stream.AddDexRegisterEntry(Kind::kConstant, i % 2); // Short location.
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000507 }
Calin Juravle4f46ac52015-04-23 18:47:21 +0100508 stream.EndStackMapEntry();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000509 // Create the second stack map (and its Dex register map).
Calin Juravle4f46ac52015-04-23 18:47:21 +0100510 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000511 for (uint32_t i = 0; i < number_of_dex_registers; ++i) {
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100512 stream.AddDexRegisterEntry(Kind::kConstant, 0); // Short location.
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000513 }
Calin Juravle4f46ac52015-04-23 18:47:21 +0100514 stream.EndStackMapEntry();
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000515
Calin Juravle4f46ac52015-04-23 18:47:21 +0100516 size_t size = stream.PrepareForFillIn();
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000517 void* memory = arena.Alloc(size, kArenaAllocMisc);
518 MemoryRegion region(memory, size);
519 stream.FillIn(region);
520
521 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000522 CodeInfoEncoding encoding = code_info.ExtractEncoding();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000523 // The location catalog contains two entries (DexRegisterLocation(kConstant, 0)
524 // and DexRegisterLocation(kConstant, 1)), therefore the location catalog index
525 // has a size of 1 bit.
David Srbecky09ed0982016-02-12 21:58:43 +0000526 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
527 ASSERT_EQ(2u, number_of_catalog_entries);
528 ASSERT_EQ(1u, DexRegisterMap::SingleEntrySizeInBits(number_of_catalog_entries));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000529
530 // The first Dex register map contains:
531 // - a live register bit mask for 1024 registers (that is, 128 bytes of
532 // data); and
533 // - Dex register mapping information for 1016 1-bit Dex (live) register
534 // locations (that is, 127 bytes of data).
535 // Hence it has a size of 255 bytes, and therefore...
536 ASSERT_EQ(128u, DexRegisterMap::GetLiveBitMaskSize(number_of_dex_registers));
David Brazdilf677ebf2015-05-29 16:29:43 +0100537 StackMap stack_map0 = code_info.GetStackMapAt(0, encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000538 DexRegisterMap dex_register_map0 =
David Brazdilf677ebf2015-05-29 16:29:43 +0100539 code_info.GetDexRegisterMapOf(stack_map0, encoding, number_of_dex_registers);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000540 ASSERT_EQ(127u, dex_register_map0.GetLocationMappingDataSize(number_of_dex_registers,
David Srbecky09ed0982016-02-12 21:58:43 +0000541 number_of_catalog_entries));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000542 ASSERT_EQ(255u, dex_register_map0.Size());
543
David Brazdilf677ebf2015-05-29 16:29:43 +0100544 StackMap stack_map1 = code_info.GetStackMapAt(1, encoding);
David Srbecky09ed0982016-02-12 21:58:43 +0000545 ASSERT_TRUE(stack_map1.HasDexRegisterMap(encoding.stack_map_encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000546 // ...the offset of the second Dex register map (relative to the
547 // beginning of the Dex register maps region) is 255 (i.e.,
548 // kNoDexRegisterMapSmallEncoding).
David Srbecky09ed0982016-02-12 21:58:43 +0000549 ASSERT_NE(stack_map1.GetDexRegisterMapOffset(encoding.stack_map_encoding),
550 StackMap::kNoDexRegisterMap);
551 ASSERT_EQ(stack_map1.GetDexRegisterMapOffset(encoding.stack_map_encoding), 0xFFu);
Nicolas Geoffrayfead4e42015-03-13 14:39:40 +0000552}
553
Calin Juravle6ae70962015-03-18 16:31:28 +0000554TEST(StackMapTest, TestShareDexRegisterMap) {
555 ArenaPool pool;
556 ArenaAllocator arena(&pool);
557 StackMapStream stream(&arena);
558
559 ArenaBitVector sp_mask(&arena, 0, false);
560 uint32_t number_of_dex_registers = 2;
561 // First stack map.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100562 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100563 stream.AddDexRegisterEntry(Kind::kInRegister, 0); // Short location.
564 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100565 stream.EndStackMapEntry();
Calin Juravle6ae70962015-03-18 16:31:28 +0000566 // Second stack map, which should share the same dex register map.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100567 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100568 stream.AddDexRegisterEntry(Kind::kInRegister, 0); // Short location.
569 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100570 stream.EndStackMapEntry();
Calin Juravle6ae70962015-03-18 16:31:28 +0000571 // Third stack map (doesn't share the dex register map).
Calin Juravle4f46ac52015-04-23 18:47:21 +0100572 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100573 stream.AddDexRegisterEntry(Kind::kInRegister, 2); // Short location.
574 stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
Calin Juravle4f46ac52015-04-23 18:47:21 +0100575 stream.EndStackMapEntry();
Calin Juravle6ae70962015-03-18 16:31:28 +0000576
Calin Juravle4f46ac52015-04-23 18:47:21 +0100577 size_t size = stream.PrepareForFillIn();
Calin Juravle6ae70962015-03-18 16:31:28 +0000578 void* memory = arena.Alloc(size, kArenaAllocMisc);
579 MemoryRegion region(memory, size);
580 stream.FillIn(region);
581
582 CodeInfo ci(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000583 CodeInfoEncoding encoding = ci.ExtractEncoding();
David Brazdilf677ebf2015-05-29 16:29:43 +0100584
Calin Juravle6ae70962015-03-18 16:31:28 +0000585 // Verify first stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100586 StackMap sm0 = ci.GetStackMapAt(0, encoding);
587 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, encoding, number_of_dex_registers);
588 ASSERT_EQ(0, dex_registers0.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
589 ASSERT_EQ(-2, dex_registers0.GetConstant(1, number_of_dex_registers, ci, encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000590
591 // Verify second stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100592 StackMap sm1 = ci.GetStackMapAt(1, encoding);
593 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapOf(sm1, encoding, number_of_dex_registers);
594 ASSERT_EQ(0, dex_registers1.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
595 ASSERT_EQ(-2, dex_registers1.GetConstant(1, number_of_dex_registers, ci, encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000596
597 // Verify third stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100598 StackMap sm2 = ci.GetStackMapAt(2, encoding);
599 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapOf(sm2, encoding, number_of_dex_registers);
600 ASSERT_EQ(2, dex_registers2.GetMachineRegister(0, number_of_dex_registers, ci, encoding));
601 ASSERT_EQ(-2, dex_registers2.GetConstant(1, number_of_dex_registers, ci, encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000602
603 // Verify dex register map offsets.
David Srbecky09ed0982016-02-12 21:58:43 +0000604 ASSERT_EQ(sm0.GetDexRegisterMapOffset(encoding.stack_map_encoding),
605 sm1.GetDexRegisterMapOffset(encoding.stack_map_encoding));
606 ASSERT_NE(sm0.GetDexRegisterMapOffset(encoding.stack_map_encoding),
607 sm2.GetDexRegisterMapOffset(encoding.stack_map_encoding));
608 ASSERT_NE(sm1.GetDexRegisterMapOffset(encoding.stack_map_encoding),
609 sm2.GetDexRegisterMapOffset(encoding.stack_map_encoding));
Calin Juravle6ae70962015-03-18 16:31:28 +0000610}
611
Roland Levillaina552e1c2015-03-26 15:01:03 +0000612TEST(StackMapTest, TestNoDexRegisterMap) {
613 ArenaPool pool;
614 ArenaAllocator arena(&pool);
615 StackMapStream stream(&arena);
616
617 ArenaBitVector sp_mask(&arena, 0, false);
618 uint32_t number_of_dex_registers = 0;
Calin Juravle4f46ac52015-04-23 18:47:21 +0100619 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
620 stream.EndStackMapEntry();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000621
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000622 number_of_dex_registers = 1;
623 stream.BeginStackMapEntry(1, 67, 0x4, &sp_mask, number_of_dex_registers, 0);
624 stream.EndStackMapEntry();
625
Calin Juravle4f46ac52015-04-23 18:47:21 +0100626 size_t size = stream.PrepareForFillIn();
Roland Levillaina552e1c2015-03-26 15:01:03 +0000627 void* memory = arena.Alloc(size, kArenaAllocMisc);
628 MemoryRegion region(memory, size);
629 stream.FillIn(region);
630
631 CodeInfo code_info(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000632 CodeInfoEncoding encoding = code_info.ExtractEncoding();
633 ASSERT_EQ(2u, code_info.GetNumberOfStackMaps(encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000634
David Srbecky09ed0982016-02-12 21:58:43 +0000635 uint32_t number_of_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
636 ASSERT_EQ(0u, number_of_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100637 DexRegisterLocationCatalog location_catalog = code_info.GetDexRegisterLocationCatalog(encoding);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000638 ASSERT_EQ(0u, location_catalog.Size());
639
David Brazdilf677ebf2015-05-29 16:29:43 +0100640 StackMap stack_map = code_info.GetStackMapAt(0, encoding);
641 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(0, encoding)));
642 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(64, encoding)));
David Srbecky09ed0982016-02-12 21:58:43 +0000643 ASSERT_EQ(0u, stack_map.GetDexPc(encoding.stack_map_encoding));
644 ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map_encoding));
645 ASSERT_EQ(0x3u, stack_map.GetRegisterMask(encoding.stack_map_encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000646
David Srbecky09ed0982016-02-12 21:58:43 +0000647 ASSERT_FALSE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding));
648 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map_encoding));
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000649
650 stack_map = code_info.GetStackMapAt(1, encoding);
651 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForDexPc(1, encoding)));
652 ASSERT_TRUE(stack_map.Equals(code_info.GetStackMapForNativePcOffset(67, encoding)));
David Srbecky09ed0982016-02-12 21:58:43 +0000653 ASSERT_EQ(1u, stack_map.GetDexPc(encoding.stack_map_encoding));
654 ASSERT_EQ(67u, stack_map.GetNativePcOffset(encoding.stack_map_encoding));
655 ASSERT_EQ(0x4u, stack_map.GetRegisterMask(encoding.stack_map_encoding));
Nicolas Geoffray012fc4e2016-01-08 15:58:19 +0000656
David Srbecky09ed0982016-02-12 21:58:43 +0000657 ASSERT_FALSE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding));
658 ASSERT_FALSE(stack_map.HasInlineInfo(encoding.stack_map_encoding));
Roland Levillaina552e1c2015-03-26 15:01:03 +0000659}
660
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100661TEST(StackMapTest, InlineTest) {
662 ArenaPool pool;
663 ArenaAllocator arena(&pool);
664 StackMapStream stream(&arena);
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000665 ArtMethod art_method;
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100666
667 ArenaBitVector sp_mask1(&arena, 0, true);
668 sp_mask1.SetBit(2);
669 sp_mask1.SetBit(4);
670
671 // First stack map.
672 stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, 2, 2);
673 stream.AddDexRegisterEntry(Kind::kInStack, 0);
674 stream.AddDexRegisterEntry(Kind::kConstant, 4);
675
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000676 stream.BeginInlineInfoEntry(&art_method, 2, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100677 stream.AddDexRegisterEntry(Kind::kInStack, 8);
678 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000679 stream.BeginInlineInfoEntry(&art_method, 3, 3);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100680 stream.AddDexRegisterEntry(Kind::kInStack, 16);
681 stream.AddDexRegisterEntry(Kind::kConstant, 20);
682 stream.AddDexRegisterEntry(Kind::kInRegister, 15);
683 stream.EndInlineInfoEntry();
684
685 stream.EndStackMapEntry();
686
687 // Second stack map.
688 stream.BeginStackMapEntry(2, 22, 0x3, &sp_mask1, 2, 3);
689 stream.AddDexRegisterEntry(Kind::kInStack, 56);
690 stream.AddDexRegisterEntry(Kind::kConstant, 0);
691
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000692 stream.BeginInlineInfoEntry(&art_method, 2, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100693 stream.AddDexRegisterEntry(Kind::kInStack, 12);
694 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000695 stream.BeginInlineInfoEntry(&art_method, 3, 3);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100696 stream.AddDexRegisterEntry(Kind::kInStack, 80);
697 stream.AddDexRegisterEntry(Kind::kConstant, 10);
698 stream.AddDexRegisterEntry(Kind::kInRegister, 5);
699 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000700 stream.BeginInlineInfoEntry(&art_method, 5, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100701 stream.EndInlineInfoEntry();
702
703 stream.EndStackMapEntry();
704
705 // Third stack map.
706 stream.BeginStackMapEntry(4, 56, 0x3, &sp_mask1, 2, 0);
707 stream.AddDexRegisterEntry(Kind::kNone, 0);
708 stream.AddDexRegisterEntry(Kind::kConstant, 4);
709 stream.EndStackMapEntry();
710
711 // Fourth stack map.
712 stream.BeginStackMapEntry(6, 78, 0x3, &sp_mask1, 2, 3);
713 stream.AddDexRegisterEntry(Kind::kInStack, 56);
714 stream.AddDexRegisterEntry(Kind::kConstant, 0);
715
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000716 stream.BeginInlineInfoEntry(&art_method, 2, 0);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100717 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000718 stream.BeginInlineInfoEntry(&art_method, 5, 1);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100719 stream.AddDexRegisterEntry(Kind::kInRegister, 2);
720 stream.EndInlineInfoEntry();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000721 stream.BeginInlineInfoEntry(&art_method, 10, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100722 stream.AddDexRegisterEntry(Kind::kNone, 0);
723 stream.AddDexRegisterEntry(Kind::kInRegister, 3);
724 stream.EndInlineInfoEntry();
725
726 stream.EndStackMapEntry();
727
728 size_t size = stream.PrepareForFillIn();
729 void* memory = arena.Alloc(size, kArenaAllocMisc);
730 MemoryRegion region(memory, size);
731 stream.FillIn(region);
732
733 CodeInfo ci(region);
David Srbecky09ed0982016-02-12 21:58:43 +0000734 CodeInfoEncoding encoding = ci.ExtractEncoding();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100735
736 {
737 // Verify first stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100738 StackMap sm0 = ci.GetStackMapAt(0, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100739
David Brazdilf677ebf2015-05-29 16:29:43 +0100740 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, encoding, 2);
741 ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
742 ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100743
David Brazdilf677ebf2015-05-29 16:29:43 +0100744 InlineInfo if0 = ci.GetInlineInfoOf(sm0, encoding);
David Srbecky61b28a12016-02-25 21:55:03 +0000745 ASSERT_EQ(2u, if0.GetDepth(encoding.inline_info_encoding));
746 ASSERT_EQ(2u, if0.GetDexPcAtDepth(encoding.inline_info_encoding, 0));
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000747 ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 0));
David Srbecky61b28a12016-02-25 21:55:03 +0000748 ASSERT_EQ(3u, if0.GetDexPcAtDepth(encoding.inline_info_encoding, 1));
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000749 ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 1));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100750
David Brazdilf677ebf2015-05-29 16:29:43 +0100751 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, encoding, 1);
752 ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100753
David Brazdilf677ebf2015-05-29 16:29:43 +0100754 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if0, encoding, 3);
755 ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0, 3, ci, encoding));
756 ASSERT_EQ(20, dex_registers2.GetConstant(1, 3, ci, encoding));
757 ASSERT_EQ(15, dex_registers2.GetMachineRegister(2, 3, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100758 }
759
760 {
761 // Verify second stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100762 StackMap sm1 = ci.GetStackMapAt(1, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100763
David Brazdilf677ebf2015-05-29 16:29:43 +0100764 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm1, encoding, 2);
765 ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
766 ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100767
David Brazdilf677ebf2015-05-29 16:29:43 +0100768 InlineInfo if1 = ci.GetInlineInfoOf(sm1, encoding);
David Srbecky61b28a12016-02-25 21:55:03 +0000769 ASSERT_EQ(3u, if1.GetDepth(encoding.inline_info_encoding));
770 ASSERT_EQ(2u, if1.GetDexPcAtDepth(encoding.inline_info_encoding, 0));
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000771 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 0));
David Srbecky61b28a12016-02-25 21:55:03 +0000772 ASSERT_EQ(3u, if1.GetDexPcAtDepth(encoding.inline_info_encoding, 1));
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000773 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 1));
David Srbecky61b28a12016-02-25 21:55:03 +0000774 ASSERT_EQ(5u, if1.GetDexPcAtDepth(encoding.inline_info_encoding, 2));
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000775 ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100776
David Brazdilf677ebf2015-05-29 16:29:43 +0100777 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, encoding, 1);
778 ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100779
David Brazdilf677ebf2015-05-29 16:29:43 +0100780 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if1, encoding, 3);
781 ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0, 3, ci, encoding));
782 ASSERT_EQ(10, dex_registers2.GetConstant(1, 3, ci, encoding));
783 ASSERT_EQ(5, dex_registers2.GetMachineRegister(2, 3, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100784
David Srbecky61b28a12016-02-25 21:55:03 +0000785 ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(encoding.inline_info_encoding, 2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100786 }
787
788 {
789 // Verify third stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100790 StackMap sm2 = ci.GetStackMapAt(2, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100791
David Brazdilf677ebf2015-05-29 16:29:43 +0100792 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2, encoding, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100793 ASSERT_FALSE(dex_registers0.IsDexRegisterLive(0));
David Brazdilf677ebf2015-05-29 16:29:43 +0100794 ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci, encoding));
David Srbecky09ed0982016-02-12 21:58:43 +0000795 ASSERT_FALSE(sm2.HasInlineInfo(encoding.stack_map_encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100796 }
797
798 {
799 // Verify fourth stack map.
David Brazdilf677ebf2015-05-29 16:29:43 +0100800 StackMap sm3 = ci.GetStackMapAt(3, encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100801
David Brazdilf677ebf2015-05-29 16:29:43 +0100802 DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm3, encoding, 2);
803 ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci, encoding));
804 ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100805
David Brazdilf677ebf2015-05-29 16:29:43 +0100806 InlineInfo if2 = ci.GetInlineInfoOf(sm3, encoding);
David Srbecky61b28a12016-02-25 21:55:03 +0000807 ASSERT_EQ(3u, if2.GetDepth(encoding.inline_info_encoding));
808 ASSERT_EQ(2u, if2.GetDexPcAtDepth(encoding.inline_info_encoding, 0));
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000809 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 0));
David Srbecky61b28a12016-02-25 21:55:03 +0000810 ASSERT_EQ(5u, if2.GetDexPcAtDepth(encoding.inline_info_encoding, 1));
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000811 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 1));
David Srbecky61b28a12016-02-25 21:55:03 +0000812 ASSERT_EQ(10u, if2.GetDexPcAtDepth(encoding.inline_info_encoding, 2));
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000813 ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 2));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100814
David Srbecky61b28a12016-02-25 21:55:03 +0000815 ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(encoding.inline_info_encoding, 0));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100816
David Brazdilf677ebf2015-05-29 16:29:43 +0100817 DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, encoding, 1);
818 ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100819
David Brazdilf677ebf2015-05-29 16:29:43 +0100820 DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, encoding, 2);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100821 ASSERT_FALSE(dex_registers2.IsDexRegisterLive(0));
David Brazdilf677ebf2015-05-29 16:29:43 +0100822 ASSERT_EQ(3, dex_registers2.GetMachineRegister(1, 2, ci, encoding));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100823 }
824}
825
Nicolas Geoffray99ea58c2014-07-02 15:08:17 +0100826} // namespace art