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-inl.h"
     18 
     19 #include "android-base/stringprintf.h"
     20 
     21 #include "base/arena_bit_vector.h"
     22 #include "base/bit_vector-inl.h"
     23 #include "base/casts.h"
     24 #include "class_linker-inl.h"
     25 #include "dex/descriptors_names.h"
     26 #include "dex/dex_file-inl.h"
     27 #include "method_verifier.h"
     28 #include "mirror/class-inl.h"
     29 #include "mirror/class.h"
     30 #include "mirror/object-inl.h"
     31 #include "mirror/object_array-inl.h"
     32 #include "reg_type_cache-inl.h"
     33 #include "scoped_thread_state_change-inl.h"
     34 
     35 #include <limits>
     36 #include <sstream>
     37 
     38 namespace art {
     39 namespace verifier {
     40 
     41 using android::base::StringPrintf;
     42 
     43 const UndefinedType* UndefinedType::instance_ = nullptr;
     44 const ConflictType* ConflictType::instance_ = nullptr;
     45 const BooleanType* BooleanType::instance_ = nullptr;
     46 const ByteType* ByteType::instance_ = nullptr;
     47 const ShortType* ShortType::instance_ = nullptr;
     48 const CharType* CharType::instance_ = nullptr;
     49 const FloatType* FloatType::instance_ = nullptr;
     50 const LongLoType* LongLoType::instance_ = nullptr;
     51 const LongHiType* LongHiType::instance_ = nullptr;
     52 const DoubleLoType* DoubleLoType::instance_ = nullptr;
     53 const DoubleHiType* DoubleHiType::instance_ = nullptr;
     54 const IntegerType* IntegerType::instance_ = nullptr;
     55 const NullType* NullType::instance_ = nullptr;
     56 
     57 PrimitiveType::PrimitiveType(ObjPtr<mirror::Class> klass,
     58                              const std::string_view& descriptor,
     59                              uint16_t cache_id)
     60     : RegType(klass, descriptor, cache_id) {
     61   CHECK(klass != nullptr);
     62   CHECK(!descriptor.empty());
     63 }
     64 
     65 Cat1Type::Cat1Type(ObjPtr<mirror::Class> klass,
     66                    const std::string_view& descriptor,
     67                    uint16_t cache_id)
     68     : PrimitiveType(klass, descriptor, cache_id) {
     69 }
     70 
     71 Cat2Type::Cat2Type(ObjPtr<mirror::Class> klass,
     72                    const std::string_view& descriptor,
     73                    uint16_t cache_id)
     74     : PrimitiveType(klass, descriptor, cache_id) {
     75 }
     76 
     77 std::string PreciseConstType::Dump() const {
     78   std::stringstream result;
     79   uint32_t val = ConstantValue();
     80   if (val == 0) {
     81     CHECK(IsPreciseConstant());
     82     result << "Zero/null";
     83   } else {
     84     result << "Precise ";
     85     if (IsConstantShort()) {
     86       result << StringPrintf("Constant: %d", val);
     87     } else {
     88       result << StringPrintf("Constant: 0x%x", val);
     89     }
     90   }
     91   return result.str();
     92 }
     93 
     94 std::string BooleanType::Dump() const {
     95   return "Boolean";
     96 }
     97 
     98 std::string ConflictType::Dump() const {
     99     return "Conflict";
    100 }
    101 
    102 std::string ByteType::Dump() const {
    103   return "Byte";
    104 }
    105 
    106 std::string ShortType::Dump() const {
    107   return "Short";
    108 }
    109 
    110 std::string CharType::Dump() const {
    111   return "Char";
    112 }
    113 
    114 std::string FloatType::Dump() const {
    115   return "Float";
    116 }
    117 
    118 std::string LongLoType::Dump() const {
    119   return "Long (Low Half)";
    120 }
    121 
    122 std::string LongHiType::Dump() const {
    123   return "Long (High Half)";
    124 }
    125 
    126 std::string DoubleLoType::Dump() const {
    127   return "Double (Low Half)";
    128 }
    129 
    130 std::string DoubleHiType::Dump() const {
    131   return "Double (High Half)";
    132 }
    133 
    134 std::string IntegerType::Dump() const {
    135   return "Integer";
    136 }
    137 
    138 const DoubleHiType* DoubleHiType::CreateInstance(ObjPtr<mirror::Class> klass,
    139                                                  const std::string_view& descriptor,
    140                                                  uint16_t cache_id) {
    141   CHECK(instance_ == nullptr);
    142   instance_ = new DoubleHiType(klass, descriptor, cache_id);
    143   return instance_;
    144 }
    145 
    146 void DoubleHiType::Destroy() {
    147   if (instance_ != nullptr) {
    148     delete instance_;
    149     instance_ = nullptr;
    150   }
    151 }
    152 
    153 const DoubleLoType* DoubleLoType::CreateInstance(ObjPtr<mirror::Class> klass,
    154                                                  const std::string_view& descriptor,
    155                                                  uint16_t cache_id) {
    156   CHECK(instance_ == nullptr);
    157   instance_ = new DoubleLoType(klass, descriptor, cache_id);
    158   return instance_;
    159 }
    160 
    161 void DoubleLoType::Destroy() {
    162   if (instance_ != nullptr) {
    163     delete instance_;
    164     instance_ = nullptr;
    165   }
    166 }
    167 
    168 const LongLoType* LongLoType::CreateInstance(ObjPtr<mirror::Class> klass,
    169                                              const std::string_view& descriptor,
    170                                              uint16_t cache_id) {
    171   CHECK(instance_ == nullptr);
    172   instance_ = new LongLoType(klass, descriptor, cache_id);
    173   return instance_;
    174 }
    175 
    176 const LongHiType* LongHiType::CreateInstance(ObjPtr<mirror::Class> klass,
    177                                              const std::string_view& descriptor,
    178                                              uint16_t cache_id) {
    179   CHECK(instance_ == nullptr);
    180   instance_ = new LongHiType(klass, descriptor, cache_id);
    181   return instance_;
    182 }
    183 
    184 void LongHiType::Destroy() {
    185   if (instance_ != nullptr) {
    186     delete instance_;
    187     instance_ = nullptr;
    188   }
    189 }
    190 
    191 void LongLoType::Destroy() {
    192   if (instance_ != nullptr) {
    193     delete instance_;
    194     instance_ = nullptr;
    195   }
    196 }
    197 
    198 const FloatType* FloatType::CreateInstance(ObjPtr<mirror::Class> klass,
    199                                            const std::string_view& descriptor,
    200                                            uint16_t cache_id) {
    201   CHECK(instance_ == nullptr);
    202   instance_ = new FloatType(klass, descriptor, cache_id);
    203   return instance_;
    204 }
    205 
    206 void FloatType::Destroy() {
    207   if (instance_ != nullptr) {
    208     delete instance_;
    209     instance_ = nullptr;
    210   }
    211 }
    212 
    213 const CharType* CharType::CreateInstance(ObjPtr<mirror::Class> klass,
    214                                          const std::string_view& descriptor,
    215                                          uint16_t cache_id) {
    216   CHECK(instance_ == nullptr);
    217   instance_ = new CharType(klass, descriptor, cache_id);
    218   return instance_;
    219 }
    220 
    221 void CharType::Destroy() {
    222   if (instance_ != nullptr) {
    223     delete instance_;
    224     instance_ = nullptr;
    225   }
    226 }
    227 
    228 const ShortType* ShortType::CreateInstance(ObjPtr<mirror::Class> klass,
    229                                            const std::string_view& descriptor,
    230                                            uint16_t cache_id) {
    231   CHECK(instance_ == nullptr);
    232   instance_ = new ShortType(klass, descriptor, cache_id);
    233   return instance_;
    234 }
    235 
    236 void ShortType::Destroy() {
    237   if (instance_ != nullptr) {
    238     delete instance_;
    239     instance_ = nullptr;
    240   }
    241 }
    242 
    243 const ByteType* ByteType::CreateInstance(ObjPtr<mirror::Class> klass,
    244                                          const std::string_view& descriptor,
    245                                          uint16_t cache_id) {
    246   CHECK(instance_ == nullptr);
    247   instance_ = new ByteType(klass, descriptor, cache_id);
    248   return instance_;
    249 }
    250 
    251 void ByteType::Destroy() {
    252   if (instance_ != nullptr) {
    253     delete instance_;
    254     instance_ = nullptr;
    255   }
    256 }
    257 
    258 const IntegerType* IntegerType::CreateInstance(ObjPtr<mirror::Class> klass,
    259                                                const std::string_view& descriptor,
    260                                                uint16_t cache_id) {
    261   CHECK(instance_ == nullptr);
    262   instance_ = new IntegerType(klass, descriptor, cache_id);
    263   return instance_;
    264 }
    265 
    266 void IntegerType::Destroy() {
    267   if (instance_ != nullptr) {
    268     delete instance_;
    269     instance_ = nullptr;
    270   }
    271 }
    272 
    273 const ConflictType* ConflictType::CreateInstance(ObjPtr<mirror::Class> klass,
    274                                                  const std::string_view& descriptor,
    275                                                  uint16_t cache_id) {
    276   CHECK(instance_ == nullptr);
    277   instance_ = new ConflictType(klass, descriptor, cache_id);
    278   return instance_;
    279 }
    280 
    281 void ConflictType::Destroy() {
    282   if (instance_ != nullptr) {
    283     delete instance_;
    284     instance_ = nullptr;
    285   }
    286 }
    287 
    288 const BooleanType* BooleanType::CreateInstance(ObjPtr<mirror::Class> klass,
    289                                                const std::string_view& descriptor,
    290                                                uint16_t cache_id) {
    291   CHECK(BooleanType::instance_ == nullptr);
    292   instance_ = new BooleanType(klass, descriptor, cache_id);
    293   return BooleanType::instance_;
    294 }
    295 
    296 void BooleanType::Destroy() {
    297   if (BooleanType::instance_ != nullptr) {
    298     delete instance_;
    299     instance_ = nullptr;
    300   }
    301 }
    302 
    303 std::string UndefinedType::Dump() const REQUIRES_SHARED(Locks::mutator_lock_) {
    304   return "Undefined";
    305 }
    306 
    307 const UndefinedType* UndefinedType::CreateInstance(ObjPtr<mirror::Class> klass,
    308                                                    const std::string_view& descriptor,
    309                                                    uint16_t cache_id) {
    310   CHECK(instance_ == nullptr);
    311   instance_ = new UndefinedType(klass, descriptor, cache_id);
    312   return instance_;
    313 }
    314 
    315 void UndefinedType::Destroy() {
    316   if (instance_ != nullptr) {
    317     delete instance_;
    318     instance_ = nullptr;
    319   }
    320 }
    321 
    322 PreciseReferenceType::PreciseReferenceType(ObjPtr<mirror::Class> klass,
    323                                            const std::string_view& descriptor,
    324                                            uint16_t cache_id)
    325     : RegType(klass, descriptor, cache_id) {
    326   // Note: no check for IsInstantiable() here. We may produce this in case an InstantiationError
    327   //       would be thrown at runtime, but we need to continue verification and *not* create a
    328   //       hard failure or abort.
    329   CheckConstructorInvariants(this);
    330 }
    331 
    332 std::string UnresolvedMergedType::Dump() const {
    333   std::stringstream result;
    334   result << "UnresolvedMergedReferences(" << GetResolvedPart().Dump() << " | ";
    335   const BitVector& types = GetUnresolvedTypes();
    336 
    337   bool first = true;
    338   for (uint32_t idx : types.Indexes()) {
    339     if (!first) {
    340       result << ", ";
    341     } else {
    342       first = false;
    343     }
    344     result << reg_type_cache_->GetFromId(idx).Dump();
    345   }
    346   result << ")";
    347   return result.str();
    348 }
    349 
    350 std::string UnresolvedSuperClass::Dump() const {
    351   std::stringstream result;
    352   uint16_t super_type_id = GetUnresolvedSuperClassChildId();
    353   result << "UnresolvedSuperClass(" << reg_type_cache_->GetFromId(super_type_id).Dump() << ")";
    354   return result.str();
    355 }
    356 
    357 std::string UnresolvedReferenceType::Dump() const {
    358   std::stringstream result;
    359   result << "Unresolved Reference: " << PrettyDescriptor(std::string(GetDescriptor()).c_str());
    360   return result.str();
    361 }
    362 
    363 std::string UnresolvedUninitializedRefType::Dump() const {
    364   std::stringstream result;
    365   result << "Unresolved And Uninitialized Reference: "
    366       << PrettyDescriptor(std::string(GetDescriptor()).c_str())
    367       << " Allocation PC: " << GetAllocationPc();
    368   return result.str();
    369 }
    370 
    371 std::string UnresolvedUninitializedThisRefType::Dump() const {
    372   std::stringstream result;
    373   result << "Unresolved And Uninitialized This Reference: "
    374       << PrettyDescriptor(std::string(GetDescriptor()).c_str());
    375   return result.str();
    376 }
    377 
    378 std::string ReferenceType::Dump() const {
    379   std::stringstream result;
    380   result << "Reference: " << mirror::Class::PrettyDescriptor(GetClass());
    381   return result.str();
    382 }
    383 
    384 std::string PreciseReferenceType::Dump() const {
    385   std::stringstream result;
    386   result << "Precise Reference: " << mirror::Class::PrettyDescriptor(GetClass());
    387   return result.str();
    388 }
    389 
    390 std::string UninitializedReferenceType::Dump() const {
    391   std::stringstream result;
    392   result << "Uninitialized Reference: " << mirror::Class::PrettyDescriptor(GetClass());
    393   result << " Allocation PC: " << GetAllocationPc();
    394   return result.str();
    395 }
    396 
    397 std::string UninitializedThisReferenceType::Dump() const {
    398   std::stringstream result;
    399   result << "Uninitialized This Reference: " << mirror::Class::PrettyDescriptor(GetClass());
    400   result << "Allocation PC: " << GetAllocationPc();
    401   return result.str();
    402 }
    403 
    404 std::string ImpreciseConstType::Dump() const {
    405   std::stringstream result;
    406   uint32_t val = ConstantValue();
    407   if (val == 0) {
    408     result << "Zero/null";
    409   } else {
    410     result << "Imprecise ";
    411     if (IsConstantShort()) {
    412       result << StringPrintf("Constant: %d", val);
    413     } else {
    414       result << StringPrintf("Constant: 0x%x", val);
    415     }
    416   }
    417   return result.str();
    418 }
    419 std::string PreciseConstLoType::Dump() const {
    420   std::stringstream result;
    421 
    422   int32_t val = ConstantValueLo();
    423   result << "Precise ";
    424   if (val >= std::numeric_limits<jshort>::min() &&
    425       val <= std::numeric_limits<jshort>::max()) {
    426     result << StringPrintf("Low-half Constant: %d", val);
    427   } else {
    428     result << StringPrintf("Low-half Constant: 0x%x", val);
    429   }
    430   return result.str();
    431 }
    432 
    433 std::string ImpreciseConstLoType::Dump() const {
    434   std::stringstream result;
    435 
    436   int32_t val = ConstantValueLo();
    437   result << "Imprecise ";
    438   if (val >= std::numeric_limits<jshort>::min() &&
    439       val <= std::numeric_limits<jshort>::max()) {
    440     result << StringPrintf("Low-half Constant: %d", val);
    441   } else {
    442     result << StringPrintf("Low-half Constant: 0x%x", val);
    443   }
    444   return result.str();
    445 }
    446 
    447 std::string PreciseConstHiType::Dump() const {
    448   std::stringstream result;
    449   int32_t val = ConstantValueHi();
    450   result << "Precise ";
    451   if (val >= std::numeric_limits<jshort>::min() &&
    452       val <= std::numeric_limits<jshort>::max()) {
    453     result << StringPrintf("High-half Constant: %d", val);
    454   } else {
    455     result << StringPrintf("High-half Constant: 0x%x", val);
    456   }
    457   return result.str();
    458 }
    459 
    460 std::string ImpreciseConstHiType::Dump() const {
    461   std::stringstream result;
    462   int32_t val = ConstantValueHi();
    463   result << "Imprecise ";
    464   if (val >= std::numeric_limits<jshort>::min() &&
    465       val <= std::numeric_limits<jshort>::max()) {
    466     result << StringPrintf("High-half Constant: %d", val);
    467   } else {
    468     result << StringPrintf("High-half Constant: 0x%x", val);
    469   }
    470   return result.str();
    471 }
    472 
    473 const RegType& RegType::HighHalf(RegTypeCache* cache) const {
    474   DCHECK(IsLowHalf());
    475   if (IsLongLo()) {
    476     return cache->LongHi();
    477   } else if (IsDoubleLo()) {
    478     return cache->DoubleHi();
    479   } else {
    480     DCHECK(IsImpreciseConstantLo());
    481     const ConstantType* const_val = down_cast<const ConstantType*>(this);
    482     return cache->FromCat2ConstHi(const_val->ConstantValue(), false);
    483   }
    484 }
    485 
    486 Primitive::Type RegType::GetPrimitiveType() const {
    487   if (IsNonZeroReferenceTypes()) {
    488     return Primitive::kPrimNot;
    489   } else if (IsBooleanTypes()) {
    490     return Primitive::kPrimBoolean;
    491   } else if (IsByteTypes()) {
    492     return Primitive::kPrimByte;
    493   } else if (IsShortTypes()) {
    494     return Primitive::kPrimShort;
    495   } else if (IsCharTypes()) {
    496     return Primitive::kPrimChar;
    497   } else if (IsFloat()) {
    498     return Primitive::kPrimFloat;
    499   } else if (IsIntegralTypes()) {
    500     return Primitive::kPrimInt;
    501   } else if (IsDoubleLo()) {
    502     return Primitive::kPrimDouble;
    503   } else {
    504     DCHECK(IsLongTypes());
    505     return Primitive::kPrimLong;
    506   }
    507 }
    508 
    509 bool UninitializedType::IsUninitializedTypes() const {
    510   return true;
    511 }
    512 
    513 bool UninitializedType::IsNonZeroReferenceTypes() const {
    514   return true;
    515 }
    516 
    517 bool UnresolvedType::IsNonZeroReferenceTypes() const {
    518   return true;
    519 }
    520 
    521 const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
    522   if (!IsUnresolvedTypes()) {
    523     ObjPtr<mirror::Class> super_klass = GetClass()->GetSuperClass();
    524     if (super_klass != nullptr) {
    525       // A super class of a precise type isn't precise as a precise type indicates the register
    526       // holds exactly that type.
    527       std::string temp;
    528       return cache->FromClass(super_klass->GetDescriptor(&temp), super_klass, false);
    529     } else {
    530       return cache->Zero();
    531     }
    532   } else {
    533     if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
    534         GetDescriptor()[0] == '[') {
    535       // Super class of all arrays is Object.
    536       return cache->JavaLangObject(true);
    537     } else {
    538       return cache->FromUnresolvedSuperClass(*this);
    539     }
    540   }
    541 }
    542 
    543 bool RegType::IsJavaLangObject() const REQUIRES_SHARED(Locks::mutator_lock_) {
    544   return IsReference() && GetClass()->IsObjectClass();
    545 }
    546 
    547 bool RegType::IsObjectArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_) {
    548   if (IsUnresolvedTypes()) {
    549     DCHECK(!IsUnresolvedMergedReference());
    550 
    551     if (IsUnresolvedSuperClass()) {
    552       // Cannot be an array, as the superclass of arrays is java.lang.Object (which cannot be
    553       // unresolved).
    554       return false;
    555     }
    556 
    557     // Primitive arrays will always resolve.
    558     DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
    559     return descriptor_[0] == '[';
    560   } else if (HasClass()) {
    561     ObjPtr<mirror::Class> type = GetClass();
    562     return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
    563   } else {
    564     return false;
    565   }
    566 }
    567 
    568 bool RegType::IsArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_) {
    569   if (IsUnresolvedTypes()) {
    570     DCHECK(!IsUnresolvedMergedReference());
    571 
    572     if (IsUnresolvedSuperClass()) {
    573       // Cannot be an array, as the superclass of arrays is java.lang.Object (which cannot be
    574       // unresolved).
    575       return false;
    576     }
    577     return descriptor_[0] == '[';
    578   } else if (HasClass()) {
    579     return GetClass()->IsArrayClass();
    580   } else {
    581     return false;
    582   }
    583 }
    584 
    585 bool RegType::IsJavaLangObjectArray() const {
    586   if (HasClass()) {
    587     ObjPtr<mirror::Class> type = GetClass();
    588     return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
    589   }
    590   return false;
    591 }
    592 
    593 bool RegType::IsInstantiableTypes() const {
    594   return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
    595 }
    596 
    597 static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
    598   return a.IsConstantTypes() ? b : a;
    599 }
    600 
    601 static const RegType& SelectNonConstant2(const RegType& a, const RegType& b) {
    602   return a.IsConstantTypes() ? (b.IsZero() ? a : b) : a;
    603 }
    604 
    605 const RegType& RegType::Merge(const RegType& incoming_type,
    606                               RegTypeCache* reg_types,
    607                               MethodVerifier* verifier) const {
    608   DCHECK(!Equals(incoming_type));  // Trivial equality handled by caller
    609   // Perform pointer equality tests for undefined and conflict to avoid virtual method dispatch.
    610   const UndefinedType& undefined = reg_types->Undefined();
    611   const ConflictType& conflict = reg_types->Conflict();
    612   DCHECK_EQ(this == &undefined, IsUndefined());
    613   DCHECK_EQ(&incoming_type == &undefined, incoming_type.IsUndefined());
    614   DCHECK_EQ(this == &conflict, IsConflict());
    615   DCHECK_EQ(&incoming_type == &conflict, incoming_type.IsConflict());
    616   if (this == &undefined || &incoming_type == &undefined) {
    617     // There is a difference between undefined and conflict. Conflicts may be copied around, but
    618     // not used. Undefined registers must not be copied. So any merge with undefined should return
    619     // undefined.
    620     return undefined;
    621   } else if (this == &conflict || &incoming_type == &conflict) {
    622     return conflict;  // (Conflict MERGE *) or (* MERGE Conflict) => Conflict
    623   } else if (IsConstant() && incoming_type.IsConstant()) {
    624     const ConstantType& type1 = *down_cast<const ConstantType*>(this);
    625     const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
    626     int32_t val1 = type1.ConstantValue();
    627     int32_t val2 = type2.ConstantValue();
    628     if (val1 >= 0 && val2 >= 0) {
    629       // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
    630       if (val1 >= val2) {
    631         if (!type1.IsPreciseConstant()) {
    632           return *this;
    633         } else {
    634           return reg_types->FromCat1Const(val1, false);
    635         }
    636       } else {
    637         if (!type2.IsPreciseConstant()) {
    638           return type2;
    639         } else {
    640           return reg_types->FromCat1Const(val2, false);
    641         }
    642       }
    643     } else if (val1 < 0 && val2 < 0) {
    644       // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
    645       if (val1 <= val2) {
    646         if (!type1.IsPreciseConstant()) {
    647           return *this;
    648         } else {
    649           return reg_types->FromCat1Const(val1, false);
    650         }
    651       } else {
    652         if (!type2.IsPreciseConstant()) {
    653           return type2;
    654         } else {
    655           return reg_types->FromCat1Const(val2, false);
    656         }
    657       }
    658     } else {
    659       // Values are +ve and -ve, choose smallest signed type in which they both fit
    660       if (type1.IsConstantByte()) {
    661         if (type2.IsConstantByte()) {
    662           return reg_types->ByteConstant();
    663         } else if (type2.IsConstantShort()) {
    664           return reg_types->ShortConstant();
    665         } else {
    666           return reg_types->IntConstant();
    667         }
    668       } else if (type1.IsConstantShort()) {
    669         if (type2.IsConstantShort()) {
    670           return reg_types->ShortConstant();
    671         } else {
    672           return reg_types->IntConstant();
    673         }
    674       } else {
    675         return reg_types->IntConstant();
    676       }
    677     }
    678   } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
    679     const ConstantType& type1 = *down_cast<const ConstantType*>(this);
    680     const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
    681     int32_t val1 = type1.ConstantValueLo();
    682     int32_t val2 = type2.ConstantValueLo();
    683     return reg_types->FromCat2ConstLo(val1 | val2, false);
    684   } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
    685     const ConstantType& type1 = *down_cast<const ConstantType*>(this);
    686     const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
    687     int32_t val1 = type1.ConstantValueHi();
    688     int32_t val2 = type2.ConstantValueHi();
    689     return reg_types->FromCat2ConstHi(val1 | val2, false);
    690   } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
    691     if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
    692       return reg_types->Boolean();  // boolean MERGE boolean => boolean
    693     }
    694     if (IsByteTypes() && incoming_type.IsByteTypes()) {
    695       return reg_types->Byte();  // byte MERGE byte => byte
    696     }
    697     if (IsShortTypes() && incoming_type.IsShortTypes()) {
    698       return reg_types->Short();  // short MERGE short => short
    699     }
    700     if (IsCharTypes() && incoming_type.IsCharTypes()) {
    701       return reg_types->Char();  // char MERGE char => char
    702     }
    703     return reg_types->Integer();  // int MERGE * => int
    704   } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
    705              (IsLongTypes() && incoming_type.IsLongTypes()) ||
    706              (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
    707              (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
    708              (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
    709     // check constant case was handled prior to entry
    710     DCHECK(!IsConstant() || !incoming_type.IsConstant());
    711     // float/long/double MERGE float/long/double_constant => float/long/double
    712     return SelectNonConstant(*this, incoming_type);
    713   } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
    714     if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
    715       // Something that is uninitialized hasn't had its constructor called. Unitialized types are
    716       // special. They may only ever be merged with themselves (must be taken care of by the
    717       // caller of Merge(), see the DCHECK on entry). So mark any other merge as conflicting here.
    718       return conflict;
    719     } else if (IsZeroOrNull() || incoming_type.IsZeroOrNull()) {
    720       return SelectNonConstant2(*this, incoming_type);  // 0 MERGE ref => ref
    721     } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
    722       return reg_types->JavaLangObject(false);  // Object MERGE ref => Object
    723     } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
    724       // We know how to merge an unresolved type with itself, 0 or Object. In this case we
    725       // have two sub-classes and don't know how to merge. Create a new string-based unresolved
    726       // type that reflects our lack of knowledge and that allows the rest of the unresolved
    727       // mechanics to continue.
    728       return reg_types->FromUnresolvedMerge(*this, incoming_type, verifier);
    729     } else {  // Two reference types, compute Join
    730       // Do not cache the classes as ClassJoin() can suspend and invalidate ObjPtr<>s.
    731       DCHECK(GetClass() != nullptr && !GetClass()->IsPrimitive());
    732       DCHECK(incoming_type.GetClass() != nullptr && !incoming_type.GetClass()->IsPrimitive());
    733       ObjPtr<mirror::Class> join_class = ClassJoin(GetClass(), incoming_type.GetClass());
    734       if (UNLIKELY(join_class == nullptr)) {
    735         // Internal error joining the classes (e.g., OOME). Report an unresolved reference type.
    736         // We cannot report an unresolved merge type, as that will attempt to merge the resolved
    737         // components, leaving us in an infinite loop.
    738         // We do not want to report the originating exception, as that would require a fast path
    739         // out all the way to VerifyClass. Instead attempt to continue on without a detailed type.
    740         Thread* self = Thread::Current();
    741         self->AssertPendingException();
    742         self->ClearException();
    743 
    744         // When compiling on the host, we rather want to abort to ensure determinism for preopting.
    745         // (In that case, it is likely a misconfiguration of dex2oat.)
    746         if (!kIsTargetBuild && Runtime::Current()->IsAotCompiler()) {
    747           LOG(FATAL) << "Could not create class join of "
    748                      << GetClass()->PrettyClass()
    749                      << " & "
    750                      << incoming_type.GetClass()->PrettyClass();
    751           UNREACHABLE();
    752         }
    753 
    754         return reg_types->MakeUnresolvedReference();
    755       }
    756 
    757       // Record the dependency that both `GetClass()` and `incoming_type.GetClass()`
    758       // are assignable to `join_class`. The `verifier` is null during unit tests.
    759       if (verifier != nullptr) {
    760         VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
    761                                                join_class,
    762                                                GetClass(),
    763                                                /* is_strict= */ true,
    764                                                /* is_assignable= */ true);
    765         VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
    766                                                join_class,
    767                                                incoming_type.GetClass(),
    768                                                /* is_strict= */ true,
    769                                                /* is_assignable= */ true);
    770       }
    771       if (GetClass() == join_class && !IsPreciseReference()) {
    772         return *this;
    773       } else if (incoming_type.GetClass() == join_class && !incoming_type.IsPreciseReference()) {
    774         return incoming_type;
    775       } else {
    776         std::string temp;
    777         const char* descriptor = join_class->GetDescriptor(&temp);
    778         return reg_types->FromClass(descriptor, join_class, /* precise= */ false);
    779       }
    780     }
    781   } else {
    782     return conflict;  // Unexpected types => Conflict
    783   }
    784 }
    785 
    786 // See comment in reg_type.h
    787 ObjPtr<mirror::Class> RegType::ClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t) {
    788   DCHECK(!s->IsPrimitive()) << s->PrettyClass();
    789   DCHECK(!t->IsPrimitive()) << t->PrettyClass();
    790   if (s == t) {
    791     return s;
    792   } else if (s->IsAssignableFrom(t)) {
    793     return s;
    794   } else if (t->IsAssignableFrom(s)) {
    795     return t;
    796   } else if (s->IsArrayClass() && t->IsArrayClass()) {
    797     ObjPtr<mirror::Class> s_ct = s->GetComponentType();
    798     ObjPtr<mirror::Class> t_ct = t->GetComponentType();
    799     if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
    800       // Given the types aren't the same, if either array is of primitive types then the only
    801       // common parent is java.lang.Object
    802       ObjPtr<mirror::Class> result = s->GetSuperClass();  // short-cut to java.lang.Object
    803       DCHECK(result->IsObjectClass());
    804       return result;
    805     }
    806     Thread* self = Thread::Current();
    807     ObjPtr<mirror::Class> common_elem = ClassJoin(s_ct, t_ct);
    808     if (UNLIKELY(common_elem == nullptr)) {
    809       self->AssertPendingException();
    810       return nullptr;
    811     }
    812     // Note: The following lookup invalidates existing ObjPtr<>s.
    813     ObjPtr<mirror::Class> array_class =
    814         Runtime::Current()->GetClassLinker()->FindArrayClass(self, common_elem);
    815     if (UNLIKELY(array_class == nullptr)) {
    816       self->AssertPendingException();
    817       return nullptr;
    818     }
    819     return array_class;
    820   } else {
    821     size_t s_depth = s->Depth();
    822     size_t t_depth = t->Depth();
    823     // Get s and t to the same depth in the hierarchy
    824     if (s_depth > t_depth) {
    825       while (s_depth > t_depth) {
    826         s = s->GetSuperClass();
    827         s_depth--;
    828       }
    829     } else {
    830       while (t_depth > s_depth) {
    831         t = t->GetSuperClass();
    832         t_depth--;
    833       }
    834     }
    835     // Go up the hierarchy until we get to the common parent
    836     while (s != t) {
    837       s = s->GetSuperClass();
    838       t = t->GetSuperClass();
    839     }
    840     return s;
    841   }
    842 }
    843 
    844 void RegType::CheckInvariants() const {
    845   if (IsConstant() || IsConstantLo() || IsConstantHi()) {
    846     CHECK(descriptor_.empty()) << *this;
    847     CHECK(klass_.IsNull()) << *this;
    848   }
    849   if (!klass_.IsNull()) {
    850     CHECK(!descriptor_.empty()) << *this;
    851     std::string temp;
    852     CHECK_EQ(descriptor_, klass_.Read()->GetDescriptor(&temp)) << *this;
    853   }
    854 }
    855 
    856 void RegType::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const {
    857   klass_.VisitRootIfNonNull(visitor, root_info);
    858 }
    859 
    860 void UninitializedThisReferenceType::CheckInvariants() const {
    861   CHECK_EQ(GetAllocationPc(), 0U) << *this;
    862 }
    863 
    864 void UnresolvedUninitializedThisRefType::CheckInvariants() const {
    865   CHECK_EQ(GetAllocationPc(), 0U) << *this;
    866   CHECK(!descriptor_.empty()) << *this;
    867   CHECK(klass_.IsNull()) << *this;
    868 }
    869 
    870 void UnresolvedUninitializedRefType::CheckInvariants() const {
    871   CHECK(!descriptor_.empty()) << *this;
    872   CHECK(klass_.IsNull()) << *this;
    873 }
    874 
    875 UnresolvedMergedType::UnresolvedMergedType(const RegType& resolved,
    876                                            const BitVector& unresolved,
    877                                            const RegTypeCache* reg_type_cache,
    878                                            uint16_t cache_id)
    879     : UnresolvedType("", cache_id),
    880       reg_type_cache_(reg_type_cache),
    881       resolved_part_(resolved),
    882       unresolved_types_(unresolved, false, unresolved.GetAllocator()) {
    883   CheckConstructorInvariants(this);
    884 }
    885 void UnresolvedMergedType::CheckInvariants() const {
    886   CHECK(reg_type_cache_ != nullptr);
    887 
    888   // Unresolved merged types: merged types should be defined.
    889   CHECK(descriptor_.empty()) << *this;
    890   CHECK(klass_.IsNull()) << *this;
    891 
    892   CHECK(!resolved_part_.IsConflict());
    893   CHECK(resolved_part_.IsReferenceTypes());
    894   CHECK(!resolved_part_.IsUnresolvedTypes());
    895 
    896   CHECK(resolved_part_.IsZero() ||
    897         !(resolved_part_.IsArrayTypes() && !resolved_part_.IsObjectArrayTypes()));
    898 
    899   CHECK_GT(unresolved_types_.NumSetBits(), 0U);
    900   bool unresolved_is_array =
    901       reg_type_cache_->GetFromId(unresolved_types_.GetHighestBitSet()).IsArrayTypes();
    902   for (uint32_t idx : unresolved_types_.Indexes()) {
    903     const RegType& t = reg_type_cache_->GetFromId(idx);
    904     CHECK_EQ(unresolved_is_array, t.IsArrayTypes());
    905   }
    906 
    907   if (!resolved_part_.IsZero()) {
    908     CHECK_EQ(resolved_part_.IsArrayTypes(), unresolved_is_array);
    909   }
    910 }
    911 
    912 bool UnresolvedMergedType::IsArrayTypes() const {
    913   // For a merge to be an array, both the resolved and the unresolved part need to be object
    914   // arrays.
    915   // (Note: we encode a missing resolved part [which doesn't need to be an array] as zero.)
    916 
    917   if (!resolved_part_.IsZero() && !resolved_part_.IsArrayTypes()) {
    918     return false;
    919   }
    920 
    921   // It is enough to check just one of the merged types. Otherwise the merge should have been
    922   // collapsed (checked in CheckInvariants on construction).
    923   uint32_t idx = unresolved_types_.GetHighestBitSet();
    924   const RegType& unresolved = reg_type_cache_->GetFromId(idx);
    925   return unresolved.IsArrayTypes();
    926 }
    927 bool UnresolvedMergedType::IsObjectArrayTypes() const {
    928   // Same as IsArrayTypes, as primitive arrays are always resolved.
    929   return IsArrayTypes();
    930 }
    931 
    932 void UnresolvedReferenceType::CheckInvariants() const {
    933   CHECK(!descriptor_.empty()) << *this;
    934   CHECK(klass_.IsNull()) << *this;
    935 }
    936 
    937 void UnresolvedSuperClass::CheckInvariants() const {
    938   // Unresolved merged types: merged types should be defined.
    939   CHECK(descriptor_.empty()) << *this;
    940   CHECK(klass_.IsNull()) << *this;
    941   CHECK_NE(unresolved_child_id_, 0U) << *this;
    942 }
    943 
    944 std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
    945   os << rhs.Dump();
    946   return os;
    947 }
    948 
    949 bool RegType::CanAssignArray(const RegType& src,
    950                              RegTypeCache& reg_types,
    951                              Handle<mirror::ClassLoader> class_loader,
    952                              MethodVerifier* verifier,
    953                              bool* soft_error) const {
    954   if (!IsArrayTypes() || !src.IsArrayTypes()) {
    955     *soft_error = false;
    956     return false;
    957   }
    958 
    959   if (IsUnresolvedMergedReference() || src.IsUnresolvedMergedReference()) {
    960     // An unresolved array type means that it's an array of some reference type. Reference arrays
    961     // can never be assigned to primitive-type arrays, and vice versa. So it is a soft error if
    962     // both arrays are reference arrays, otherwise a hard error.
    963     *soft_error = IsObjectArrayTypes() && src.IsObjectArrayTypes();
    964     return false;
    965   }
    966 
    967   const RegType& cmp1 = reg_types.GetComponentType(*this, class_loader.Get());
    968   const RegType& cmp2 = reg_types.GetComponentType(src, class_loader.Get());
    969 
    970   if (cmp1.IsAssignableFrom(cmp2, verifier)) {
    971     return true;
    972   }
    973   if (cmp1.IsUnresolvedTypes()) {
    974     if (cmp2.IsIntegralTypes() || cmp2.IsFloatTypes() || cmp2.IsArrayTypes()) {
    975       *soft_error = false;
    976       return false;
    977     }
    978     *soft_error = true;
    979     return false;
    980   }
    981   if (cmp2.IsUnresolvedTypes()) {
    982     if (cmp1.IsIntegralTypes() || cmp1.IsFloatTypes() || cmp1.IsArrayTypes()) {
    983       *soft_error = false;
    984       return false;
    985     }
    986     *soft_error = true;
    987     return false;
    988   }
    989   if (!cmp1.IsArrayTypes() || !cmp2.IsArrayTypes()) {
    990     *soft_error = false;
    991     return false;
    992   }
    993   return cmp1.CanAssignArray(cmp2, reg_types, class_loader, verifier, soft_error);
    994 }
    995 
    996 const NullType* NullType::CreateInstance(ObjPtr<mirror::Class> klass,
    997                                          const std::string_view& descriptor,
    998                                          uint16_t cache_id) {
    999   CHECK(instance_ == nullptr);
   1000   instance_ = new NullType(klass, descriptor, cache_id);
   1001   return instance_;
   1002 }
   1003 
   1004 void NullType::Destroy() {
   1005   if (NullType::instance_ != nullptr) {
   1006     delete instance_;
   1007     instance_ = nullptr;
   1008   }
   1009 }
   1010 
   1011 
   1012 }  // namespace verifier
   1013 }  // namespace art
   1014