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