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/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