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