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