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