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