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 #ifndef ART_RUNTIME_VERIFIER_REG_TYPE_H_
     18 #define ART_RUNTIME_VERIFIER_REG_TYPE_H_
     19 
     20 #include <stdint.h>
     21 #include <limits>
     22 #include <set>
     23 #include <string>
     24 
     25 #include "base/bit_vector.h"
     26 #include "base/macros.h"
     27 #include "base/mutex.h"
     28 #include "gc_root.h"
     29 #include "handle_scope.h"
     30 #include "object_callbacks.h"
     31 #include "primitive.h"
     32 
     33 namespace art {
     34 namespace mirror {
     35 class Class;
     36 }  // namespace mirror
     37 
     38 namespace verifier {
     39 
     40 class RegTypeCache;
     41 /*
     42  * RegType holds information about the "type" of data held in a register.
     43  */
     44 class RegType {
     45  public:
     46   virtual bool IsUndefined() const { return false; }
     47   virtual bool IsConflict() const { return false; }
     48   virtual bool IsBoolean() const { return false; }
     49   virtual bool IsByte() const { return false; }
     50   virtual bool IsChar() const { return false; }
     51   virtual bool IsShort() const { return false; }
     52   virtual bool IsInteger() const { return false; }
     53   virtual bool IsLongLo() const { return false; }
     54   virtual bool IsLongHi() const { return false; }
     55   virtual bool IsFloat() const { return false; }
     56   virtual bool IsDouble() const { return false; }
     57   virtual bool IsDoubleLo() const { return false; }
     58   virtual bool IsDoubleHi() const { return false; }
     59   virtual bool IsUnresolvedReference() const { return false; }
     60   virtual bool IsUninitializedReference() const { return false; }
     61   virtual bool IsUninitializedThisReference() const { return false; }
     62   virtual bool IsUnresolvedAndUninitializedReference() const { return false; }
     63   virtual bool IsUnresolvedAndUninitializedThisReference() const {
     64     return false;
     65   }
     66   virtual bool IsUnresolvedMergedReference() const { return false; }
     67   virtual bool IsUnresolvedSuperClass() const { return false; }
     68   virtual bool IsReference() const { return false; }
     69   virtual bool IsPreciseReference() const { return false; }
     70   virtual bool IsPreciseConstant() const { return false; }
     71   virtual bool IsPreciseConstantLo() const { return false; }
     72   virtual bool IsPreciseConstantHi() const { return false; }
     73   virtual bool IsImpreciseConstantLo() const { return false; }
     74   virtual bool IsImpreciseConstantHi() const { return false; }
     75   virtual bool IsImpreciseConstant() const { return false; }
     76   virtual bool IsConstantTypes() const { return false; }
     77   bool IsConstant() const {
     78     return IsImpreciseConstant() || IsPreciseConstant();
     79   }
     80   bool IsConstantLo() const {
     81     return IsImpreciseConstantLo() || IsPreciseConstantLo();
     82   }
     83   bool IsPrecise() const {
     84     return IsPreciseConstantLo() || IsPreciseConstant() ||
     85            IsPreciseConstantHi();
     86   }
     87   bool IsLongConstant() const { return IsConstantLo(); }
     88   bool IsConstantHi() const {
     89     return (IsPreciseConstantHi() || IsImpreciseConstantHi());
     90   }
     91   bool IsLongConstantHigh() const { return IsConstantHi(); }
     92   virtual bool IsUninitializedTypes() const { return false; }
     93   virtual bool IsUnresolvedTypes() const { return false; }
     94 
     95   bool IsLowHalf() const {
     96     return (IsLongLo() || IsDoubleLo() || IsPreciseConstantLo() || IsImpreciseConstantLo());
     97   }
     98   bool IsHighHalf() const {
     99     return (IsLongHi() || IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi());
    100   }
    101   bool IsLongOrDoubleTypes() const { return IsLowHalf(); }
    102   // Check this is the low half, and that type_h is its matching high-half.
    103   inline bool CheckWidePair(const RegType& type_h) const {
    104     if (IsLowHalf()) {
    105       return ((IsImpreciseConstantLo() && type_h.IsPreciseConstantHi()) ||
    106               (IsImpreciseConstantLo() && type_h.IsImpreciseConstantHi()) ||
    107               (IsPreciseConstantLo() && type_h.IsPreciseConstantHi()) ||
    108               (IsPreciseConstantLo() && type_h.IsImpreciseConstantHi()) ||
    109               (IsDoubleLo() && type_h.IsDoubleHi()) ||
    110               (IsLongLo() && type_h.IsLongHi()));
    111     }
    112     return false;
    113   }
    114   // The high half that corresponds to this low half
    115   const RegType& HighHalf(RegTypeCache* cache) const
    116       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    117 
    118   bool IsConstantBoolean() const;
    119   virtual bool IsConstantChar() const { return false; }
    120   virtual bool IsConstantByte() const { return false; }
    121   virtual bool IsConstantShort() const { return false; }
    122   virtual bool IsOne() const { return false; }
    123   virtual bool IsZero() const { return false; }
    124   bool IsReferenceTypes() const {
    125     return IsNonZeroReferenceTypes() || IsZero();
    126   }
    127   virtual bool IsNonZeroReferenceTypes() const { return false; }
    128   bool IsCategory1Types() const {
    129     return IsChar() || IsInteger() || IsFloat() || IsConstant() || IsByte() ||
    130            IsShort() || IsBoolean();
    131   }
    132   bool IsCategory2Types() const {
    133     return IsLowHalf();  // Don't expect explicit testing of high halves
    134   }
    135   bool IsBooleanTypes() const { return IsBoolean() || IsConstantBoolean(); }
    136   bool IsByteTypes() const {
    137     return IsConstantByte() || IsByte() || IsBoolean();
    138   }
    139   bool IsShortTypes() const {
    140     return IsShort() || IsByte() || IsBoolean() || IsConstantShort();
    141   }
    142   bool IsCharTypes() const {
    143     return IsChar() || IsBooleanTypes() || IsConstantChar();
    144   }
    145   bool IsIntegralTypes() const {
    146     return IsInteger() || IsConstant() || IsByte() || IsShort() || IsChar() ||
    147            IsBoolean();
    148   }
    149   // Give the constant value encoded, but this shouldn't be called in the
    150   // general case.
    151   bool IsArrayIndexTypes() const { return IsIntegralTypes(); }
    152   // Float type may be derived from any constant type
    153   bool IsFloatTypes() const { return IsFloat() || IsConstant(); }
    154   bool IsLongTypes() const { return IsLongLo() || IsLongConstant(); }
    155   bool IsLongHighTypes() const {
    156     return (IsLongHi() || IsPreciseConstantHi() || IsImpreciseConstantHi());
    157   }
    158   bool IsDoubleTypes() const { return IsDoubleLo() || IsLongConstant(); }
    159   bool IsDoubleHighTypes() const {
    160     return (IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi());
    161   }
    162   virtual bool IsLong() const { return false; }
    163   bool HasClass() const {
    164     bool result = !klass_.IsNull();
    165     DCHECK_EQ(result, HasClassVirtual());
    166     return result;
    167   }
    168   virtual bool HasClassVirtual() const { return false; }
    169   bool IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    170   bool IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    171   bool IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    172   Primitive::Type GetPrimitiveType() const;
    173   bool IsJavaLangObjectArray() const
    174       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    175   bool IsInstantiableTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    176   const std::string& GetDescriptor() const {
    177     DCHECK(HasClass() ||
    178            (IsUnresolvedTypes() && !IsUnresolvedMergedReference() &&
    179             !IsUnresolvedSuperClass()));
    180     return descriptor_;
    181   }
    182   mirror::Class* GetClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    183     DCHECK(!IsUnresolvedReference());
    184     DCHECK(!klass_.IsNull()) << Dump();
    185     DCHECK(HasClass());
    186     return klass_.Read();
    187   }
    188   uint16_t GetId() const { return cache_id_; }
    189   const RegType& GetSuperClass(RegTypeCache* cache) const
    190       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    191 
    192   virtual std::string Dump() const
    193       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
    194 
    195   // Can this type access other?
    196   bool CanAccess(const RegType& other) const
    197       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    198 
    199   // Can this type access a member with the given properties?
    200   bool CanAccessMember(mirror::Class* klass, uint32_t access_flags) const
    201       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    202 
    203   // Can this type be assigned by src?
    204   // Note: Object and interface types may always be assigned to one another, see
    205   // comment on
    206   // ClassJoin.
    207   bool IsAssignableFrom(const RegType& src) const
    208       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    209 
    210   // Can this array type potentially be assigned by src.
    211   // This function is necessary as array types are valid even if their components types are not,
    212   // e.g., when they component type could not be resolved. The function will return true iff the
    213   // types are assignable. It will return false otherwise. In case of return=false, soft_error
    214   // will be set to true iff the assignment test failure should be treated as a soft-error, i.e.,
    215   // when both array types have the same 'depth' and the 'final' component types may be assignable
    216   // (both are reference types).
    217   bool CanAssignArray(const RegType& src, RegTypeCache& reg_types,
    218                       Handle<mirror::ClassLoader> class_loader, bool* soft_error) const
    219       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    220 
    221   // Can this type be assigned by src? Variant of IsAssignableFrom that doesn't
    222   // allow assignment to
    223   // an interface from an Object.
    224   bool IsStrictlyAssignableFrom(const RegType& src) const
    225       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    226 
    227   // Are these RegTypes the same?
    228   bool Equals(const RegType& other) const { return GetId() == other.GetId(); }
    229 
    230   // Compute the merge of this register from one edge (path) with incoming_type
    231   // from another.
    232   const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
    233       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    234   // Same as above, but also handles the case where incoming_type == this.
    235   const RegType& SafeMerge(const RegType& incoming_type, RegTypeCache* reg_types) const
    236       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    237     if (Equals(incoming_type)) {
    238       return *this;
    239     }
    240     return Merge(incoming_type, reg_types);
    241   }
    242 
    243   /*
    244    * A basic Join operation on classes. For a pair of types S and T the Join,
    245    *written S v T = J, is
    246    * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is
    247    *J is the parent of
    248    * S and T such that there isn't a parent of both S and T that isn't also the
    249    *parent of J (ie J
    250    * is the deepest (lowest upper bound) parent of S and T).
    251    *
    252    * This operation applies for regular classes and arrays, however, for
    253    *interface types there
    254    * needn't be a partial ordering on the types. We could solve the problem of a
    255    *lack of a partial
    256    * order by introducing sets of types, however, the only operation permissible
    257    *on an interface is
    258    * invoke-interface. In the tradition of Java verifiers [1] we defer the
    259    *verification of interface
    260    * types until an invoke-interface call on the interface typed reference at
    261    *runtime and allow
    262    * the perversion of Object being assignable to an interface type (note,
    263    *however, that we don't
    264    * allow assignment of Object or Interface to any concrete class and are
    265    *therefore type safe).
    266    *
    267    * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
    268    */
    269   static mirror::Class* ClassJoin(mirror::Class* s, mirror::Class* t)
    270       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    271 
    272   virtual ~RegType() {}
    273 
    274   void VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const
    275       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    276 
    277  protected:
    278   RegType(mirror::Class* klass, const std::string& descriptor,
    279           uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    280       : descriptor_(descriptor), klass_(klass), cache_id_(cache_id) {
    281     if (kIsDebugBuild) {
    282       CheckInvariants();
    283     }
    284   }
    285 
    286   void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    287 
    288   const std::string descriptor_;
    289   mutable GcRoot<mirror::Class>
    290       klass_;  // Non-const only due to moving classes.
    291   const uint16_t cache_id_;
    292 
    293   friend class RegTypeCache;
    294 
    295  private:
    296   static bool AssignableFrom(const RegType& lhs, const RegType& rhs, bool strict)
    297       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    298 
    299   DISALLOW_COPY_AND_ASSIGN(RegType);
    300 };
    301 
    302 // Bottom type.
    303 class ConflictType FINAL : public RegType {
    304  public:
    305   bool IsConflict() const OVERRIDE { return true; }
    306 
    307   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    308 
    309   // Get the singleton Conflict instance.
    310   static const ConflictType* GetInstance() PURE;
    311 
    312   // Create the singleton instance.
    313   static const ConflictType* CreateInstance(mirror::Class* klass,
    314                                             const std::string& descriptor,
    315                                             uint16_t cache_id)
    316       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    317 
    318   // Destroy the singleton instance.
    319   static void Destroy();
    320 
    321  private:
    322   ConflictType(mirror::Class* klass, const std::string& descriptor,
    323                uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    324       : RegType(klass, descriptor, cache_id) {}
    325 
    326   static const ConflictType* instance_;
    327 };
    328 
    329 // A variant of the bottom type used to specify an undefined value in the
    330 // incoming registers.
    331 // Merging with UndefinedType yields ConflictType which is the true bottom.
    332 class UndefinedType FINAL : public RegType {
    333  public:
    334   bool IsUndefined() const OVERRIDE { return true; }
    335 
    336   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    337 
    338   // Get the singleton Undefined instance.
    339   static const UndefinedType* GetInstance() PURE;
    340 
    341   // Create the singleton instance.
    342   static const UndefinedType* CreateInstance(mirror::Class* klass,
    343                                              const std::string& descriptor,
    344                                              uint16_t cache_id)
    345       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    346 
    347   // Destroy the singleton instance.
    348   static void Destroy();
    349 
    350  private:
    351   UndefinedType(mirror::Class* klass, const std::string& descriptor,
    352                 uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    353       : RegType(klass, descriptor, cache_id) {}
    354 
    355   static const UndefinedType* instance_;
    356 };
    357 
    358 class PrimitiveType : public RegType {
    359  public:
    360   PrimitiveType(mirror::Class* klass, const std::string& descriptor,
    361                 uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    362 
    363   bool HasClassVirtual() const OVERRIDE { return true; }
    364 };
    365 
    366 class Cat1Type : public PrimitiveType {
    367  public:
    368   Cat1Type(mirror::Class* klass, const std::string& descriptor,
    369            uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    370 };
    371 
    372 class IntegerType : public Cat1Type {
    373  public:
    374   bool IsInteger() const OVERRIDE { return true; }
    375   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    376   static const IntegerType* CreateInstance(mirror::Class* klass,
    377                                            const std::string& descriptor,
    378                                            uint16_t cache_id)
    379       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    380   static const IntegerType* GetInstance() PURE;
    381   static void Destroy();
    382 
    383  private:
    384   IntegerType(mirror::Class* klass, const std::string& descriptor,
    385               uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    386       : Cat1Type(klass, descriptor, cache_id) {}
    387   static const IntegerType* instance_;
    388 };
    389 
    390 class BooleanType FINAL : public Cat1Type {
    391  public:
    392   bool IsBoolean() const OVERRIDE { return true; }
    393   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    394   static const BooleanType* CreateInstance(mirror::Class* klass,
    395                                            const std::string& descriptor,
    396                                            uint16_t cache_id)
    397       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    398   static const BooleanType* GetInstance() PURE;
    399   static void Destroy();
    400 
    401  private:
    402   BooleanType(mirror::Class* klass, const std::string& descriptor,
    403               uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    404       : Cat1Type(klass, descriptor, cache_id) {}
    405 
    406   static const BooleanType* instance_;
    407 };
    408 
    409 class ByteType FINAL : public Cat1Type {
    410  public:
    411   bool IsByte() const OVERRIDE { return true; }
    412   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    413   static const ByteType* CreateInstance(mirror::Class* klass,
    414                                         const std::string& descriptor,
    415                                         uint16_t cache_id)
    416       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    417   static const ByteType* GetInstance() PURE;
    418   static void Destroy();
    419 
    420  private:
    421   ByteType(mirror::Class* klass, const std::string& descriptor,
    422            uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    423       : Cat1Type(klass, descriptor, cache_id) {}
    424   static const ByteType* instance_;
    425 };
    426 
    427 class ShortType FINAL : public Cat1Type {
    428  public:
    429   bool IsShort() const OVERRIDE { return true; }
    430   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    431   static const ShortType* CreateInstance(mirror::Class* klass,
    432                                          const std::string& descriptor,
    433                                          uint16_t cache_id)
    434       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    435   static const ShortType* GetInstance() PURE;
    436   static void Destroy();
    437 
    438  private:
    439   ShortType(mirror::Class* klass, const std::string& descriptor,
    440             uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    441       : Cat1Type(klass, descriptor, cache_id) {}
    442   static const ShortType* instance_;
    443 };
    444 
    445 class CharType FINAL : public Cat1Type {
    446  public:
    447   bool IsChar() const OVERRIDE { return true; }
    448   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    449   static const CharType* CreateInstance(mirror::Class* klass,
    450                                         const std::string& descriptor,
    451                                         uint16_t cache_id)
    452       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    453   static const CharType* GetInstance() PURE;
    454   static void Destroy();
    455 
    456  private:
    457   CharType(mirror::Class* klass, const std::string& descriptor,
    458            uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    459       : Cat1Type(klass, descriptor, cache_id) {}
    460   static const CharType* instance_;
    461 };
    462 
    463 class FloatType FINAL : public Cat1Type {
    464  public:
    465   bool IsFloat() const OVERRIDE { return true; }
    466   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    467   static const FloatType* CreateInstance(mirror::Class* klass,
    468                                          const std::string& descriptor,
    469                                          uint16_t cache_id)
    470       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    471   static const FloatType* GetInstance() PURE;
    472   static void Destroy();
    473 
    474  private:
    475   FloatType(mirror::Class* klass, const std::string& descriptor,
    476             uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    477       : Cat1Type(klass, descriptor, cache_id) {}
    478   static const FloatType* instance_;
    479 };
    480 
    481 class Cat2Type : public PrimitiveType {
    482  public:
    483   Cat2Type(mirror::Class* klass, const std::string& descriptor,
    484            uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    485 };
    486 
    487 class LongLoType FINAL : public Cat2Type {
    488  public:
    489   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    490   bool IsLongLo() const OVERRIDE { return true; }
    491   bool IsLong() const OVERRIDE { return true; }
    492   static const LongLoType* CreateInstance(mirror::Class* klass,
    493                                           const std::string& descriptor,
    494                                           uint16_t cache_id)
    495       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    496   static const LongLoType* GetInstance() PURE;
    497   static void Destroy();
    498 
    499  private:
    500   LongLoType(mirror::Class* klass, const std::string& descriptor,
    501              uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    502       : Cat2Type(klass, descriptor, cache_id) {}
    503   static const LongLoType* instance_;
    504 };
    505 
    506 class LongHiType FINAL : public Cat2Type {
    507  public:
    508   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    509   bool IsLongHi() const OVERRIDE { return true; }
    510   static const LongHiType* CreateInstance(mirror::Class* klass,
    511                                           const std::string& descriptor,
    512                                           uint16_t cache_id)
    513       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    514   static const LongHiType* GetInstance() PURE;
    515   static void Destroy();
    516 
    517  private:
    518   LongHiType(mirror::Class* klass, const std::string& descriptor,
    519              uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    520       : Cat2Type(klass, descriptor, cache_id) {}
    521   static const LongHiType* instance_;
    522 };
    523 
    524 class DoubleLoType FINAL : public Cat2Type {
    525  public:
    526   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    527   bool IsDoubleLo() const OVERRIDE { return true; }
    528   bool IsDouble() const OVERRIDE { return true; }
    529   static const DoubleLoType* CreateInstance(mirror::Class* klass,
    530                                             const std::string& descriptor,
    531                                             uint16_t cache_id)
    532       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    533   static const DoubleLoType* GetInstance() PURE;
    534   static void Destroy();
    535 
    536  private:
    537   DoubleLoType(mirror::Class* klass, const std::string& descriptor,
    538                uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    539       : Cat2Type(klass, descriptor, cache_id) {}
    540   static const DoubleLoType* instance_;
    541 };
    542 
    543 class DoubleHiType FINAL : public Cat2Type {
    544  public:
    545   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    546   virtual bool IsDoubleHi() const OVERRIDE { return true; }
    547   static const DoubleHiType* CreateInstance(mirror::Class* klass,
    548                                       const std::string& descriptor,
    549                                       uint16_t cache_id)
    550       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    551   static const DoubleHiType* GetInstance() PURE;
    552   static void Destroy();
    553 
    554  private:
    555   DoubleHiType(mirror::Class* klass, const std::string& descriptor,
    556                uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    557       : Cat2Type(klass, descriptor, cache_id) {}
    558   static const DoubleHiType* instance_;
    559 };
    560 
    561 class ConstantType : public RegType {
    562  public:
    563   ConstantType(uint32_t constant, uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    564       : RegType(nullptr, "", cache_id), constant_(constant) {
    565   }
    566 
    567 
    568   // If this is a 32-bit constant, what is the value? This value may be
    569   // imprecise in which case
    570   // the value represents part of the integer range of values that may be held
    571   // in the register.
    572   int32_t ConstantValue() const {
    573     DCHECK(IsConstantTypes());
    574     return constant_;
    575   }
    576 
    577   int32_t ConstantValueLo() const {
    578     DCHECK(IsConstantLo());
    579     return constant_;
    580   }
    581 
    582   int32_t ConstantValueHi() const {
    583     if (IsConstantHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()) {
    584       return constant_;
    585     } else {
    586       DCHECK(false);
    587       return 0;
    588     }
    589   }
    590 
    591   bool IsZero() const OVERRIDE {
    592     return IsPreciseConstant() && ConstantValue() == 0;
    593   }
    594   bool IsOne() const OVERRIDE {
    595     return IsPreciseConstant() && ConstantValue() == 1;
    596   }
    597 
    598   bool IsConstantChar() const OVERRIDE {
    599     return IsConstant() && ConstantValue() >= 0 &&
    600            ConstantValue() <= std::numeric_limits<uint16_t>::max();
    601   }
    602   bool IsConstantByte() const OVERRIDE {
    603     return IsConstant() &&
    604            ConstantValue() >= std::numeric_limits<int8_t>::min() &&
    605            ConstantValue() <= std::numeric_limits<int8_t>::max();
    606   }
    607   bool IsConstantShort() const OVERRIDE {
    608     return IsConstant() &&
    609            ConstantValue() >= std::numeric_limits<int16_t>::min() &&
    610            ConstantValue() <= std::numeric_limits<int16_t>::max();
    611   }
    612   virtual bool IsConstantTypes() const OVERRIDE { return true; }
    613 
    614  private:
    615   const uint32_t constant_;
    616 };
    617 
    618 class PreciseConstType FINAL : public ConstantType {
    619  public:
    620   PreciseConstType(uint32_t constant, uint16_t cache_id)
    621       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    622       : ConstantType(constant, cache_id) {}
    623 
    624   bool IsPreciseConstant() const OVERRIDE { return true; }
    625 
    626   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    627 };
    628 
    629 class PreciseConstLoType FINAL : public ConstantType {
    630  public:
    631   PreciseConstLoType(uint32_t constant, uint16_t cache_id)
    632       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    633       : ConstantType(constant, cache_id) {}
    634   bool IsPreciseConstantLo() const OVERRIDE { return true; }
    635   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    636 };
    637 
    638 class PreciseConstHiType FINAL : public ConstantType {
    639  public:
    640   PreciseConstHiType(uint32_t constant, uint16_t cache_id)
    641       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    642       : ConstantType(constant, cache_id) {}
    643   bool IsPreciseConstantHi() const OVERRIDE { return true; }
    644   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    645 };
    646 
    647 class ImpreciseConstType FINAL : public ConstantType {
    648  public:
    649   ImpreciseConstType(uint32_t constat, uint16_t cache_id)
    650        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    651        : ConstantType(constat, cache_id) {
    652   }
    653   bool IsImpreciseConstant() const OVERRIDE { return true; }
    654   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    655 };
    656 
    657 class ImpreciseConstLoType FINAL : public ConstantType {
    658  public:
    659   ImpreciseConstLoType(uint32_t constant, uint16_t cache_id)
    660       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    661       : ConstantType(constant, cache_id) {}
    662   bool IsImpreciseConstantLo() const OVERRIDE { return true; }
    663   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    664 };
    665 
    666 class ImpreciseConstHiType FINAL : public ConstantType {
    667  public:
    668   ImpreciseConstHiType(uint32_t constant, uint16_t cache_id)
    669       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    670       : ConstantType(constant, cache_id) {}
    671   bool IsImpreciseConstantHi() const OVERRIDE { return true; }
    672   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    673 };
    674 
    675 // Common parent of all uninitialized types. Uninitialized types are created by
    676 // "new" dex
    677 // instructions and must be passed to a constructor.
    678 class UninitializedType : public RegType {
    679  public:
    680   UninitializedType(mirror::Class* klass, const std::string& descriptor,
    681                     uint32_t allocation_pc, uint16_t cache_id)
    682       : RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {}
    683 
    684   bool IsUninitializedTypes() const OVERRIDE;
    685   bool IsNonZeroReferenceTypes() const OVERRIDE;
    686 
    687   uint32_t GetAllocationPc() const {
    688     DCHECK(IsUninitializedTypes());
    689     return allocation_pc_;
    690   }
    691 
    692  private:
    693   const uint32_t allocation_pc_;
    694 };
    695 
    696 // Similar to ReferenceType but not yet having been passed to a constructor.
    697 class UninitializedReferenceType FINAL : public UninitializedType {
    698  public:
    699   UninitializedReferenceType(mirror::Class* klass,
    700                              const std::string& descriptor,
    701                              uint32_t allocation_pc, uint16_t cache_id)
    702       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    703       : UninitializedType(klass, descriptor, allocation_pc, cache_id) {}
    704 
    705   bool IsUninitializedReference() const OVERRIDE { return true; }
    706 
    707   bool HasClassVirtual() const OVERRIDE { return true; }
    708 
    709   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    710 };
    711 
    712 // Similar to UnresolvedReferenceType but not yet having been passed to a
    713 // constructor.
    714 class UnresolvedUninitializedRefType FINAL : public UninitializedType {
    715  public:
    716   UnresolvedUninitializedRefType(const std::string& descriptor,
    717                                  uint32_t allocation_pc, uint16_t cache_id)
    718       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    719       : UninitializedType(nullptr, descriptor, allocation_pc, cache_id) {
    720     if (kIsDebugBuild) {
    721       CheckInvariants();
    722     }
    723   }
    724 
    725   bool IsUnresolvedAndUninitializedReference() const OVERRIDE { return true; }
    726 
    727   bool IsUnresolvedTypes() const OVERRIDE { return true; }
    728 
    729   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    730 
    731  private:
    732   void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    733 };
    734 
    735 // Similar to UninitializedReferenceType but special case for the this argument
    736 // of a constructor.
    737 class UninitializedThisReferenceType FINAL : public UninitializedType {
    738  public:
    739   UninitializedThisReferenceType(mirror::Class* klass,
    740                                  const std::string& descriptor,
    741                                  uint16_t cache_id)
    742       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    743       : UninitializedType(klass, descriptor, 0, cache_id) {
    744     if (kIsDebugBuild) {
    745       CheckInvariants();
    746     }
    747   }
    748 
    749   virtual bool IsUninitializedThisReference() const OVERRIDE { return true; }
    750 
    751   bool HasClassVirtual() const OVERRIDE { return true; }
    752 
    753   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    754 
    755  private:
    756   void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    757 };
    758 
    759 class UnresolvedUninitializedThisRefType FINAL : public UninitializedType {
    760  public:
    761   UnresolvedUninitializedThisRefType(const std::string& descriptor,
    762                                      uint16_t cache_id)
    763       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    764       : UninitializedType(nullptr, descriptor, 0, cache_id) {
    765     if (kIsDebugBuild) {
    766       CheckInvariants();
    767     }
    768   }
    769 
    770   bool IsUnresolvedAndUninitializedThisReference() const OVERRIDE { return true; }
    771 
    772   bool IsUnresolvedTypes() const OVERRIDE { return true; }
    773 
    774   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    775 
    776  private:
    777   void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    778 };
    779 
    780 // A type of register holding a reference to an Object of type GetClass or a
    781 // sub-class.
    782 class ReferenceType FINAL : public RegType {
    783  public:
    784   ReferenceType(mirror::Class* klass, const std::string& descriptor,
    785                 uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    786       : RegType(klass, descriptor, cache_id) {}
    787 
    788   bool IsReference() const OVERRIDE { return true; }
    789 
    790   bool IsNonZeroReferenceTypes() const OVERRIDE { return true; }
    791 
    792   bool HasClassVirtual() const OVERRIDE { return true; }
    793 
    794   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    795 };
    796 
    797 // A type of register holding a reference to an Object of type GetClass and only
    798 // an object of that
    799 // type.
    800 class PreciseReferenceType FINAL : public RegType {
    801  public:
    802   PreciseReferenceType(mirror::Class* klass, const std::string& descriptor,
    803                        uint16_t cache_id)
    804       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    805 
    806   bool IsPreciseReference() const OVERRIDE { return true; }
    807 
    808   bool IsNonZeroReferenceTypes() const OVERRIDE { return true; }
    809 
    810   bool HasClassVirtual() const OVERRIDE { return true; }
    811 
    812   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    813 };
    814 
    815 // Common parent of unresolved types.
    816 class UnresolvedType : public RegType {
    817  public:
    818   UnresolvedType(const std::string& descriptor, uint16_t cache_id)
    819       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    820       : RegType(nullptr, descriptor, cache_id) {}
    821 
    822   bool IsNonZeroReferenceTypes() const OVERRIDE;
    823 };
    824 
    825 // Similar to ReferenceType except the Class couldn't be loaded. Assignability
    826 // and other tests made
    827 // of this type must be conservative.
    828 class UnresolvedReferenceType FINAL : public UnresolvedType {
    829  public:
    830   UnresolvedReferenceType(const std::string& descriptor, uint16_t cache_id)
    831       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    832       : UnresolvedType(descriptor, cache_id) {
    833     if (kIsDebugBuild) {
    834       CheckInvariants();
    835     }
    836   }
    837 
    838   bool IsUnresolvedReference() const OVERRIDE { return true; }
    839 
    840   bool IsUnresolvedTypes() const OVERRIDE { return true; }
    841 
    842   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    843 
    844  private:
    845   void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    846 };
    847 
    848 // Type representing the super-class of an unresolved type.
    849 class UnresolvedSuperClass FINAL : public UnresolvedType {
    850  public:
    851   UnresolvedSuperClass(uint16_t child_id, RegTypeCache* reg_type_cache,
    852                        uint16_t cache_id)
    853       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    854       : UnresolvedType("", cache_id),
    855         unresolved_child_id_(child_id),
    856         reg_type_cache_(reg_type_cache) {
    857     if (kIsDebugBuild) {
    858       CheckInvariants();
    859     }
    860   }
    861 
    862   bool IsUnresolvedSuperClass() const OVERRIDE { return true; }
    863 
    864   bool IsUnresolvedTypes() const OVERRIDE { return true; }
    865 
    866   uint16_t GetUnresolvedSuperClassChildId() const {
    867     DCHECK(IsUnresolvedSuperClass());
    868     return static_cast<uint16_t>(unresolved_child_id_ & 0xFFFF);
    869   }
    870 
    871   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    872 
    873  private:
    874   void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    875 
    876   const uint16_t unresolved_child_id_;
    877   const RegTypeCache* const reg_type_cache_;
    878 };
    879 
    880 // A merge of unresolved (and resolved) types. If the types were resolved this may be
    881 // Conflict or another known ReferenceType.
    882 class UnresolvedMergedType FINAL : public UnresolvedType {
    883  public:
    884   // Note: the constructor will copy the unresolved BitVector, not use it directly.
    885   UnresolvedMergedType(const RegType& resolved, const BitVector& unresolved,
    886                        const RegTypeCache* reg_type_cache, uint16_t cache_id)
    887       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    888 
    889   // The resolved part. See description below.
    890   const RegType& GetResolvedPart() const {
    891     return resolved_part_;
    892   }
    893   // The unresolved part.
    894   const BitVector& GetUnresolvedTypes() const {
    895     return unresolved_types_;
    896   }
    897 
    898   bool IsUnresolvedMergedReference() const OVERRIDE { return true; }
    899 
    900   bool IsUnresolvedTypes() const OVERRIDE { return true; }
    901 
    902   std::string Dump() const OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    903 
    904  private:
    905   void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    906 
    907   const RegTypeCache* const reg_type_cache_;
    908 
    909   // The original implementation of merged types was a binary tree. Collection of the flattened
    910   // types ("leaves") can be expensive, so we store the expanded list now, as two components:
    911   // 1) A resolved component. We use Zero when there is no resolved component, as that will be
    912   //    an identity merge.
    913   // 2) A bitvector of the unresolved reference types. A bitvector was chosen with the assumption
    914   //    that there should not be too many types in flight in practice. (We also bias the index
    915   //    against the index of Zero, which is one of the later default entries in any cache.)
    916   const RegType& resolved_part_;
    917   const BitVector unresolved_types_;
    918 };
    919 
    920 std::ostream& operator<<(std::ostream& os, const RegType& rhs)
    921     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    922 
    923 }  // namespace verifier
    924 }  // namespace art
    925 
    926 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_H_
    927