• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
IsUndefined()43   virtual bool IsUndefined() const { return false; }
IsConflict()44   virtual bool IsConflict() const { return false; }
IsBoolean()45   virtual bool IsBoolean() const { return false; }
IsByte()46   virtual bool IsByte() const { return false; }
IsChar()47   virtual bool IsChar() const { return false; }
IsShort()48   virtual bool IsShort() const { return false; }
IsInteger()49   virtual bool IsInteger() const { return false; }
IsLongLo()50   virtual bool IsLongLo() const { return false; }
IsLongHi()51   virtual bool IsLongHi() const { return false; }
IsFloat()52   virtual bool IsFloat() const { return false; }
IsDouble()53   virtual bool IsDouble() const { return false; }
IsDoubleLo()54   virtual bool IsDoubleLo() const { return false; }
IsDoubleHi()55   virtual bool IsDoubleHi() const { return false; }
IsUnresolvedReference()56   virtual bool IsUnresolvedReference() const { return false; }
IsUninitializedReference()57   virtual bool IsUninitializedReference() const { return false; }
IsUninitializedThisReference()58   virtual bool IsUninitializedThisReference() const { return false; }
IsUnresolvedAndUninitializedReference()59   virtual bool IsUnresolvedAndUninitializedReference() const { return false; }
IsUnresolvedAndUninitializedThisReference()60   virtual bool IsUnresolvedAndUninitializedThisReference() const { return false; }
IsUnresolvedMergedReference()61   virtual bool IsUnresolvedMergedReference() const { return false; }
IsUnresolvedSuperClass()62   virtual bool IsUnresolvedSuperClass() const { return false; }
IsReference()63   virtual bool IsReference() const { return false; }
IsPreciseReference()64   virtual bool IsPreciseReference() const { return false; }
IsPreciseConstant()65   virtual bool IsPreciseConstant() const { return false; }
IsPreciseConstantLo()66   virtual bool IsPreciseConstantLo() const { return false; }
IsPreciseConstantHi()67   virtual bool IsPreciseConstantHi() const { return false; }
IsImpreciseConstantLo()68   virtual bool IsImpreciseConstantLo() const { return false; }
IsImpreciseConstantHi()69   virtual bool IsImpreciseConstantHi() const { return false; }
IsImpreciseConstant()70   virtual bool IsImpreciseConstant() const { return false; }
IsConstantTypes()71   virtual bool IsConstantTypes() const { return false; }
IsConstant()72   bool IsConstant() const {
73     return IsPreciseConstant() || IsImpreciseConstant();
74   }
IsConstantLo()75   bool IsConstantLo() const {
76     return IsPreciseConstantLo() || IsImpreciseConstantLo();
77   }
IsPrecise()78   bool IsPrecise() const {
79     return IsPreciseConstantLo() || IsPreciseConstant() || IsPreciseConstantHi();
80   }
IsLongConstant()81   bool IsLongConstant() const {
82     return IsConstantLo();
83   }
IsConstantHi()84   bool IsConstantHi() const {
85     return (IsPreciseConstantHi() || IsImpreciseConstantHi());
86   }
IsLongConstantHigh()87   bool IsLongConstantHigh() const {
88     return IsConstantHi();
89   }
IsUninitializedTypes()90   virtual bool IsUninitializedTypes() const { return false; }
IsUnresolvedTypes()91   bool IsUnresolvedTypes() const {
92     return IsUnresolvedReference() || IsUnresolvedAndUninitializedReference() ||
93            IsUnresolvedAndUninitializedThisReference() ||
94            IsUnresolvedMergedReference() || IsUnresolvedSuperClass();
95   }
96 
IsLowHalf()97   bool IsLowHalf() const {
98     return (IsLongLo() || IsDoubleLo() || IsPreciseConstantLo() ||
99             IsImpreciseConstantLo());
100   }
IsHighHalf()101   bool IsHighHalf() const {
102     return (IsLongHi() || IsDoubleHi() || IsPreciseConstantHi() ||
103             IsImpreciseConstantHi());
104   }
IsLongOrDoubleTypes()105   bool IsLongOrDoubleTypes() const {
106     return IsLowHalf();
107   }
108   // Check this is the low half, and that type_h is its matching high-half.
CheckWidePair(const RegType & type_h)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 
IsConstantBoolean()123   bool IsConstantBoolean() const {
124     return IsConstant() && (ConstantValue() >= 0) && (ConstantValue() <= 1);
125   }
IsConstantChar()126   virtual bool IsConstantChar() const {
127     return false;
128   }
IsConstantByte()129   virtual bool IsConstantByte() const {
130     return false;
131   }
IsConstantShort()132   virtual bool IsConstantShort() const {
133     return false;
134   }
IsOne()135   virtual bool IsOne() const {
136     return false;
137   }
IsZero()138   virtual bool IsZero() const {
139     return false;
140   }
IsReferenceTypes()141   bool IsReferenceTypes() const {
142     return IsNonZeroReferenceTypes() || IsZero();
143   }
IsNonZeroReferenceTypes()144   virtual bool IsNonZeroReferenceTypes() const {
145     return false;
146   }
IsCategory1Types()147   bool IsCategory1Types() const {
148     return IsChar() || IsInteger() || IsFloat() || IsConstant() || IsByte() || IsShort() ||
149         IsBoolean();
150   }
IsCategory2Types()151   bool IsCategory2Types() const {
152     return IsLowHalf();  // Don't expect explicit testing of high halves
153   }
IsBooleanTypes()154   bool IsBooleanTypes() const {
155     return IsBoolean() || IsConstantBoolean();
156   }
IsByteTypes()157   bool IsByteTypes() const {
158     return IsConstantByte() || IsByte() || IsBoolean();
159   }
IsShortTypes()160   bool IsShortTypes() const {
161     return IsShort() || IsByte() || IsBoolean() || IsConstantShort();
162   }
IsCharTypes()163   bool IsCharTypes() const {
164     return IsChar() || IsBooleanTypes() || IsConstantChar();
165   }
IsIntegralTypes()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;
IsArrayIndexTypes()173   bool IsArrayIndexTypes() const {
174     return IsIntegralTypes();
175   }
176   // Float type may be derived from any constant type
IsFloatTypes()177   bool IsFloatTypes() const {
178     return IsFloat() || IsConstant();
179   }
IsLongTypes()180   bool IsLongTypes() const {
181     return IsLongLo() || IsLongConstant();
182   }
IsLongHighTypes()183   bool IsLongHighTypes() const {
184     return (IsLongHi() ||
185             IsPreciseConstantHi() ||
186             IsImpreciseConstantHi());
187   }
IsDoubleTypes()188   bool IsDoubleTypes() const {
189     return IsDoubleLo() || IsLongConstant();
190   }
IsDoubleHighTypes()191   bool IsDoubleHighTypes() const {
192     return (IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi());
193   }
IsLong()194   virtual bool IsLong() const {
195     return false;
196   }
HasClass()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;
GetDescriptor()206   const std::string& GetDescriptor() const {
207     DCHECK(HasClass() || (IsUnresolvedTypes() && !IsUnresolvedMergedReference() &&
208                           !IsUnresolvedSuperClass()));
209     return descriptor_;
210   }
GetClass()211   mirror::Class* GetClass() const {
212     DCHECK(!IsUnresolvedReference());
213     DCHECK(klass_ != NULL);
214     DCHECK(HasClass());
215     return klass_;
216   }
GetId()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?
Equals(const RegType & other)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 
~RegType()270   virtual ~RegType() {}
271 
272  protected:
RegType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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:
IsConflict()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:
ConflictType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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:
IsUndefined()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:
UndefinedType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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:
IsInteger()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:
IntegerType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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:
IsBoolean()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:
BooleanType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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:
IsByte()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:
ByteType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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:
IsShort()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:
ShortType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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:
IsChar()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:
CharType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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:
IsFloat()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:
FloatType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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_);
IsLongLo()492   bool IsLongLo() const {
493     return true;
494   }
IsLong()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:
LongLoType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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_);
IsLongHi()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:
LongHiType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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_);
IsDoubleLo()533   bool IsDoubleLo() const {
534     return true;
535   }
IsDouble()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:
DoubleLoType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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;
IsDoubleHi()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:
DoubleHiType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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 
IsZero()581   bool IsZero() const {
582     return IsPreciseConstant() && ConstantValue() == 0;
583   }
IsOne()584   bool IsOne() const {
585     return IsPreciseConstant() && ConstantValue() == 1;
586   }
587 
IsConstantChar()588   bool IsConstantChar() const {
589     return IsConstant() && ConstantValue() >= 0 &&
590            ConstantValue() <= std::numeric_limits<jchar>::max();
591   }
IsConstantByte()592   bool IsConstantByte() const {
593     return IsConstant() &&
594            ConstantValue() >= std::numeric_limits<jbyte>::min() &&
595            ConstantValue() <= std::numeric_limits<jbyte>::max();
596   }
IsConstantShort()597   bool IsConstantShort() const {
598     return IsConstant() &&
599            ConstantValue() >= std::numeric_limits<jshort>::min() &&
600            ConstantValue() <= std::numeric_limits<jshort>::max();
601   }
IsConstantTypes()602   virtual bool IsConstantTypes() const { return true; }
603 
604  private:
605   const uint32_t constant_;
606 };
607 
608 class PreciseConstType : public ConstantType {
609  public:
PreciseConstType(uint32_t constat,uint16_t cache_id)610   PreciseConstType(uint32_t constat, uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
611       : ConstantType(constat, cache_id) {
612   }
613 
IsPreciseConstant()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:
PreciseConstLoType(uint32_t constat,uint16_t cache_id)623   PreciseConstLoType(uint32_t constat, uint16_t cache_id)
624      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
625       : ConstantType(constat, cache_id) {
626   }
IsPreciseConstantLo()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:
PreciseConstHiType(uint32_t constat,uint16_t cache_id)635   PreciseConstHiType(uint32_t constat, uint16_t cache_id)
636      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
637       : ConstantType(constat, cache_id) {
638   }
IsPreciseConstantHi()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_);
IsImpreciseConstant()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:
ImpreciseConstLoType(uint32_t constat,uint16_t cache_id)657   ImpreciseConstLoType(uint32_t constat, uint16_t cache_id)
658      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : ConstantType(constat, cache_id) {
659   }
IsImpreciseConstantLo()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:
ImpreciseConstHiType(uint32_t constat,uint16_t cache_id)668   ImpreciseConstHiType(uint32_t constat, uint16_t cache_id)
669      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : ConstantType(constat, cache_id) {
670   }
IsImpreciseConstantHi()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:
UninitializedType(mirror::Class * klass,const std::string & descriptor,uint32_t allocation_pc,uint16_t cache_id)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 
GetAllocationPc()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:
UninitializedReferenceType(mirror::Class * klass,const std::string & descriptor,uint32_t allocation_pc,uint16_t cache_id)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 
IsUninitializedReference()707   bool IsUninitializedReference() const {
708     return true;
709   }
710 
HasClass()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:
UnresolvedUninitializedRefType(const std::string & descriptor,uint32_t allocation_pc,uint16_t cache_id)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 
IsUnresolvedAndUninitializedReference()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:
UninitializedThisReferenceType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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 
IsUninitializedThisReference()751   virtual bool IsUninitializedThisReference() const {
752     return true;
753   }
754 
HasClass()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:
UnresolvedUninitializedThisRefType(const std::string & descriptor,uint16_t cache_id)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 
IsUnresolvedAndUninitializedThisReference()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:
ReferenceType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)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 
IsReference()792   bool IsReference() const {
793     return true;
794   }
795 
IsNonZeroReferenceTypes()796   bool IsNonZeroReferenceTypes() const {
797     return true;
798   }
799 
HasClass()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 
IsPreciseReference()814   bool IsPreciseReference() const {
815     return true;
816   }
817 
IsNonZeroReferenceTypes()818   bool IsNonZeroReferenceTypes() const {
819     return true;
820   }
821 
HasClass()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:
UnresolvedType(const std::string & descriptor,uint16_t cache_id)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:
UnresolvedReferenceType(const std::string & descriptor,uint16_t cache_id)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 
IsUnresolvedReference()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:
UnresolvedSuperClass(uint16_t child_id,RegTypeCache * reg_type_cache,uint16_t cache_id)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 
IsUnresolvedSuperClass()871   bool IsUnresolvedSuperClass() const {
872     return true;
873   }
874 
GetUnresolvedSuperClassChildId()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:
UnresolvedMergedType(uint16_t left_id,uint16_t right_id,const RegTypeCache * reg_type_cache,uint16_t cache_id)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.
GetTopMergedTypes()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 
IsUnresolvedMergedReference()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