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 "dex_file-inl.h"
     21 #include "mirror/class-inl.h"
     22 #include "mirror/object-inl.h"
     23 #include "object_utils.h"
     24 
     25 namespace art {
     26 namespace verifier {
     27 
     28 bool RegTypeCache::primitive_initialized_ = false;
     29 uint16_t RegTypeCache::primitive_start_ = 0;
     30 uint16_t RegTypeCache::primitive_count_ = 0;
     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::FillPrimitiveTypes() {
     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   DCHECK_EQ(entries_.size(), primitive_count_);
     61 }
     62 
     63 const RegType& RegTypeCache::FromDescriptor(mirror::ClassLoader* loader, const char* descriptor,
     64                                             bool precise) {
     65   DCHECK(RegTypeCache::primitive_initialized_);
     66   if (descriptor[1] == '\0') {
     67     switch (descriptor[0]) {
     68       case 'Z':
     69         return Boolean();
     70       case 'B':
     71         return Byte();
     72       case 'S':
     73         return Short();
     74       case 'C':
     75         return Char();
     76       case 'I':
     77         return Integer();
     78       case 'J':
     79         return LongLo();
     80       case 'F':
     81         return Float();
     82       case 'D':
     83         return DoubleLo();
     84       case 'V':  // For void types, conflict types.
     85       default:
     86         return Conflict();
     87     }
     88   } else if (descriptor[0] == 'L' || descriptor[0] == '[') {
     89     return From(loader, descriptor, precise);
     90   } else {
     91     return Conflict();
     92   }
     93 };
     94 
     95 const RegType& RegTypeCache::RegTypeFromPrimitiveType(Primitive::Type prim_type) const {
     96   CHECK(RegTypeCache::primitive_initialized_);
     97   switch (prim_type) {
     98     case Primitive::kPrimBoolean:
     99       return *BooleanType::GetInstance();
    100     case Primitive::kPrimByte:
    101       return *ByteType::GetInstance();
    102     case Primitive::kPrimShort:
    103       return *ShortType::GetInstance();
    104     case Primitive::kPrimChar:
    105       return *CharType::GetInstance();
    106     case Primitive::kPrimInt:
    107       return *IntegerType::GetInstance();
    108     case Primitive::kPrimLong:
    109       return *LongLoType::GetInstance();
    110     case Primitive::kPrimFloat:
    111       return *FloatType::GetInstance();
    112     case Primitive::kPrimDouble:
    113       return *DoubleLoType::GetInstance();
    114     case Primitive::kPrimVoid:
    115     default:
    116       return *ConflictType::GetInstance();
    117   }
    118 }
    119 
    120 bool RegTypeCache::MatchDescriptor(size_t idx, const char* descriptor, bool precise) {
    121   RegType* entry = entries_[idx];
    122   if (entry->descriptor_ != descriptor) {
    123     return false;
    124   }
    125   if (entry->HasClass()) {
    126     return MatchingPrecisionForClass(entry, precise);
    127   }
    128   // There is no notion of precise unresolved references, the precise information is just dropped
    129   // on the floor.
    130   DCHECK(entry->IsUnresolvedReference());
    131   return true;
    132 }
    133 
    134 mirror::Class* RegTypeCache::ResolveClass(const char* descriptor, mirror::ClassLoader* loader) {
    135   // Class was not found, must create new type.
    136   // Try resolving class
    137   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    138   mirror::Class* klass = NULL;
    139   if (can_load_classes_) {
    140     klass = class_linker->FindClass(descriptor, loader);
    141   } else {
    142     klass = class_linker->LookupClass(descriptor, loader);
    143     if (klass != NULL && !klass->IsLoaded()) {
    144       // We found the class but without it being loaded its not safe for use.
    145       klass = NULL;
    146     }
    147   }
    148   return klass;
    149 }
    150 
    151 void RegTypeCache::ClearException() {
    152   if (can_load_classes_) {
    153     DCHECK(Thread::Current()->IsExceptionPending());
    154     Thread::Current()->ClearException();
    155   } else {
    156     DCHECK(!Thread::Current()->IsExceptionPending());
    157   }
    158 }
    159 
    160 const RegType& RegTypeCache::From(mirror::ClassLoader* loader, const char* descriptor,
    161                                   bool precise) {
    162   // Try looking up the class in the cache first.
    163   for (size_t i = primitive_count_; i < entries_.size(); i++) {
    164     if (MatchDescriptor(i, descriptor, precise)) {
    165       return *(entries_[i]);
    166     }
    167   }
    168   // Class not found in the cache, will create a new type for that.
    169   // Try resolving class.
    170   mirror::Class* klass = ResolveClass(descriptor, loader);
    171   if (klass != NULL) {
    172     // Class resolved, first look for the class in the list of entries
    173     // Class was not found, must create new type.
    174     // To pass the verification, the type should be imprecise,
    175     // instantiable or an interface with the precise type set to false.
    176     DCHECK(!precise || klass->IsInstantiable());
    177     // Create a precise type if:
    178     // 1- Class is final and NOT an interface. a precise interface is meaningless !!
    179     // 2- Precise Flag passed as true.
    180     RegType* entry;
    181     // Create an imprecise type if we can't tell for a fact that it is precise.
    182     if (klass->CannotBeAssignedFromOtherTypes() || precise) {
    183       DCHECK(!(klass->IsAbstract()) || klass->IsArrayClass());
    184       DCHECK(!klass->IsInterface());
    185       entry = new PreciseReferenceType(klass, descriptor, entries_.size());
    186     } else {
    187       entry = new ReferenceType(klass, descriptor, entries_.size());
    188     }
    189     entries_.push_back(entry);
    190     return *entry;
    191   } else {  // Class not resolved.
    192     // We tried loading the class and failed, this might get an exception raised
    193     // so we want to clear it before we go on.
    194     ClearException();
    195     if (IsValidDescriptor(descriptor)) {
    196       RegType* entry = new UnresolvedReferenceType(descriptor, entries_.size());
    197       entries_.push_back(entry);
    198       return *entry;
    199     } else {
    200       // The descriptor is broken return the unknown type as there's nothing sensible that
    201       // could be done at runtime
    202       return Conflict();
    203     }
    204   }
    205 }
    206 
    207 const RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* klass, bool precise) {
    208   if (klass->IsPrimitive()) {
    209     // Note: precise isn't used for primitive classes. A char is assignable to an int. All
    210     // primitive classes are final.
    211     return RegTypeFromPrimitiveType(klass->GetPrimitiveType());
    212   } else {
    213     // Look for the reference in the list of entries to have.
    214     for (size_t i = primitive_count_; i < entries_.size(); i++) {
    215       RegType* cur_entry = entries_[i];
    216       if (cur_entry->klass_ == klass && MatchingPrecisionForClass(cur_entry, precise)) {
    217         return *cur_entry;
    218       }
    219     }
    220     // No reference to the class was found, create new reference.
    221     RegType* entry;
    222     if (precise) {
    223       entry = new PreciseReferenceType(klass, descriptor, entries_.size());
    224     } else {
    225       entry = new ReferenceType(klass, descriptor, entries_.size());
    226     }
    227     entries_.push_back(entry);
    228     return *entry;
    229   }
    230 }
    231 
    232 RegTypeCache::~RegTypeCache() {
    233   CHECK_LE(primitive_count_, entries_.size());
    234   // Delete only the non primitive types.
    235   if (entries_.size() == kNumPrimitives) {
    236     // All entries are primitive, nothing to delete.
    237     return;
    238   }
    239   std::vector<RegType*>::iterator non_primitive_begin = entries_.begin();
    240   std::advance(non_primitive_begin, kNumPrimitives);
    241   STLDeleteContainerPointers(non_primitive_begin, entries_.end());
    242 }
    243 
    244 void RegTypeCache::ShutDown() {
    245   if (RegTypeCache::primitive_initialized_) {
    246     UndefinedType::Destroy();
    247     ConflictType::Destroy();
    248     BooleanType::Destroy();
    249     ByteType::Destroy();
    250     ShortType::Destroy();
    251     CharType::Destroy();
    252     IntegerType::Destroy();
    253     LongLoType::Destroy();
    254     LongHiType::Destroy();
    255     FloatType::Destroy();
    256     DoubleLoType::Destroy();
    257     DoubleHiType::Destroy();
    258     RegTypeCache::primitive_initialized_ = false;
    259     RegTypeCache::primitive_count_ = 0;
    260   }
    261 }
    262 
    263 void RegTypeCache::CreatePrimitiveTypes() {
    264   CreatePrimitiveTypeInstance<UndefinedType>("");
    265   CreatePrimitiveTypeInstance<ConflictType>("");
    266   CreatePrimitiveTypeInstance<BooleanType>("Z");
    267   CreatePrimitiveTypeInstance<ByteType>("B");
    268   CreatePrimitiveTypeInstance<ShortType>("S");
    269   CreatePrimitiveTypeInstance<CharType>("C");
    270   CreatePrimitiveTypeInstance<IntegerType>("I");
    271   CreatePrimitiveTypeInstance<LongLoType>("J");
    272   CreatePrimitiveTypeInstance<LongHiType>("J");
    273   CreatePrimitiveTypeInstance<FloatType>("F");
    274   CreatePrimitiveTypeInstance<DoubleLoType>("D");
    275   CreatePrimitiveTypeInstance<DoubleHiType>("D");
    276 }
    277 
    278 const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left, const RegType& right) {
    279   std::set<uint16_t> types;
    280   if (left.IsUnresolvedMergedReference()) {
    281     RegType& non_const(const_cast<RegType&>(left));
    282     types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
    283   } else {
    284     types.insert(left.GetId());
    285   }
    286   if (right.IsUnresolvedMergedReference()) {
    287     RegType& non_const(const_cast<RegType&>(right));
    288     std::set<uint16_t> right_types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
    289     types.insert(right_types.begin(), right_types.end());
    290   } else {
    291     types.insert(right.GetId());
    292   }
    293   // Check if entry already exists.
    294   for (size_t i = primitive_count_; i < entries_.size(); i++) {
    295     RegType* cur_entry = entries_[i];
    296     if (cur_entry->IsUnresolvedMergedReference()) {
    297       std::set<uint16_t> cur_entry_types =
    298           (down_cast<UnresolvedMergedType*>(cur_entry))->GetMergedTypes();
    299       if (cur_entry_types == types) {
    300         return *cur_entry;
    301       }
    302     }
    303   }
    304   // Create entry.
    305   RegType* entry = new UnresolvedMergedType(left.GetId(), right.GetId(), this, entries_.size());
    306   entries_.push_back(entry);
    307   if (kIsDebugBuild) {
    308     UnresolvedMergedType* tmp_entry = down_cast<UnresolvedMergedType*>(entry);
    309     std::set<uint16_t> check_types = tmp_entry->GetMergedTypes();
    310     CHECK(check_types == types);
    311   }
    312   return *entry;
    313 }
    314 
    315 const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
    316   // Check if entry already exists.
    317   for (size_t i = primitive_count_; i < entries_.size(); i++) {
    318     RegType* cur_entry = entries_[i];
    319     if (cur_entry->IsUnresolvedSuperClass()) {
    320       UnresolvedSuperClass* tmp_entry =
    321           down_cast<UnresolvedSuperClass*>(cur_entry);
    322       uint16_t unresolved_super_child_id =
    323           tmp_entry->GetUnresolvedSuperClassChildId();
    324       if (unresolved_super_child_id == child.GetId()) {
    325         return *cur_entry;
    326       }
    327     }
    328   }
    329   RegType* entry = new UnresolvedSuperClass(child.GetId(), this, entries_.size());
    330   entries_.push_back(entry);
    331   return *entry;
    332 }
    333 
    334 const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
    335   RegType* entry = NULL;
    336   RegType* cur_entry = NULL;
    337   const std::string& descriptor(type.GetDescriptor());
    338   if (type.IsUnresolvedTypes()) {
    339     for (size_t i = primitive_count_; i < entries_.size(); i++) {
    340       cur_entry = entries_[i];
    341       if (cur_entry->IsUnresolvedAndUninitializedReference() &&
    342           down_cast<UnresolvedUninitializedRefType*>(cur_entry)->GetAllocationPc() == allocation_pc &&
    343           (cur_entry->GetDescriptor() == descriptor)) {
    344         return *cur_entry;
    345       }
    346     }
    347     entry = new UnresolvedUninitializedRefType(descriptor, allocation_pc, entries_.size());
    348   } else {
    349     mirror::Class* klass = type.GetClass();
    350     for (size_t i = primitive_count_; i < entries_.size(); i++) {
    351       cur_entry = entries_[i];
    352       if (cur_entry->IsUninitializedReference() &&
    353           down_cast<UninitializedReferenceType*>(cur_entry)
    354               ->GetAllocationPc() == allocation_pc &&
    355           cur_entry->GetClass() == klass) {
    356         return *cur_entry;
    357       }
    358     }
    359     entry = new UninitializedReferenceType(klass, descriptor, allocation_pc, entries_.size());
    360   }
    361   entries_.push_back(entry);
    362   return *entry;
    363 }
    364 
    365 const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
    366   RegType* entry;
    367 
    368   if (uninit_type.IsUnresolvedTypes()) {
    369     const std::string& descriptor(uninit_type.GetDescriptor());
    370     for (size_t i = primitive_count_; i < entries_.size(); i++) {
    371       RegType* cur_entry = entries_[i];
    372       if (cur_entry->IsUnresolvedReference() &&
    373           cur_entry->GetDescriptor() == descriptor) {
    374         return *cur_entry;
    375       }
    376     }
    377     entry = new UnresolvedReferenceType(descriptor.c_str(), entries_.size());
    378   } else {
    379     mirror::Class* klass = uninit_type.GetClass();
    380     if (uninit_type.IsUninitializedThisReference() && !klass->IsFinal()) {
    381       // For uninitialized "this reference" look for reference types that are not precise.
    382       for (size_t i = primitive_count_; i < entries_.size(); i++) {
    383         RegType* cur_entry = entries_[i];
    384         if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
    385           return *cur_entry;
    386         }
    387       }
    388       entry = new ReferenceType(klass, "", entries_.size());
    389     } else if (klass->IsInstantiable()) {
    390       // We're uninitialized because of allocation, look or create a precise type as allocations
    391       // may only create objects of that type.
    392       for (size_t i = primitive_count_; i < entries_.size(); i++) {
    393         RegType* cur_entry = entries_[i];
    394         if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
    395           return *cur_entry;
    396         }
    397       }
    398       entry = new PreciseReferenceType(klass, uninit_type.GetDescriptor(), entries_.size());
    399     } else {
    400       return Conflict();
    401     }
    402   }
    403   entries_.push_back(entry);
    404   return *entry;
    405 }
    406 
    407 const RegType& RegTypeCache::ByteConstant() {
    408   return FromCat1Const(std::numeric_limits<jbyte>::min(), false);
    409 }
    410 
    411 const RegType& RegTypeCache::ShortConstant() {
    412   return FromCat1Const(std::numeric_limits<jshort>::min(), false);
    413 }
    414 
    415 const RegType& RegTypeCache::IntConstant() {
    416   return FromCat1Const(std::numeric_limits<jint>::max(), false);
    417 }
    418 
    419 const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
    420   RegType* entry;
    421   const std::string& descriptor(type.GetDescriptor());
    422   if (type.IsUnresolvedTypes()) {
    423     for (size_t i = primitive_count_; i < entries_.size(); i++) {
    424       RegType* cur_entry = entries_[i];
    425       if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
    426           cur_entry->GetDescriptor() == descriptor) {
    427         return *cur_entry;
    428       }
    429     }
    430     entry = new UnresolvedUninitializedThisRefType(descriptor, entries_.size());
    431   } else {
    432     mirror::Class* klass = type.GetClass();
    433     for (size_t i = primitive_count_; i < entries_.size(); i++) {
    434       RegType* cur_entry = entries_[i];
    435       if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
    436         return *cur_entry;
    437       }
    438     }
    439     entry = new UninitializedThisReferenceType(klass, descriptor, entries_.size());
    440   }
    441   entries_.push_back(entry);
    442   return *entry;
    443 }
    444 
    445 const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) {
    446   for (size_t i = primitive_count_; i < entries_.size(); i++) {
    447     RegType* cur_entry = entries_[i];
    448     if (cur_entry->klass_ == NULL && cur_entry->IsConstant() &&
    449         cur_entry->IsPreciseConstant() == precise &&
    450         (down_cast<ConstantType*>(cur_entry))->ConstantValue() == value) {
    451       return *cur_entry;
    452     }
    453   }
    454   RegType* entry;
    455   if (precise) {
    456     entry = new PreciseConstType(value, entries_.size());
    457   } else {
    458     entry = new ImpreciseConstType(value, entries_.size());
    459   }
    460   entries_.push_back(entry);
    461   return *entry;
    462 }
    463 
    464 const RegType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) {
    465   for (size_t i = primitive_count_; i < entries_.size(); i++) {
    466     RegType* cur_entry = entries_[i];
    467     if (cur_entry->IsConstantLo() && (cur_entry->IsPrecise() == precise) &&
    468         (down_cast<ConstantType*>(cur_entry))->ConstantValueLo() == value) {
    469       return *cur_entry;
    470     }
    471   }
    472   RegType* entry;
    473   if (precise) {
    474     entry = new PreciseConstLoType(value, entries_.size());
    475   } else {
    476     entry = new ImpreciseConstLoType(value, entries_.size());
    477   }
    478   entries_.push_back(entry);
    479   return *entry;
    480 }
    481 
    482 const RegType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
    483   for (size_t i = primitive_count_; i < entries_.size(); i++) {
    484     RegType* cur_entry = entries_[i];
    485     if (cur_entry->IsConstantHi() && (cur_entry->IsPrecise() == precise) &&
    486         (down_cast<ConstantType*>(cur_entry))->ConstantValueHi() == value) {
    487       return *cur_entry;
    488     }
    489   }
    490   RegType* entry;
    491   if (precise) {
    492     entry = new PreciseConstHiType(value, entries_.size());
    493   } else {
    494     entry = new ImpreciseConstHiType(value, entries_.size());
    495   }
    496   entries_.push_back(entry);
    497   return *entry;
    498 }
    499 
    500 const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::ClassLoader* loader) {
    501   CHECK(array.IsArrayTypes());
    502   if (array.IsUnresolvedTypes()) {
    503     const std::string& descriptor(array.GetDescriptor());
    504     const std::string component(descriptor.substr(1, descriptor.size() - 1));
    505     return FromDescriptor(loader, component.c_str(), false);
    506   } else {
    507     mirror::Class* klass = array.GetClass()->GetComponentType();
    508     return FromClass(ClassHelper(klass).GetDescriptor(), klass,
    509                      klass->CannotBeAssignedFromOtherTypes());
    510   }
    511 }
    512 
    513 void RegTypeCache::Dump(std::ostream& os) {
    514   for (size_t i = 0; i < entries_.size(); i++) {
    515     RegType* cur_entry = entries_[i];
    516     if (cur_entry != NULL) {
    517       os << i << ": " << cur_entry->Dump() << "\n";
    518     }
    519   }
    520 }
    521 
    522 }  // namespace verifier
    523 }  // namespace art
    524