1 /* 2 * Copyright (C) 2012 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 "reg_type_cache-inl.h" 18 19 #include <type_traits> 20 21 #include "base/aborting.h" 22 #include "base/arena_bit_vector.h" 23 #include "base/bit_vector-inl.h" 24 #include "base/casts.h" 25 #include "base/scoped_arena_allocator.h" 26 #include "base/stl_util.h" 27 #include "class_linker-inl.h" 28 #include "dex/descriptors_names.h" 29 #include "dex/dex_file-inl.h" 30 #include "mirror/class-inl.h" 31 #include "mirror/object-inl.h" 32 #include "reg_type-inl.h" 33 34 namespace art { 35 namespace verifier { 36 37 bool RegTypeCache::primitive_initialized_ = false; 38 uint16_t RegTypeCache::primitive_count_ = 0; 39 const PreciseConstType* RegTypeCache::small_precise_constants_[kMaxSmallConstant - 40 kMinSmallConstant + 1]; 41 42 ALWAYS_INLINE static inline bool MatchingPrecisionForClass(const RegType* entry, bool precise) 43 REQUIRES_SHARED(Locks::mutator_lock_) { 44 if (entry->IsPreciseReference() == precise) { 45 // We were or weren't looking for a precise reference and we found what we need. 46 return true; 47 } else { 48 if (!precise && entry->GetClass()->CannotBeAssignedFromOtherTypes()) { 49 // We weren't looking for a precise reference, as we're looking up based on a descriptor, but 50 // we found a matching entry based on the descriptor. Return the precise entry in that case. 51 return true; 52 } 53 return false; 54 } 55 } 56 57 void RegTypeCache::FillPrimitiveAndSmallConstantTypes() { 58 // Note: this must have the same order as CreatePrimitiveAndSmallConstantTypes. 59 entries_.push_back(UndefinedType::GetInstance()); 60 entries_.push_back(ConflictType::GetInstance()); 61 entries_.push_back(NullType::GetInstance()); 62 entries_.push_back(BooleanType::GetInstance()); 63 entries_.push_back(ByteType::GetInstance()); 64 entries_.push_back(ShortType::GetInstance()); 65 entries_.push_back(CharType::GetInstance()); 66 entries_.push_back(IntegerType::GetInstance()); 67 entries_.push_back(LongLoType::GetInstance()); 68 entries_.push_back(LongHiType::GetInstance()); 69 entries_.push_back(FloatType::GetInstance()); 70 entries_.push_back(DoubleLoType::GetInstance()); 71 entries_.push_back(DoubleHiType::GetInstance()); 72 for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) { 73 int32_t i = value - kMinSmallConstant; 74 DCHECK_EQ(entries_.size(), small_precise_constants_[i]->GetId()); 75 entries_.push_back(small_precise_constants_[i]); 76 } 77 DCHECK_EQ(entries_.size(), primitive_count_); 78 } 79 80 const RegType& RegTypeCache::FromDescriptor(ObjPtr<mirror::ClassLoader> loader, 81 const char* descriptor, 82 bool precise) { 83 DCHECK(RegTypeCache::primitive_initialized_); 84 if (descriptor[1] == '\0') { 85 switch (descriptor[0]) { 86 case 'Z': 87 return Boolean(); 88 case 'B': 89 return Byte(); 90 case 'S': 91 return Short(); 92 case 'C': 93 return Char(); 94 case 'I': 95 return Integer(); 96 case 'J': 97 return LongLo(); 98 case 'F': 99 return Float(); 100 case 'D': 101 return DoubleLo(); 102 case 'V': // For void types, conflict types. 103 default: 104 return Conflict(); 105 } 106 } else if (descriptor[0] == 'L' || descriptor[0] == '[') { 107 return From(loader, descriptor, precise); 108 } else { 109 return Conflict(); 110 } 111 } 112 113 const RegType& RegTypeCache::RegTypeFromPrimitiveType(Primitive::Type prim_type) const { 114 DCHECK(RegTypeCache::primitive_initialized_); 115 switch (prim_type) { 116 case Primitive::kPrimBoolean: 117 return *BooleanType::GetInstance(); 118 case Primitive::kPrimByte: 119 return *ByteType::GetInstance(); 120 case Primitive::kPrimShort: 121 return *ShortType::GetInstance(); 122 case Primitive::kPrimChar: 123 return *CharType::GetInstance(); 124 case Primitive::kPrimInt: 125 return *IntegerType::GetInstance(); 126 case Primitive::kPrimLong: 127 return *LongLoType::GetInstance(); 128 case Primitive::kPrimFloat: 129 return *FloatType::GetInstance(); 130 case Primitive::kPrimDouble: 131 return *DoubleLoType::GetInstance(); 132 case Primitive::kPrimVoid: 133 default: 134 return *ConflictType::GetInstance(); 135 } 136 } 137 138 bool RegTypeCache::MatchDescriptor(size_t idx, const std::string_view& descriptor, bool precise) { 139 const RegType* entry = entries_[idx]; 140 if (descriptor != entry->descriptor_) { 141 return false; 142 } 143 if (entry->HasClass()) { 144 return MatchingPrecisionForClass(entry, precise); 145 } 146 // There is no notion of precise unresolved references, the precise information is just dropped 147 // on the floor. 148 DCHECK(entry->IsUnresolvedReference()); 149 return true; 150 } 151 152 ObjPtr<mirror::Class> RegTypeCache::ResolveClass(const char* descriptor, 153 ObjPtr<mirror::ClassLoader> loader) { 154 // Class was not found, must create new type. 155 // Try resolving class 156 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 157 Thread* self = Thread::Current(); 158 StackHandleScope<1> hs(self); 159 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(loader)); 160 ObjPtr<mirror::Class> klass = nullptr; 161 if (can_load_classes_) { 162 klass = class_linker->FindClass(self, descriptor, class_loader); 163 } else { 164 klass = class_linker->LookupClass(self, descriptor, loader); 165 if (klass != nullptr && !klass->IsResolved()) { 166 // We found the class but without it being loaded its not safe for use. 167 klass = nullptr; 168 } 169 } 170 return klass; 171 } 172 173 std::string_view RegTypeCache::AddString(const std::string_view& str) { 174 char* ptr = allocator_.AllocArray<char>(str.length()); 175 memcpy(ptr, str.data(), str.length()); 176 return std::string_view(ptr, str.length()); 177 } 178 179 const RegType& RegTypeCache::From(ObjPtr<mirror::ClassLoader> loader, 180 const char* descriptor, 181 bool precise) { 182 std::string_view sv_descriptor(descriptor); 183 // Try looking up the class in the cache first. We use a std::string_view to avoid 184 // repeated strlen operations on the descriptor. 185 for (size_t i = primitive_count_; i < entries_.size(); i++) { 186 if (MatchDescriptor(i, sv_descriptor, precise)) { 187 return *(entries_[i]); 188 } 189 } 190 // Class not found in the cache, will create a new type for that. 191 // Try resolving class. 192 ObjPtr<mirror::Class> klass = ResolveClass(descriptor, loader); 193 if (klass != nullptr) { 194 // Class resolved, first look for the class in the list of entries 195 // Class was not found, must create new type. 196 // To pass the verification, the type should be imprecise, 197 // instantiable or an interface with the precise type set to false. 198 DCHECK(!precise || klass->IsInstantiable()); 199 // Create a precise type if: 200 // 1- Class is final and NOT an interface. a precise interface is meaningless !! 201 // 2- Precise Flag passed as true. 202 RegType* entry; 203 // Create an imprecise type if we can't tell for a fact that it is precise. 204 if (klass->CannotBeAssignedFromOtherTypes() || precise) { 205 DCHECK(!(klass->IsAbstract()) || klass->IsArrayClass()); 206 DCHECK(!klass->IsInterface()); 207 entry = 208 new (&allocator_) PreciseReferenceType(klass, AddString(sv_descriptor), entries_.size()); 209 } else { 210 entry = new (&allocator_) ReferenceType(klass, AddString(sv_descriptor), entries_.size()); 211 } 212 return AddEntry(entry); 213 } else { // Class not resolved. 214 // We tried loading the class and failed, this might get an exception raised 215 // so we want to clear it before we go on. 216 if (can_load_classes_) { 217 DCHECK(Thread::Current()->IsExceptionPending()); 218 Thread::Current()->ClearException(); 219 } else { 220 DCHECK(!Thread::Current()->IsExceptionPending()); 221 } 222 if (IsValidDescriptor(descriptor)) { 223 return AddEntry( 224 new (&allocator_) UnresolvedReferenceType(AddString(sv_descriptor), entries_.size())); 225 } else { 226 // The descriptor is broken return the unknown type as there's nothing sensible that 227 // could be done at runtime 228 return Conflict(); 229 } 230 } 231 } 232 233 const RegType& RegTypeCache::MakeUnresolvedReference() { 234 // The descriptor is intentionally invalid so nothing else will match this type. 235 return AddEntry(new (&allocator_) UnresolvedReferenceType(AddString("a"), entries_.size())); 236 } 237 238 const RegType* RegTypeCache::FindClass(ObjPtr<mirror::Class> klass, bool precise) const { 239 DCHECK(klass != nullptr); 240 if (klass->IsPrimitive()) { 241 // Note: precise isn't used for primitive classes. A char is assignable to an int. All 242 // primitive classes are final. 243 return &RegTypeFromPrimitiveType(klass->GetPrimitiveType()); 244 } 245 for (auto& pair : klass_entries_) { 246 const ObjPtr<mirror::Class> reg_klass = pair.first.Read(); 247 if (reg_klass == klass) { 248 const RegType* reg_type = pair.second; 249 if (MatchingPrecisionForClass(reg_type, precise)) { 250 return reg_type; 251 } 252 } 253 } 254 return nullptr; 255 } 256 257 const RegType* RegTypeCache::InsertClass(const std::string_view& descriptor, 258 ObjPtr<mirror::Class> klass, 259 bool precise) { 260 // No reference to the class was found, create new reference. 261 DCHECK(FindClass(klass, precise) == nullptr); 262 RegType* const reg_type = precise 263 ? static_cast<RegType*>( 264 new (&allocator_) PreciseReferenceType(klass, descriptor, entries_.size())) 265 : new (&allocator_) ReferenceType(klass, descriptor, entries_.size()); 266 return &AddEntry(reg_type); 267 } 268 269 const RegType& RegTypeCache::FromClass(const char* descriptor, 270 ObjPtr<mirror::Class> klass, 271 bool precise) { 272 DCHECK(klass != nullptr); 273 const RegType* reg_type = FindClass(klass, precise); 274 if (reg_type == nullptr) { 275 reg_type = InsertClass(AddString(std::string_view(descriptor)), klass, precise); 276 } 277 return *reg_type; 278 } 279 280 RegTypeCache::RegTypeCache(bool can_load_classes, ScopedArenaAllocator& allocator, bool can_suspend) 281 : entries_(allocator.Adapter(kArenaAllocVerifier)), 282 klass_entries_(allocator.Adapter(kArenaAllocVerifier)), 283 can_load_classes_(can_load_classes), 284 allocator_(allocator) { 285 DCHECK(can_suspend || !can_load_classes) << "Cannot load classes if suspension is disabled!"; 286 if (kIsDebugBuild && can_suspend) { 287 Thread::Current()->AssertThreadSuspensionIsAllowable(gAborting == 0); 288 } 289 // The klass_entries_ array does not have primitives or small constants. 290 static constexpr size_t kNumReserveEntries = 32; 291 klass_entries_.reserve(kNumReserveEntries); 292 // We want to have room for additional entries after inserting primitives and small 293 // constants. 294 entries_.reserve(kNumReserveEntries + kNumPrimitivesAndSmallConstants); 295 FillPrimitiveAndSmallConstantTypes(); 296 } 297 298 RegTypeCache::~RegTypeCache() { 299 DCHECK_LE(primitive_count_, entries_.size()); 300 } 301 302 void RegTypeCache::ShutDown() { 303 if (RegTypeCache::primitive_initialized_) { 304 UndefinedType::Destroy(); 305 ConflictType::Destroy(); 306 BooleanType::Destroy(); 307 ByteType::Destroy(); 308 ShortType::Destroy(); 309 CharType::Destroy(); 310 IntegerType::Destroy(); 311 LongLoType::Destroy(); 312 LongHiType::Destroy(); 313 FloatType::Destroy(); 314 DoubleLoType::Destroy(); 315 DoubleHiType::Destroy(); 316 NullType::Destroy(); 317 for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) { 318 const PreciseConstType* type = small_precise_constants_[value - kMinSmallConstant]; 319 delete type; 320 small_precise_constants_[value - kMinSmallConstant] = nullptr; 321 } 322 RegTypeCache::primitive_initialized_ = false; 323 RegTypeCache::primitive_count_ = 0; 324 } 325 } 326 327 // Helper for create_primitive_type_instance lambda. 328 namespace { 329 template <typename T> 330 struct TypeHelper { 331 using type = T; 332 static_assert(std::is_convertible<T*, RegType*>::value, "T must be a RegType"); 333 334 const char* descriptor; 335 336 explicit TypeHelper(const char* d) : descriptor(d) {} 337 }; 338 } // namespace 339 340 void RegTypeCache::CreatePrimitiveAndSmallConstantTypes() { 341 // Note: this must have the same order as FillPrimitiveAndSmallConstantTypes. 342 343 // It is acceptable to pass on the const char* in type to CreateInstance, as all calls below are 344 // with compile-time constants that will have global lifetime. Use of the lambda ensures this 345 // code cannot leak to other users. 346 auto create_primitive_type_instance = [&](auto type) REQUIRES_SHARED(Locks::mutator_lock_) { 347 using Type = typename decltype(type)::type; 348 ObjPtr<mirror::Class> klass = nullptr; 349 // Try loading the class from linker. 350 DCHECK(type.descriptor != nullptr); 351 if (strlen(type.descriptor) > 0) { 352 klass = art::Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(), 353 type.descriptor); 354 DCHECK(klass != nullptr); 355 } 356 const Type* entry = Type::CreateInstance(klass, 357 type.descriptor, 358 RegTypeCache::primitive_count_); 359 RegTypeCache::primitive_count_++; 360 return entry; 361 }; 362 create_primitive_type_instance(TypeHelper<UndefinedType>("")); 363 create_primitive_type_instance(TypeHelper<ConflictType>("")); 364 create_primitive_type_instance(TypeHelper<NullType>("")); 365 create_primitive_type_instance(TypeHelper<BooleanType>("Z")); 366 create_primitive_type_instance(TypeHelper<ByteType>("B")); 367 create_primitive_type_instance(TypeHelper<ShortType>("S")); 368 create_primitive_type_instance(TypeHelper<CharType>("C")); 369 create_primitive_type_instance(TypeHelper<IntegerType>("I")); 370 create_primitive_type_instance(TypeHelper<LongLoType>("J")); 371 create_primitive_type_instance(TypeHelper<LongHiType>("J")); 372 create_primitive_type_instance(TypeHelper<FloatType>("F")); 373 create_primitive_type_instance(TypeHelper<DoubleLoType>("D")); 374 create_primitive_type_instance(TypeHelper<DoubleHiType>("D")); 375 376 for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) { 377 PreciseConstType* type = new PreciseConstType(value, primitive_count_); 378 small_precise_constants_[value - kMinSmallConstant] = type; 379 primitive_count_++; 380 } 381 } 382 383 const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left, 384 const RegType& right, 385 MethodVerifier* verifier) { 386 ArenaBitVector types(&allocator_, 387 kDefaultArenaBitVectorBytes * kBitsPerByte, // Allocate at least 8 bytes. 388 true); // Is expandable. 389 const RegType* left_resolved; 390 bool left_unresolved_is_array; 391 if (left.IsUnresolvedMergedReference()) { 392 const UnresolvedMergedType& left_merge = *down_cast<const UnresolvedMergedType*>(&left); 393 394 types.Copy(&left_merge.GetUnresolvedTypes()); 395 left_resolved = &left_merge.GetResolvedPart(); 396 left_unresolved_is_array = left.IsArrayTypes(); 397 } else if (left.IsUnresolvedTypes()) { 398 types.ClearAllBits(); 399 types.SetBit(left.GetId()); 400 left_resolved = &Zero(); 401 left_unresolved_is_array = left.IsArrayTypes(); 402 } else { 403 types.ClearAllBits(); 404 left_resolved = &left; 405 left_unresolved_is_array = false; 406 } 407 408 const RegType* right_resolved; 409 bool right_unresolved_is_array; 410 if (right.IsUnresolvedMergedReference()) { 411 const UnresolvedMergedType& right_merge = *down_cast<const UnresolvedMergedType*>(&right); 412 413 types.Union(&right_merge.GetUnresolvedTypes()); 414 right_resolved = &right_merge.GetResolvedPart(); 415 right_unresolved_is_array = right.IsArrayTypes(); 416 } else if (right.IsUnresolvedTypes()) { 417 types.SetBit(right.GetId()); 418 right_resolved = &Zero(); 419 right_unresolved_is_array = right.IsArrayTypes(); 420 } else { 421 right_resolved = &right; 422 right_unresolved_is_array = false; 423 } 424 425 // Merge the resolved parts. Left and right might be equal, so use SafeMerge. 426 const RegType& resolved_parts_merged = left_resolved->SafeMerge(*right_resolved, this, verifier); 427 // If we get a conflict here, the merge result is a conflict, not an unresolved merge type. 428 if (resolved_parts_merged.IsConflict()) { 429 return Conflict(); 430 } 431 if (resolved_parts_merged.IsJavaLangObject()) { 432 return resolved_parts_merged; 433 } 434 435 bool resolved_merged_is_array = resolved_parts_merged.IsArrayTypes(); 436 if (left_unresolved_is_array || right_unresolved_is_array || resolved_merged_is_array) { 437 // Arrays involved, see if we need to merge to Object. 438 439 // Is the resolved part a primitive array? 440 if (resolved_merged_is_array && !resolved_parts_merged.IsObjectArrayTypes()) { 441 return JavaLangObject(/* precise= */ false); 442 } 443 444 // Is any part not an array (but exists)? 445 if ((!left_unresolved_is_array && left_resolved != &left) || 446 (!right_unresolved_is_array && right_resolved != &right) || 447 !resolved_merged_is_array) { 448 return JavaLangObject(/* precise= */ false); 449 } 450 } 451 452 // Check if entry already exists. 453 for (size_t i = primitive_count_; i < entries_.size(); i++) { 454 const RegType* cur_entry = entries_[i]; 455 if (cur_entry->IsUnresolvedMergedReference()) { 456 const UnresolvedMergedType* cmp_type = down_cast<const UnresolvedMergedType*>(cur_entry); 457 const RegType& resolved_part = cmp_type->GetResolvedPart(); 458 const BitVector& unresolved_part = cmp_type->GetUnresolvedTypes(); 459 // Use SameBitsSet. "types" is expandable to allow merging in the components, but the 460 // BitVector in the final RegType will be made non-expandable. 461 if (&resolved_part == &resolved_parts_merged && types.SameBitsSet(&unresolved_part)) { 462 return *cur_entry; 463 } 464 } 465 } 466 return AddEntry(new (&allocator_) UnresolvedMergedType(resolved_parts_merged, 467 types, 468 this, 469 entries_.size())); 470 } 471 472 const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) { 473 // Check if entry already exists. 474 for (size_t i = primitive_count_; i < entries_.size(); i++) { 475 const RegType* cur_entry = entries_[i]; 476 if (cur_entry->IsUnresolvedSuperClass()) { 477 const UnresolvedSuperClass* tmp_entry = 478 down_cast<const UnresolvedSuperClass*>(cur_entry); 479 uint16_t unresolved_super_child_id = 480 tmp_entry->GetUnresolvedSuperClassChildId(); 481 if (unresolved_super_child_id == child.GetId()) { 482 return *cur_entry; 483 } 484 } 485 } 486 return AddEntry(new (&allocator_) UnresolvedSuperClass(child.GetId(), this, entries_.size())); 487 } 488 489 const UninitializedType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) { 490 UninitializedType* entry = nullptr; 491 const std::string_view& descriptor(type.GetDescriptor()); 492 if (type.IsUnresolvedTypes()) { 493 for (size_t i = primitive_count_; i < entries_.size(); i++) { 494 const RegType* cur_entry = entries_[i]; 495 if (cur_entry->IsUnresolvedAndUninitializedReference() && 496 down_cast<const UnresolvedUninitializedRefType*>(cur_entry)->GetAllocationPc() 497 == allocation_pc && 498 (cur_entry->GetDescriptor() == descriptor)) { 499 return *down_cast<const UnresolvedUninitializedRefType*>(cur_entry); 500 } 501 } 502 entry = new (&allocator_) UnresolvedUninitializedRefType(descriptor, 503 allocation_pc, 504 entries_.size()); 505 } else { 506 ObjPtr<mirror::Class> klass = type.GetClass(); 507 for (size_t i = primitive_count_; i < entries_.size(); i++) { 508 const RegType* cur_entry = entries_[i]; 509 if (cur_entry->IsUninitializedReference() && 510 down_cast<const UninitializedReferenceType*>(cur_entry) 511 ->GetAllocationPc() == allocation_pc && 512 cur_entry->GetClass() == klass) { 513 return *down_cast<const UninitializedReferenceType*>(cur_entry); 514 } 515 } 516 entry = new (&allocator_) UninitializedReferenceType(klass, 517 descriptor, 518 allocation_pc, 519 entries_.size()); 520 } 521 return AddEntry(entry); 522 } 523 524 const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) { 525 RegType* entry; 526 527 if (uninit_type.IsUnresolvedTypes()) { 528 const std::string_view& descriptor(uninit_type.GetDescriptor()); 529 for (size_t i = primitive_count_; i < entries_.size(); i++) { 530 const RegType* cur_entry = entries_[i]; 531 if (cur_entry->IsUnresolvedReference() && 532 cur_entry->GetDescriptor() == descriptor) { 533 return *cur_entry; 534 } 535 } 536 entry = new (&allocator_) UnresolvedReferenceType(descriptor, entries_.size()); 537 } else { 538 ObjPtr<mirror::Class> klass = uninit_type.GetClass(); 539 if (uninit_type.IsUninitializedThisReference() && !klass->IsFinal()) { 540 // For uninitialized "this reference" look for reference types that are not precise. 541 for (size_t i = primitive_count_; i < entries_.size(); i++) { 542 const RegType* cur_entry = entries_[i]; 543 if (cur_entry->IsReference() && cur_entry->GetClass() == klass) { 544 return *cur_entry; 545 } 546 } 547 entry = new (&allocator_) ReferenceType(klass, "", entries_.size()); 548 } else if (!klass->IsPrimitive()) { 549 // We're uninitialized because of allocation, look or create a precise type as allocations 550 // may only create objects of that type. 551 // Note: we do not check whether the given klass is actually instantiable (besides being 552 // primitive), that is, we allow interfaces and abstract classes here. The reasoning is 553 // twofold: 554 // 1) The "new-instance" instruction to generate the uninitialized type will already 555 // queue an instantiation error. This is a soft error that must be thrown at runtime, 556 // and could potentially change if the class is resolved differently at runtime. 557 // 2) Checking whether the klass is instantiable and using conflict may produce a hard 558 // error when the value is used, which leads to a VerifyError, which is not the 559 // correct semantics. 560 for (size_t i = primitive_count_; i < entries_.size(); i++) { 561 const RegType* cur_entry = entries_[i]; 562 if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) { 563 return *cur_entry; 564 } 565 } 566 entry = new (&allocator_) PreciseReferenceType(klass, 567 uninit_type.GetDescriptor(), 568 entries_.size()); 569 } else { 570 return Conflict(); 571 } 572 } 573 return AddEntry(entry); 574 } 575 576 const UninitializedType& RegTypeCache::UninitializedThisArgument(const RegType& type) { 577 UninitializedType* entry; 578 const std::string_view& descriptor(type.GetDescriptor()); 579 if (type.IsUnresolvedTypes()) { 580 for (size_t i = primitive_count_; i < entries_.size(); i++) { 581 const RegType* cur_entry = entries_[i]; 582 if (cur_entry->IsUnresolvedAndUninitializedThisReference() && 583 cur_entry->GetDescriptor() == descriptor) { 584 return *down_cast<const UninitializedType*>(cur_entry); 585 } 586 } 587 entry = new (&allocator_) UnresolvedUninitializedThisRefType(descriptor, entries_.size()); 588 } else { 589 ObjPtr<mirror::Class> klass = type.GetClass(); 590 for (size_t i = primitive_count_; i < entries_.size(); i++) { 591 const RegType* cur_entry = entries_[i]; 592 if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) { 593 return *down_cast<const UninitializedType*>(cur_entry); 594 } 595 } 596 entry = new (&allocator_) UninitializedThisReferenceType(klass, descriptor, entries_.size()); 597 } 598 return AddEntry(entry); 599 } 600 601 const ConstantType& RegTypeCache::FromCat1NonSmallConstant(int32_t value, bool precise) { 602 for (size_t i = primitive_count_; i < entries_.size(); i++) { 603 const RegType* cur_entry = entries_[i]; 604 if (cur_entry->klass_.IsNull() && cur_entry->IsConstant() && 605 cur_entry->IsPreciseConstant() == precise && 606 (down_cast<const ConstantType*>(cur_entry))->ConstantValue() == value) { 607 return *down_cast<const ConstantType*>(cur_entry); 608 } 609 } 610 ConstantType* entry; 611 if (precise) { 612 entry = new (&allocator_) PreciseConstType(value, entries_.size()); 613 } else { 614 entry = new (&allocator_) ImpreciseConstType(value, entries_.size()); 615 } 616 return AddEntry(entry); 617 } 618 619 const ConstantType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) { 620 for (size_t i = primitive_count_; i < entries_.size(); i++) { 621 const RegType* cur_entry = entries_[i]; 622 if (cur_entry->IsConstantLo() && (cur_entry->IsPrecise() == precise) && 623 (down_cast<const ConstantType*>(cur_entry))->ConstantValueLo() == value) { 624 return *down_cast<const ConstantType*>(cur_entry); 625 } 626 } 627 ConstantType* entry; 628 if (precise) { 629 entry = new (&allocator_) PreciseConstLoType(value, entries_.size()); 630 } else { 631 entry = new (&allocator_) ImpreciseConstLoType(value, entries_.size()); 632 } 633 return AddEntry(entry); 634 } 635 636 const ConstantType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) { 637 for (size_t i = primitive_count_; i < entries_.size(); i++) { 638 const RegType* cur_entry = entries_[i]; 639 if (cur_entry->IsConstantHi() && (cur_entry->IsPrecise() == precise) && 640 (down_cast<const ConstantType*>(cur_entry))->ConstantValueHi() == value) { 641 return *down_cast<const ConstantType*>(cur_entry); 642 } 643 } 644 ConstantType* entry; 645 if (precise) { 646 entry = new (&allocator_) PreciseConstHiType(value, entries_.size()); 647 } else { 648 entry = new (&allocator_) ImpreciseConstHiType(value, entries_.size()); 649 } 650 return AddEntry(entry); 651 } 652 653 const RegType& RegTypeCache::GetComponentType(const RegType& array, 654 ObjPtr<mirror::ClassLoader> loader) { 655 if (!array.IsArrayTypes()) { 656 return Conflict(); 657 } else if (array.IsUnresolvedTypes()) { 658 DCHECK(!array.IsUnresolvedMergedReference()); // Caller must make sure not to ask for this. 659 const std::string descriptor(array.GetDescriptor()); 660 return FromDescriptor(loader, descriptor.c_str() + 1, false); 661 } else { 662 ObjPtr<mirror::Class> klass = array.GetClass()->GetComponentType(); 663 std::string temp; 664 const char* descriptor = klass->GetDescriptor(&temp); 665 if (klass->IsErroneous()) { 666 // Arrays may have erroneous component types, use unresolved in that case. 667 // We assume that the primitive classes are not erroneous, so we know it is a 668 // reference type. 669 return FromDescriptor(loader, descriptor, false); 670 } else { 671 return FromClass(descriptor, klass, klass->CannotBeAssignedFromOtherTypes()); 672 } 673 } 674 } 675 676 void RegTypeCache::Dump(std::ostream& os) { 677 for (size_t i = 0; i < entries_.size(); i++) { 678 const RegType* cur_entry = entries_[i]; 679 if (cur_entry != nullptr) { 680 os << i << ": " << cur_entry->Dump() << "\n"; 681 } 682 } 683 } 684 685 void RegTypeCache::VisitStaticRoots(RootVisitor* visitor) { 686 // Visit the primitive types, this is required since if there are no active verifiers they wont 687 // be in the entries array, and therefore not visited as roots. 688 if (primitive_initialized_) { 689 RootInfo ri(kRootUnknown); 690 UndefinedType::GetInstance()->VisitRoots(visitor, ri); 691 ConflictType::GetInstance()->VisitRoots(visitor, ri); 692 BooleanType::GetInstance()->VisitRoots(visitor, ri); 693 ByteType::GetInstance()->VisitRoots(visitor, ri); 694 ShortType::GetInstance()->VisitRoots(visitor, ri); 695 CharType::GetInstance()->VisitRoots(visitor, ri); 696 IntegerType::GetInstance()->VisitRoots(visitor, ri); 697 LongLoType::GetInstance()->VisitRoots(visitor, ri); 698 LongHiType::GetInstance()->VisitRoots(visitor, ri); 699 FloatType::GetInstance()->VisitRoots(visitor, ri); 700 DoubleLoType::GetInstance()->VisitRoots(visitor, ri); 701 DoubleHiType::GetInstance()->VisitRoots(visitor, ri); 702 for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) { 703 small_precise_constants_[value - kMinSmallConstant]->VisitRoots(visitor, ri); 704 } 705 } 706 } 707 708 void RegTypeCache::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) { 709 // Exclude the static roots that are visited by VisitStaticRoots(). 710 for (size_t i = primitive_count_; i < entries_.size(); ++i) { 711 entries_[i]->VisitRoots(visitor, root_info); 712 } 713 for (auto& pair : klass_entries_) { 714 GcRoot<mirror::Class>& root = pair.first; 715 root.VisitRoot(visitor, root_info); 716 } 717 } 718 719 } // namespace verifier 720 } // namespace art 721