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