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 "base/casts.h" 20 #include "class_linker-inl.h" 21 #include "dex_file-inl.h" 22 #include "mirror/class-inl.h" 23 #include "mirror/object-inl.h" 24 25 namespace art { 26 namespace verifier { 27 28 bool RegTypeCache::primitive_initialized_ = false; 29 uint16_t RegTypeCache::primitive_count_ = 0; 30 PreciseConstType* RegTypeCache::small_precise_constants_[kMaxSmallConstant - kMinSmallConstant + 1]; 31 32 static bool MatchingPrecisionForClass(RegType* entry, bool precise) 33 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 34 if (entry->IsPreciseReference() == precise) { 35 // We were or weren't looking for a precise reference and we found what we need. 36 return true; 37 } else { 38 if (!precise && entry->GetClass()->CannotBeAssignedFromOtherTypes()) { 39 // We weren't looking for a precise reference, as we're looking up based on a descriptor, but 40 // we found a matching entry based on the descriptor. Return the precise entry in that case. 41 return true; 42 } 43 return false; 44 } 45 } 46 47 void RegTypeCache::FillPrimitiveAndSmallConstantTypes() { 48 entries_.push_back(UndefinedType::GetInstance()); 49 entries_.push_back(ConflictType::GetInstance()); 50 entries_.push_back(BooleanType::GetInstance()); 51 entries_.push_back(ByteType::GetInstance()); 52 entries_.push_back(ShortType::GetInstance()); 53 entries_.push_back(CharType::GetInstance()); 54 entries_.push_back(IntegerType::GetInstance()); 55 entries_.push_back(LongLoType::GetInstance()); 56 entries_.push_back(LongHiType::GetInstance()); 57 entries_.push_back(FloatType::GetInstance()); 58 entries_.push_back(DoubleLoType::GetInstance()); 59 entries_.push_back(DoubleHiType::GetInstance()); 60 for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) { 61 int32_t i = value - kMinSmallConstant; 62 DCHECK_EQ(entries_.size(), small_precise_constants_[i]->GetId()); 63 entries_.push_back(small_precise_constants_[i]); 64 } 65 DCHECK_EQ(entries_.size(), primitive_count_); 66 } 67 68 RegType& RegTypeCache::FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, 69 bool precise) { 70 DCHECK(RegTypeCache::primitive_initialized_); 71 if (descriptor[1] == '\0') { 72 switch (descriptor[0]) { 73 case 'Z': 74 return Boolean(); 75 case 'B': 76 return Byte(); 77 case 'S': 78 return Short(); 79 case 'C': 80 return Char(); 81 case 'I': 82 return Integer(); 83 case 'J': 84 return LongLo(); 85 case 'F': 86 return Float(); 87 case 'D': 88 return DoubleLo(); 89 case 'V': // For void types, conflict types. 90 default: 91 return Conflict(); 92 } 93 } else if (descriptor[0] == 'L' || descriptor[0] == '[') { 94 return From(loader, descriptor, precise); 95 } else { 96 return Conflict(); 97 } 98 }; 99 100 RegType& RegTypeCache::RegTypeFromPrimitiveType(Primitive::Type prim_type) const { 101 CHECK(RegTypeCache::primitive_initialized_); 102 switch (prim_type) { 103 case Primitive::kPrimBoolean: 104 return *BooleanType::GetInstance(); 105 case Primitive::kPrimByte: 106 return *ByteType::GetInstance(); 107 case Primitive::kPrimShort: 108 return *ShortType::GetInstance(); 109 case Primitive::kPrimChar: 110 return *CharType::GetInstance(); 111 case Primitive::kPrimInt: 112 return *IntegerType::GetInstance(); 113 case Primitive::kPrimLong: 114 return *LongLoType::GetInstance(); 115 case Primitive::kPrimFloat: 116 return *FloatType::GetInstance(); 117 case Primitive::kPrimDouble: 118 return *DoubleLoType::GetInstance(); 119 case Primitive::kPrimVoid: 120 default: 121 return *ConflictType::GetInstance(); 122 } 123 } 124 125 bool RegTypeCache::MatchDescriptor(size_t idx, const StringPiece& descriptor, bool precise) { 126 RegType* entry = entries_[idx]; 127 if (descriptor != entry->descriptor_) { 128 return false; 129 } 130 if (entry->HasClass()) { 131 return MatchingPrecisionForClass(entry, precise); 132 } 133 // There is no notion of precise unresolved references, the precise information is just dropped 134 // on the floor. 135 DCHECK(entry->IsUnresolvedReference()); 136 return true; 137 } 138 139 mirror::Class* RegTypeCache::ResolveClass(const char* descriptor, mirror::ClassLoader* loader) { 140 // Class was not found, must create new type. 141 // Try resolving class 142 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 143 Thread* self = Thread::Current(); 144 StackHandleScope<1> hs(self); 145 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(loader)); 146 mirror::Class* klass = NULL; 147 if (can_load_classes_) { 148 klass = class_linker->FindClass(self, descriptor, class_loader); 149 } else { 150 klass = class_linker->LookupClass(descriptor, ComputeModifiedUtf8Hash(descriptor), loader); 151 if (klass != nullptr && !klass->IsLoaded()) { 152 // We found the class but without it being loaded its not safe for use. 153 klass = nullptr; 154 } 155 } 156 return klass; 157 } 158 159 RegType& RegTypeCache::From(mirror::ClassLoader* loader, const char* descriptor, 160 bool precise) { 161 // Try looking up the class in the cache first. We use a StringPiece to avoid continual strlen 162 // operations on the descriptor. 163 StringPiece descriptor_sp(descriptor); 164 for (size_t i = primitive_count_; i < entries_.size(); i++) { 165 if (MatchDescriptor(i, descriptor_sp, precise)) { 166 return *(entries_[i]); 167 } 168 } 169 // Class not found in the cache, will create a new type for that. 170 // Try resolving class. 171 mirror::Class* klass = ResolveClass(descriptor, loader); 172 if (klass != NULL) { 173 // Class resolved, first look for the class in the list of entries 174 // Class was not found, must create new type. 175 // To pass the verification, the type should be imprecise, 176 // instantiable or an interface with the precise type set to false. 177 DCHECK(!precise || klass->IsInstantiable()); 178 // Create a precise type if: 179 // 1- Class is final and NOT an interface. a precise interface is meaningless !! 180 // 2- Precise Flag passed as true. 181 RegType* entry; 182 // Create an imprecise type if we can't tell for a fact that it is precise. 183 if (klass->CannotBeAssignedFromOtherTypes() || precise) { 184 DCHECK(!(klass->IsAbstract()) || klass->IsArrayClass()); 185 DCHECK(!klass->IsInterface()); 186 entry = new PreciseReferenceType(klass, descriptor_sp.as_string(), entries_.size()); 187 } else { 188 entry = new ReferenceType(klass, descriptor_sp.as_string(), entries_.size()); 189 } 190 AddEntry(entry); 191 return *entry; 192 } else { // Class not resolved. 193 // We tried loading the class and failed, this might get an exception raised 194 // so we want to clear it before we go on. 195 if (can_load_classes_) { 196 DCHECK(Thread::Current()->IsExceptionPending()); 197 Thread::Current()->ClearException(); 198 } else { 199 DCHECK(!Thread::Current()->IsExceptionPending()); 200 } 201 if (IsValidDescriptor(descriptor)) { 202 RegType* entry = new UnresolvedReferenceType(descriptor_sp.as_string(), entries_.size()); 203 AddEntry(entry); 204 return *entry; 205 } else { 206 // The descriptor is broken return the unknown type as there's nothing sensible that 207 // could be done at runtime 208 return Conflict(); 209 } 210 } 211 } 212 213 RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* klass, bool precise) { 214 DCHECK(klass != nullptr); 215 if (klass->IsPrimitive()) { 216 // Note: precise isn't used for primitive classes. A char is assignable to an int. All 217 // primitive classes are final. 218 return RegTypeFromPrimitiveType(klass->GetPrimitiveType()); 219 } else { 220 // Look for the reference in the list of entries to have. 221 for (size_t i = primitive_count_; i < entries_.size(); i++) { 222 RegType* cur_entry = entries_[i]; 223 if (cur_entry->klass_.Read() == klass && MatchingPrecisionForClass(cur_entry, precise)) { 224 return *cur_entry; 225 } 226 } 227 // No reference to the class was found, create new reference. 228 RegType* entry; 229 if (precise) { 230 entry = new PreciseReferenceType(klass, descriptor, entries_.size()); 231 } else { 232 entry = new ReferenceType(klass, descriptor, entries_.size()); 233 } 234 AddEntry(entry); 235 return *entry; 236 } 237 } 238 239 RegTypeCache::RegTypeCache(bool can_load_classes) : can_load_classes_(can_load_classes) { 240 if (kIsDebugBuild && can_load_classes) { 241 Thread::Current()->AssertThreadSuspensionIsAllowable(); 242 } 243 entries_.reserve(64); 244 FillPrimitiveAndSmallConstantTypes(); 245 } 246 247 RegTypeCache::~RegTypeCache() { 248 CHECK_LE(primitive_count_, entries_.size()); 249 // Delete only the non primitive types. 250 if (entries_.size() == kNumPrimitivesAndSmallConstants) { 251 // All entries are from the global pool, nothing to delete. 252 return; 253 } 254 std::vector<RegType*>::iterator non_primitive_begin = entries_.begin(); 255 std::advance(non_primitive_begin, kNumPrimitivesAndSmallConstants); 256 STLDeleteContainerPointers(non_primitive_begin, entries_.end()); 257 } 258 259 void RegTypeCache::ShutDown() { 260 if (RegTypeCache::primitive_initialized_) { 261 UndefinedType::Destroy(); 262 ConflictType::Destroy(); 263 BooleanType::Destroy(); 264 ByteType::Destroy(); 265 ShortType::Destroy(); 266 CharType::Destroy(); 267 IntegerType::Destroy(); 268 LongLoType::Destroy(); 269 LongHiType::Destroy(); 270 FloatType::Destroy(); 271 DoubleLoType::Destroy(); 272 DoubleHiType::Destroy(); 273 for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) { 274 PreciseConstType* type = small_precise_constants_[value - kMinSmallConstant]; 275 delete type; 276 small_precise_constants_[value - kMinSmallConstant] = nullptr; 277 } 278 RegTypeCache::primitive_initialized_ = false; 279 RegTypeCache::primitive_count_ = 0; 280 } 281 } 282 283 template <class Type> 284 Type* RegTypeCache::CreatePrimitiveTypeInstance(const std::string& descriptor) { 285 mirror::Class* klass = NULL; 286 // Try loading the class from linker. 287 if (!descriptor.empty()) { 288 klass = art::Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(), 289 descriptor.c_str()); 290 } 291 Type* entry = Type::CreateInstance(klass, descriptor, RegTypeCache::primitive_count_); 292 RegTypeCache::primitive_count_++; 293 return entry; 294 } 295 296 void RegTypeCache::CreatePrimitiveAndSmallConstantTypes() { 297 CreatePrimitiveTypeInstance<UndefinedType>(""); 298 CreatePrimitiveTypeInstance<ConflictType>(""); 299 CreatePrimitiveTypeInstance<BooleanType>("Z"); 300 CreatePrimitiveTypeInstance<ByteType>("B"); 301 CreatePrimitiveTypeInstance<ShortType>("S"); 302 CreatePrimitiveTypeInstance<CharType>("C"); 303 CreatePrimitiveTypeInstance<IntegerType>("I"); 304 CreatePrimitiveTypeInstance<LongLoType>("J"); 305 CreatePrimitiveTypeInstance<LongHiType>("J"); 306 CreatePrimitiveTypeInstance<FloatType>("F"); 307 CreatePrimitiveTypeInstance<DoubleLoType>("D"); 308 CreatePrimitiveTypeInstance<DoubleHiType>("D"); 309 for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) { 310 PreciseConstType* type = new PreciseConstType(value, primitive_count_); 311 small_precise_constants_[value - kMinSmallConstant] = type; 312 primitive_count_++; 313 } 314 } 315 316 RegType& RegTypeCache::FromUnresolvedMerge(RegType& left, RegType& right) { 317 std::set<uint16_t> types; 318 if (left.IsUnresolvedMergedReference()) { 319 types = (down_cast<UnresolvedMergedType*>(&left))->GetMergedTypes(); 320 } else { 321 types.insert(left.GetId()); 322 } 323 if (right.IsUnresolvedMergedReference()) { 324 std::set<uint16_t> right_types = (down_cast<UnresolvedMergedType*>(&right))->GetMergedTypes(); 325 types.insert(right_types.begin(), right_types.end()); 326 } else { 327 types.insert(right.GetId()); 328 } 329 // Check if entry already exists. 330 for (size_t i = primitive_count_; i < entries_.size(); i++) { 331 RegType* cur_entry = entries_[i]; 332 if (cur_entry->IsUnresolvedMergedReference()) { 333 std::set<uint16_t> cur_entry_types = 334 (down_cast<UnresolvedMergedType*>(cur_entry))->GetMergedTypes(); 335 if (cur_entry_types == types) { 336 return *cur_entry; 337 } 338 } 339 } 340 // Create entry. 341 RegType* entry = new UnresolvedMergedType(left.GetId(), right.GetId(), this, entries_.size()); 342 AddEntry(entry); 343 if (kIsDebugBuild) { 344 UnresolvedMergedType* tmp_entry = down_cast<UnresolvedMergedType*>(entry); 345 std::set<uint16_t> check_types = tmp_entry->GetMergedTypes(); 346 CHECK(check_types == types); 347 } 348 return *entry; 349 } 350 351 RegType& RegTypeCache::FromUnresolvedSuperClass(RegType& child) { 352 // Check if entry already exists. 353 for (size_t i = primitive_count_; i < entries_.size(); i++) { 354 RegType* cur_entry = entries_[i]; 355 if (cur_entry->IsUnresolvedSuperClass()) { 356 UnresolvedSuperClass* tmp_entry = 357 down_cast<UnresolvedSuperClass*>(cur_entry); 358 uint16_t unresolved_super_child_id = 359 tmp_entry->GetUnresolvedSuperClassChildId(); 360 if (unresolved_super_child_id == child.GetId()) { 361 return *cur_entry; 362 } 363 } 364 } 365 RegType* entry = new UnresolvedSuperClass(child.GetId(), this, entries_.size()); 366 AddEntry(entry); 367 return *entry; 368 } 369 370 UninitializedType& RegTypeCache::Uninitialized(RegType& type, uint32_t allocation_pc) { 371 UninitializedType* entry = NULL; 372 const std::string& descriptor(type.GetDescriptor()); 373 if (type.IsUnresolvedTypes()) { 374 for (size_t i = primitive_count_; i < entries_.size(); i++) { 375 RegType* cur_entry = entries_[i]; 376 if (cur_entry->IsUnresolvedAndUninitializedReference() && 377 down_cast<UnresolvedUninitializedRefType*>(cur_entry)->GetAllocationPc() == allocation_pc && 378 (cur_entry->GetDescriptor() == descriptor)) { 379 return *down_cast<UnresolvedUninitializedRefType*>(cur_entry); 380 } 381 } 382 entry = new UnresolvedUninitializedRefType(descriptor, allocation_pc, entries_.size()); 383 } else { 384 mirror::Class* klass = type.GetClass(); 385 for (size_t i = primitive_count_; i < entries_.size(); i++) { 386 RegType* cur_entry = entries_[i]; 387 if (cur_entry->IsUninitializedReference() && 388 down_cast<UninitializedReferenceType*>(cur_entry) 389 ->GetAllocationPc() == allocation_pc && 390 cur_entry->GetClass() == klass) { 391 return *down_cast<UninitializedReferenceType*>(cur_entry); 392 } 393 } 394 entry = new UninitializedReferenceType(klass, descriptor, allocation_pc, entries_.size()); 395 } 396 AddEntry(entry); 397 return *entry; 398 } 399 400 RegType& RegTypeCache::FromUninitialized(RegType& uninit_type) { 401 RegType* entry; 402 403 if (uninit_type.IsUnresolvedTypes()) { 404 const std::string& descriptor(uninit_type.GetDescriptor()); 405 for (size_t i = primitive_count_; i < entries_.size(); i++) { 406 RegType* cur_entry = entries_[i]; 407 if (cur_entry->IsUnresolvedReference() && 408 cur_entry->GetDescriptor() == descriptor) { 409 return *cur_entry; 410 } 411 } 412 entry = new UnresolvedReferenceType(descriptor, entries_.size()); 413 } else { 414 mirror::Class* klass = uninit_type.GetClass(); 415 if (uninit_type.IsUninitializedThisReference() && !klass->IsFinal()) { 416 // For uninitialized "this reference" look for reference types that are not precise. 417 for (size_t i = primitive_count_; i < entries_.size(); i++) { 418 RegType* cur_entry = entries_[i]; 419 if (cur_entry->IsReference() && cur_entry->GetClass() == klass) { 420 return *cur_entry; 421 } 422 } 423 entry = new ReferenceType(klass, "", entries_.size()); 424 } else if (klass->IsInstantiable()) { 425 // We're uninitialized because of allocation, look or create a precise type as allocations 426 // may only create objects of that type. 427 for (size_t i = primitive_count_; i < entries_.size(); i++) { 428 RegType* cur_entry = entries_[i]; 429 if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) { 430 return *cur_entry; 431 } 432 } 433 entry = new PreciseReferenceType(klass, uninit_type.GetDescriptor(), entries_.size()); 434 } else { 435 return Conflict(); 436 } 437 } 438 AddEntry(entry); 439 return *entry; 440 } 441 442 ImpreciseConstType& RegTypeCache::ByteConstant() { 443 ConstantType& result = FromCat1Const(std::numeric_limits<jbyte>::min(), false); 444 DCHECK(result.IsImpreciseConstant()); 445 return *down_cast<ImpreciseConstType*>(&result); 446 } 447 448 ImpreciseConstType& RegTypeCache::CharConstant() { 449 int32_t jchar_max = static_cast<int32_t>(std::numeric_limits<jchar>::max()); 450 ConstantType& result = FromCat1Const(jchar_max, false); 451 DCHECK(result.IsImpreciseConstant()); 452 return *down_cast<ImpreciseConstType*>(&result); 453 } 454 455 ImpreciseConstType& RegTypeCache::ShortConstant() { 456 ConstantType& result = FromCat1Const(std::numeric_limits<jshort>::min(), false); 457 DCHECK(result.IsImpreciseConstant()); 458 return *down_cast<ImpreciseConstType*>(&result); 459 } 460 461 ImpreciseConstType& RegTypeCache::IntConstant() { 462 ConstantType& result = FromCat1Const(std::numeric_limits<jint>::max(), false); 463 DCHECK(result.IsImpreciseConstant()); 464 return *down_cast<ImpreciseConstType*>(&result); 465 } 466 467 ImpreciseConstType& RegTypeCache::PosByteConstant() { 468 ConstantType& result = FromCat1Const(std::numeric_limits<jbyte>::max(), false); 469 DCHECK(result.IsImpreciseConstant()); 470 return *down_cast<ImpreciseConstType*>(&result); 471 } 472 473 ImpreciseConstType& RegTypeCache::PosShortConstant() { 474 ConstantType& result = FromCat1Const(std::numeric_limits<jshort>::max(), false); 475 DCHECK(result.IsImpreciseConstant()); 476 return *down_cast<ImpreciseConstType*>(&result); 477 } 478 479 UninitializedType& RegTypeCache::UninitializedThisArgument(RegType& type) { 480 UninitializedType* entry; 481 const std::string& descriptor(type.GetDescriptor()); 482 if (type.IsUnresolvedTypes()) { 483 for (size_t i = primitive_count_; i < entries_.size(); i++) { 484 RegType* cur_entry = entries_[i]; 485 if (cur_entry->IsUnresolvedAndUninitializedThisReference() && 486 cur_entry->GetDescriptor() == descriptor) { 487 return *down_cast<UninitializedType*>(cur_entry); 488 } 489 } 490 entry = new UnresolvedUninitializedThisRefType(descriptor, entries_.size()); 491 } else { 492 mirror::Class* klass = type.GetClass(); 493 for (size_t i = primitive_count_; i < entries_.size(); i++) { 494 RegType* cur_entry = entries_[i]; 495 if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) { 496 return *down_cast<UninitializedType*>(cur_entry); 497 } 498 } 499 entry = new UninitializedThisReferenceType(klass, descriptor, entries_.size()); 500 } 501 AddEntry(entry); 502 return *entry; 503 } 504 505 ConstantType& RegTypeCache::FromCat1NonSmallConstant(int32_t value, bool precise) { 506 for (size_t i = primitive_count_; i < entries_.size(); i++) { 507 RegType* cur_entry = entries_[i]; 508 if (cur_entry->klass_.IsNull() && cur_entry->IsConstant() && 509 cur_entry->IsPreciseConstant() == precise && 510 (down_cast<ConstantType*>(cur_entry))->ConstantValue() == value) { 511 return *down_cast<ConstantType*>(cur_entry); 512 } 513 } 514 ConstantType* entry; 515 if (precise) { 516 entry = new PreciseConstType(value, entries_.size()); 517 } else { 518 entry = new ImpreciseConstType(value, entries_.size()); 519 } 520 AddEntry(entry); 521 return *entry; 522 } 523 524 ConstantType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) { 525 for (size_t i = primitive_count_; i < entries_.size(); i++) { 526 RegType* cur_entry = entries_[i]; 527 if (cur_entry->IsConstantLo() && (cur_entry->IsPrecise() == precise) && 528 (down_cast<ConstantType*>(cur_entry))->ConstantValueLo() == value) { 529 return *down_cast<ConstantType*>(cur_entry); 530 } 531 } 532 ConstantType* entry; 533 if (precise) { 534 entry = new PreciseConstLoType(value, entries_.size()); 535 } else { 536 entry = new ImpreciseConstLoType(value, entries_.size()); 537 } 538 AddEntry(entry); 539 return *entry; 540 } 541 542 ConstantType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) { 543 for (size_t i = primitive_count_; i < entries_.size(); i++) { 544 RegType* cur_entry = entries_[i]; 545 if (cur_entry->IsConstantHi() && (cur_entry->IsPrecise() == precise) && 546 (down_cast<ConstantType*>(cur_entry))->ConstantValueHi() == value) { 547 return *down_cast<ConstantType*>(cur_entry); 548 } 549 } 550 ConstantType* entry; 551 if (precise) { 552 entry = new PreciseConstHiType(value, entries_.size()); 553 } else { 554 entry = new ImpreciseConstHiType(value, entries_.size()); 555 } 556 AddEntry(entry); 557 return *entry; 558 } 559 560 RegType& RegTypeCache::GetComponentType(RegType& array, mirror::ClassLoader* loader) { 561 if (!array.IsArrayTypes()) { 562 return Conflict(); 563 } else if (array.IsUnresolvedTypes()) { 564 const std::string& descriptor(array.GetDescriptor()); 565 const std::string component(descriptor.substr(1, descriptor.size() - 1)); 566 return FromDescriptor(loader, component.c_str(), false); 567 } else { 568 mirror::Class* klass = array.GetClass()->GetComponentType(); 569 std::string temp; 570 if (klass->IsErroneous()) { 571 // Arrays may have erroneous component types, use unresolved in that case. 572 // We assume that the primitive classes are not erroneous, so we know it is a 573 // reference type. 574 return FromDescriptor(loader, klass->GetDescriptor(&temp), false); 575 } else { 576 return FromClass(klass->GetDescriptor(&temp), klass, 577 klass->CannotBeAssignedFromOtherTypes()); 578 } 579 } 580 } 581 582 void RegTypeCache::Dump(std::ostream& os) { 583 for (size_t i = 0; i < entries_.size(); i++) { 584 RegType* cur_entry = entries_[i]; 585 if (cur_entry != NULL) { 586 os << i << ": " << cur_entry->Dump() << "\n"; 587 } 588 } 589 } 590 591 void RegTypeCache::VisitStaticRoots(RootCallback* callback, void* arg) { 592 // Visit the primitive types, this is required since if there are no active verifiers they wont 593 // be in the entries array, and therefore not visited as roots. 594 if (primitive_initialized_) { 595 Undefined().VisitRoots(callback, arg); 596 Conflict().VisitRoots(callback, arg); 597 Boolean().VisitRoots(callback, arg); 598 Byte().VisitRoots(callback, arg); 599 Short().VisitRoots(callback, arg); 600 Char().VisitRoots(callback, arg); 601 Integer().VisitRoots(callback, arg); 602 LongLo().VisitRoots(callback, arg); 603 LongHi().VisitRoots(callback, arg); 604 Float().VisitRoots(callback, arg); 605 DoubleLo().VisitRoots(callback, arg); 606 DoubleHi().VisitRoots(callback, arg); 607 for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) { 608 small_precise_constants_[value - kMinSmallConstant]->VisitRoots(callback, arg); 609 } 610 } 611 } 612 613 void RegTypeCache::VisitRoots(RootCallback* callback, void* arg) { 614 for (RegType* entry : entries_) { 615 entry->VisitRoots(callback, arg); 616 } 617 } 618 619 void RegTypeCache::AddEntry(RegType* new_entry) { 620 entries_.push_back(new_entry); 621 } 622 623 } // namespace verifier 624 } // namespace art 625