• 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   static bool AssignableFrom(const RegType& lhs,
350                              const RegType& rhs,
351                              bool strict,
352                              MethodVerifier* verifier)
353       REQUIRES_SHARED(Locks::mutator_lock_);
354 
355   DISALLOW_COPY_AND_ASSIGN(RegType);
356 };
357 
358 // Bottom type.
359 class ConflictType final : public RegType {
360  public:
IsConflict()361   bool IsConflict() const override { return true; }
362 
363   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
364 
365   // Get the singleton Conflict instance.
366   static const ConflictType* GetInstance() PURE;
367 
368   // Create the singleton instance.
369   static const ConflictType* CreateInstance(ObjPtr<mirror::Class> klass,
370                                             const std::string_view& descriptor,
371                                             uint16_t cache_id)
372       REQUIRES_SHARED(Locks::mutator_lock_);
373 
374   // Destroy the singleton instance.
375   static void Destroy();
376 
GetAssignmentTypeImpl()377   AssignmentType GetAssignmentTypeImpl() const override {
378     return AssignmentType::kConflict;
379   }
380 
381  private:
ConflictType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)382   ConflictType(ObjPtr<mirror::Class> klass,
383                const std::string_view& descriptor,
384                uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
385       : RegType(klass, descriptor, cache_id) {
386     CheckConstructorInvariants(this);
387   }
388 
389   static const ConflictType* instance_;
390 };
391 
392 // A variant of the bottom type used to specify an undefined value in the
393 // incoming registers.
394 // Merging with UndefinedType yields ConflictType which is the true bottom.
395 class UndefinedType final : public RegType {
396  public:
IsUndefined()397   bool IsUndefined() const override { return true; }
398 
399   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
400 
401   // Get the singleton Undefined instance.
402   static const UndefinedType* GetInstance() PURE;
403 
404   // Create the singleton instance.
405   static const UndefinedType* CreateInstance(ObjPtr<mirror::Class> klass,
406                                              const std::string_view& descriptor,
407                                              uint16_t cache_id)
408       REQUIRES_SHARED(Locks::mutator_lock_);
409 
410   // Destroy the singleton instance.
411   static void Destroy();
412 
GetAssignmentTypeImpl()413   AssignmentType GetAssignmentTypeImpl() const override {
414     return AssignmentType::kNotAssignable;
415   }
416 
417  private:
UndefinedType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)418   UndefinedType(ObjPtr<mirror::Class> klass,
419                 const std::string_view& descriptor,
420                 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
421       : RegType(klass, descriptor, cache_id) {
422     CheckConstructorInvariants(this);
423   }
424 
425   static const UndefinedType* instance_;
426 };
427 
428 class PrimitiveType : public RegType {
429  public:
430   PrimitiveType(ObjPtr<mirror::Class> klass,
431                 const std::string_view& descriptor,
432                 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
433 
HasClassVirtual()434   bool HasClassVirtual() const override { return true; }
435 };
436 
437 class Cat1Type : public PrimitiveType {
438  public:
439   Cat1Type(ObjPtr<mirror::Class> klass,
440            const std::string_view& descriptor,
441            uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
442 };
443 
444 class IntegerType final : public Cat1Type {
445  public:
IsInteger()446   bool IsInteger() const override { return true; }
447   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
448   static const IntegerType* CreateInstance(ObjPtr<mirror::Class> klass,
449                                            const std::string_view& descriptor,
450                                            uint16_t cache_id)
451       REQUIRES_SHARED(Locks::mutator_lock_);
452   static const IntegerType* GetInstance() PURE;
453   static void Destroy();
454 
GetAssignmentTypeImpl()455   AssignmentType GetAssignmentTypeImpl() const override {
456     return AssignmentType::kInteger;
457   }
458 
459  private:
IntegerType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)460   IntegerType(ObjPtr<mirror::Class> klass,
461               const std::string_view& descriptor,
462               uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
463       : Cat1Type(klass, descriptor, cache_id) {
464     CheckConstructorInvariants(this);
465   }
466   static const IntegerType* instance_;
467 };
468 
469 class BooleanType final : public Cat1Type {
470  public:
IsBoolean()471   bool IsBoolean() const override { return true; }
472   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
473   static const BooleanType* CreateInstance(ObjPtr<mirror::Class> klass,
474                                            const std::string_view& descriptor,
475                                            uint16_t cache_id)
476       REQUIRES_SHARED(Locks::mutator_lock_);
477   static const BooleanType* GetInstance() PURE;
478   static void Destroy();
479 
GetAssignmentTypeImpl()480   AssignmentType GetAssignmentTypeImpl() const override {
481     return AssignmentType::kBoolean;
482   }
483 
484  private:
BooleanType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)485   BooleanType(ObjPtr<mirror::Class> klass,
486               const std::string_view& descriptor,
487               uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
488       : Cat1Type(klass, descriptor, cache_id) {
489     CheckConstructorInvariants(this);
490   }
491 
492   static const BooleanType* instance_;
493 };
494 
495 class ByteType final : public Cat1Type {
496  public:
IsByte()497   bool IsByte() const override { return true; }
498   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
499   static const ByteType* CreateInstance(ObjPtr<mirror::Class> klass,
500                                         const std::string_view& descriptor,
501                                         uint16_t cache_id)
502       REQUIRES_SHARED(Locks::mutator_lock_);
503   static const ByteType* GetInstance() PURE;
504   static void Destroy();
505 
GetAssignmentTypeImpl()506   AssignmentType GetAssignmentTypeImpl() const override {
507     return AssignmentType::kByte;
508   }
509 
510  private:
ByteType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)511   ByteType(ObjPtr<mirror::Class> klass,
512            const std::string_view& descriptor,
513            uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
514       : Cat1Type(klass, descriptor, cache_id) {
515     CheckConstructorInvariants(this);
516   }
517   static const ByteType* instance_;
518 };
519 
520 class ShortType final : public Cat1Type {
521  public:
IsShort()522   bool IsShort() const override { return true; }
523   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
524   static const ShortType* CreateInstance(ObjPtr<mirror::Class> klass,
525                                          const std::string_view& descriptor,
526                                          uint16_t cache_id)
527       REQUIRES_SHARED(Locks::mutator_lock_);
528   static const ShortType* GetInstance() PURE;
529   static void Destroy();
530 
GetAssignmentTypeImpl()531   AssignmentType GetAssignmentTypeImpl() const override {
532     return AssignmentType::kShort;
533   }
534 
535  private:
ShortType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)536   ShortType(ObjPtr<mirror::Class> klass, const std::string_view& descriptor,
537             uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
538       : Cat1Type(klass, descriptor, cache_id) {
539     CheckConstructorInvariants(this);
540   }
541   static const ShortType* instance_;
542 };
543 
544 class CharType final : public Cat1Type {
545  public:
IsChar()546   bool IsChar() const override { return true; }
547   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
548   static const CharType* CreateInstance(ObjPtr<mirror::Class> klass,
549                                         const std::string_view& descriptor,
550                                         uint16_t cache_id)
551       REQUIRES_SHARED(Locks::mutator_lock_);
552   static const CharType* GetInstance() PURE;
553   static void Destroy();
554 
GetAssignmentTypeImpl()555   AssignmentType GetAssignmentTypeImpl() const override {
556     return AssignmentType::kChar;
557   }
558 
559  private:
CharType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)560   CharType(ObjPtr<mirror::Class> klass,
561            const std::string_view& descriptor,
562            uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
563       : Cat1Type(klass, descriptor, cache_id) {
564     CheckConstructorInvariants(this);
565   }
566   static const CharType* instance_;
567 };
568 
569 class FloatType final : public Cat1Type {
570  public:
IsFloat()571   bool IsFloat() const override { return true; }
572   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
573   static const FloatType* CreateInstance(ObjPtr<mirror::Class> klass,
574                                          const std::string_view& descriptor,
575                                          uint16_t cache_id)
576       REQUIRES_SHARED(Locks::mutator_lock_);
577   static const FloatType* GetInstance() PURE;
578   static void Destroy();
579 
GetAssignmentTypeImpl()580   AssignmentType GetAssignmentTypeImpl() const override {
581     return AssignmentType::kFloat;
582   }
583 
584  private:
FloatType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)585   FloatType(ObjPtr<mirror::Class> klass,
586             const std::string_view& descriptor,
587             uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
588       : Cat1Type(klass, descriptor, cache_id) {
589     CheckConstructorInvariants(this);
590   }
591   static const FloatType* instance_;
592 };
593 
594 class Cat2Type : public PrimitiveType {
595  public:
596   Cat2Type(ObjPtr<mirror::Class> klass,
597            const std::string_view& descriptor,
598            uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
599 };
600 
601 class LongLoType final : public Cat2Type {
602  public:
603   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
IsLongLo()604   bool IsLongLo() const override { return true; }
IsLong()605   bool IsLong() const override { return true; }
606   static const LongLoType* CreateInstance(ObjPtr<mirror::Class> klass,
607                                           const std::string_view& descriptor,
608                                           uint16_t cache_id)
609       REQUIRES_SHARED(Locks::mutator_lock_);
610   static const LongLoType* GetInstance() PURE;
611   static void Destroy();
612 
GetAssignmentTypeImpl()613   AssignmentType GetAssignmentTypeImpl() const override {
614     return AssignmentType::kLongLo;
615   }
616 
617  private:
LongLoType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)618   LongLoType(ObjPtr<mirror::Class> klass,
619              const std::string_view& descriptor,
620              uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
621       : Cat2Type(klass, descriptor, cache_id) {
622     CheckConstructorInvariants(this);
623   }
624   static const LongLoType* instance_;
625 };
626 
627 class LongHiType final : public Cat2Type {
628  public:
629   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
IsLongHi()630   bool IsLongHi() const override { return true; }
631   static const LongHiType* CreateInstance(ObjPtr<mirror::Class> klass,
632                                           const std::string_view& descriptor,
633                                           uint16_t cache_id)
634       REQUIRES_SHARED(Locks::mutator_lock_);
635   static const LongHiType* GetInstance() PURE;
636   static void Destroy();
637 
GetAssignmentTypeImpl()638   AssignmentType GetAssignmentTypeImpl() const override {
639     return AssignmentType::kNotAssignable;
640   }
641 
642  private:
LongHiType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)643   LongHiType(ObjPtr<mirror::Class> klass,
644              const std::string_view& descriptor,
645              uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
646       : Cat2Type(klass, descriptor, cache_id) {
647     CheckConstructorInvariants(this);
648   }
649   static const LongHiType* instance_;
650 };
651 
652 class DoubleLoType final : public Cat2Type {
653  public:
654   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
IsDoubleLo()655   bool IsDoubleLo() const override { return true; }
IsDouble()656   bool IsDouble() const override { return true; }
657   static const DoubleLoType* CreateInstance(ObjPtr<mirror::Class> klass,
658                                             const std::string_view& descriptor,
659                                             uint16_t cache_id)
660       REQUIRES_SHARED(Locks::mutator_lock_);
661   static const DoubleLoType* GetInstance() PURE;
662   static void Destroy();
663 
GetAssignmentTypeImpl()664   AssignmentType GetAssignmentTypeImpl() const override {
665     return AssignmentType::kDoubleLo;
666   }
667 
668  private:
DoubleLoType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)669   DoubleLoType(ObjPtr<mirror::Class> klass,
670                const std::string_view& descriptor,
671                uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
672       : Cat2Type(klass, descriptor, cache_id) {
673     CheckConstructorInvariants(this);
674   }
675   static const DoubleLoType* instance_;
676 };
677 
678 class DoubleHiType final : public Cat2Type {
679  public:
680   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
IsDoubleHi()681   bool IsDoubleHi() const override { return true; }
682   static const DoubleHiType* CreateInstance(ObjPtr<mirror::Class> klass,
683                                             const std::string_view& descriptor,
684                                             uint16_t cache_id)
685       REQUIRES_SHARED(Locks::mutator_lock_);
686   static const DoubleHiType* GetInstance() PURE;
687   static void Destroy();
688 
GetAssignmentTypeImpl()689   AssignmentType GetAssignmentTypeImpl() const override {
690     return AssignmentType::kNotAssignable;
691   }
692 
693  private:
DoubleHiType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)694   DoubleHiType(ObjPtr<mirror::Class> klass,
695                const std::string_view& descriptor,
696                uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
697       : Cat2Type(klass, descriptor, cache_id) {
698     CheckConstructorInvariants(this);
699   }
700   static const DoubleHiType* instance_;
701 };
702 
703 class ConstantType : public RegType {
704  public:
ConstantType(uint32_t constant,uint16_t cache_id)705   ConstantType(uint32_t constant, uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
706       : RegType(nullptr, "", cache_id), constant_(constant) {
707   }
708 
709 
710   // If this is a 32-bit constant, what is the value? This value may be
711   // imprecise in which case
712   // the value represents part of the integer range of values that may be held
713   // in the register.
ConstantValue()714   int32_t ConstantValue() const {
715     DCHECK(IsConstantTypes());
716     return constant_;
717   }
718 
ConstantValueLo()719   int32_t ConstantValueLo() const {
720     DCHECK(IsConstantLo());
721     return constant_;
722   }
723 
ConstantValueHi()724   int32_t ConstantValueHi() const {
725     if (IsConstantHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()) {
726       return constant_;
727     } else {
728       DCHECK(false);
729       return 0;
730     }
731   }
732 
IsZero()733   bool IsZero() const override {
734     return IsPreciseConstant() && ConstantValue() == 0;
735   }
IsOne()736   bool IsOne() const override {
737     return IsPreciseConstant() && ConstantValue() == 1;
738   }
739 
IsConstantChar()740   bool IsConstantChar() const override {
741     return IsConstant() && ConstantValue() >= 0 &&
742            ConstantValue() <= std::numeric_limits<uint16_t>::max();
743   }
IsConstantByte()744   bool IsConstantByte() const override {
745     return IsConstant() &&
746            ConstantValue() >= std::numeric_limits<int8_t>::min() &&
747            ConstantValue() <= std::numeric_limits<int8_t>::max();
748   }
IsConstantShort()749   bool IsConstantShort() const override {
750     return IsConstant() &&
751            ConstantValue() >= std::numeric_limits<int16_t>::min() &&
752            ConstantValue() <= std::numeric_limits<int16_t>::max();
753   }
IsConstantTypes()754   bool IsConstantTypes() const override { return true; }
755 
GetAssignmentTypeImpl()756   AssignmentType GetAssignmentTypeImpl() const override {
757     return AssignmentType::kNotAssignable;
758   }
759 
760  private:
761   const uint32_t constant_;
762 };
763 
764 class PreciseConstType final : public ConstantType {
765  public:
PreciseConstType(uint32_t constant,uint16_t cache_id)766   PreciseConstType(uint32_t constant, uint16_t cache_id)
767       REQUIRES_SHARED(Locks::mutator_lock_)
768       : ConstantType(constant, cache_id) {
769     CheckConstructorInvariants(this);
770   }
771 
IsPreciseConstant()772   bool IsPreciseConstant() const override { return true; }
773 
774   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
775 
GetAssignmentTypeImpl()776   AssignmentType GetAssignmentTypeImpl() const override {
777     return AssignmentType::kNotAssignable;
778   }
779 };
780 
781 class PreciseConstLoType final : public ConstantType {
782  public:
PreciseConstLoType(uint32_t constant,uint16_t cache_id)783   PreciseConstLoType(uint32_t constant, uint16_t cache_id)
784       REQUIRES_SHARED(Locks::mutator_lock_)
785       : ConstantType(constant, cache_id) {
786     CheckConstructorInvariants(this);
787   }
IsPreciseConstantLo()788   bool IsPreciseConstantLo() const override { return true; }
789   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
790 
GetAssignmentTypeImpl()791   AssignmentType GetAssignmentTypeImpl() const override {
792     return AssignmentType::kNotAssignable;
793   }
794 };
795 
796 class PreciseConstHiType final : public ConstantType {
797  public:
PreciseConstHiType(uint32_t constant,uint16_t cache_id)798   PreciseConstHiType(uint32_t constant, uint16_t cache_id)
799       REQUIRES_SHARED(Locks::mutator_lock_)
800       : ConstantType(constant, cache_id) {
801     CheckConstructorInvariants(this);
802   }
IsPreciseConstantHi()803   bool IsPreciseConstantHi() const override { return true; }
804   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
805 
GetAssignmentTypeImpl()806   AssignmentType GetAssignmentTypeImpl() const override {
807     return AssignmentType::kNotAssignable;
808   }
809 };
810 
811 class ImpreciseConstType final : public ConstantType {
812  public:
ImpreciseConstType(uint32_t constat,uint16_t cache_id)813   ImpreciseConstType(uint32_t constat, uint16_t cache_id)
814        REQUIRES_SHARED(Locks::mutator_lock_)
815        : ConstantType(constat, cache_id) {
816     CheckConstructorInvariants(this);
817   }
IsImpreciseConstant()818   bool IsImpreciseConstant() const override { return true; }
819   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
820 
GetAssignmentTypeImpl()821   AssignmentType GetAssignmentTypeImpl() const override {
822     return AssignmentType::kNotAssignable;
823   }
824 };
825 
826 class ImpreciseConstLoType final : public ConstantType {
827  public:
ImpreciseConstLoType(uint32_t constant,uint16_t cache_id)828   ImpreciseConstLoType(uint32_t constant, uint16_t cache_id)
829       REQUIRES_SHARED(Locks::mutator_lock_)
830       : ConstantType(constant, cache_id) {
831     CheckConstructorInvariants(this);
832   }
IsImpreciseConstantLo()833   bool IsImpreciseConstantLo() const override { return true; }
834   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
835 
GetAssignmentTypeImpl()836   AssignmentType GetAssignmentTypeImpl() const override {
837     return AssignmentType::kNotAssignable;
838   }
839 };
840 
841 class ImpreciseConstHiType final : public ConstantType {
842  public:
ImpreciseConstHiType(uint32_t constant,uint16_t cache_id)843   ImpreciseConstHiType(uint32_t constant, uint16_t cache_id)
844       REQUIRES_SHARED(Locks::mutator_lock_)
845       : ConstantType(constant, cache_id) {
846     CheckConstructorInvariants(this);
847   }
IsImpreciseConstantHi()848   bool IsImpreciseConstantHi() const override { return true; }
849   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
850 
GetAssignmentTypeImpl()851   AssignmentType GetAssignmentTypeImpl() const override {
852     return AssignmentType::kNotAssignable;
853   }
854 };
855 
856 // Special "null" type that captures the semantics of null / bottom.
857 class NullType final : public RegType {
858  public:
IsNull()859   bool IsNull() const override {
860     return true;
861   }
862 
863   // Get the singleton Null instance.
864   static const NullType* GetInstance() PURE;
865 
866   // Create the singleton instance.
867   static const NullType* CreateInstance(ObjPtr<mirror::Class> klass,
868                                         const std::string_view& descriptor,
869                                         uint16_t cache_id)
870       REQUIRES_SHARED(Locks::mutator_lock_);
871 
872   static void Destroy();
873 
Dump()874   std::string Dump() const override {
875     return "null";
876   }
877 
GetAssignmentTypeImpl()878   AssignmentType GetAssignmentTypeImpl() const override {
879     return AssignmentType::kReference;
880   }
881 
IsConstantTypes()882   bool IsConstantTypes() const override {
883     return true;
884   }
885 
886  private:
NullType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)887   NullType(ObjPtr<mirror::Class> klass, const std::string_view& descriptor, uint16_t cache_id)
888       REQUIRES_SHARED(Locks::mutator_lock_)
889       : RegType(klass, descriptor, cache_id) {
890     CheckConstructorInvariants(this);
891   }
892 
893   static const NullType* instance_;
894 };
895 
896 // Common parent of all uninitialized types. Uninitialized types are created by
897 // "new" dex
898 // instructions and must be passed to a constructor.
899 class UninitializedType : public RegType {
900  public:
UninitializedType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint32_t allocation_pc,uint16_t cache_id)901   UninitializedType(ObjPtr<mirror::Class> klass,
902                     const std::string_view& descriptor,
903                     uint32_t allocation_pc,
904                     uint16_t cache_id)
905       : RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {}
906 
907   bool IsUninitializedTypes() const override;
908   bool IsNonZeroReferenceTypes() const override;
909 
GetAllocationPc()910   uint32_t GetAllocationPc() const {
911     DCHECK(IsUninitializedTypes());
912     return allocation_pc_;
913   }
914 
GetAssignmentTypeImpl()915   AssignmentType GetAssignmentTypeImpl() const override {
916     return AssignmentType::kReference;
917   }
918 
919  private:
920   const uint32_t allocation_pc_;
921 };
922 
923 // Similar to ReferenceType but not yet having been passed to a constructor.
924 class UninitializedReferenceType final : public UninitializedType {
925  public:
UninitializedReferenceType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint32_t allocation_pc,uint16_t cache_id)926   UninitializedReferenceType(ObjPtr<mirror::Class> klass,
927                              const std::string_view& descriptor,
928                              uint32_t allocation_pc,
929                              uint16_t cache_id)
930       REQUIRES_SHARED(Locks::mutator_lock_)
931       : UninitializedType(klass, descriptor, allocation_pc, cache_id) {
932     CheckConstructorInvariants(this);
933   }
934 
IsUninitializedReference()935   bool IsUninitializedReference() const override { return true; }
936 
HasClassVirtual()937   bool HasClassVirtual() const override { return true; }
938 
939   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
940 };
941 
942 // Similar to UnresolvedReferenceType but not yet having been passed to a
943 // constructor.
944 class UnresolvedUninitializedRefType final : public UninitializedType {
945  public:
UnresolvedUninitializedRefType(const std::string_view & descriptor,uint32_t allocation_pc,uint16_t cache_id)946   UnresolvedUninitializedRefType(const std::string_view& descriptor,
947                                  uint32_t allocation_pc,
948                                  uint16_t cache_id)
949       REQUIRES_SHARED(Locks::mutator_lock_)
950       : UninitializedType(nullptr, descriptor, allocation_pc, cache_id) {
951     CheckConstructorInvariants(this);
952   }
953 
IsUnresolvedAndUninitializedReference()954   bool IsUnresolvedAndUninitializedReference() const override { return true; }
955 
IsUnresolvedTypes()956   bool IsUnresolvedTypes() const override { return true; }
957 
958   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
959 
960  private:
961   void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override;
962 };
963 
964 // Similar to UninitializedReferenceType but special case for the this argument
965 // of a constructor.
966 class UninitializedThisReferenceType final : public UninitializedType {
967  public:
UninitializedThisReferenceType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)968   UninitializedThisReferenceType(ObjPtr<mirror::Class> klass,
969                                  const std::string_view& descriptor,
970                                  uint16_t cache_id)
971       REQUIRES_SHARED(Locks::mutator_lock_)
972       : UninitializedType(klass, descriptor, 0, cache_id) {
973     CheckConstructorInvariants(this);
974   }
975 
IsUninitializedThisReference()976   bool IsUninitializedThisReference() const override { return true; }
977 
HasClassVirtual()978   bool HasClassVirtual() 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 class UnresolvedUninitializedThisRefType final : public UninitializedType {
987  public:
UnresolvedUninitializedThisRefType(const std::string_view & descriptor,uint16_t cache_id)988   UnresolvedUninitializedThisRefType(const std::string_view& descriptor, uint16_t cache_id)
989       REQUIRES_SHARED(Locks::mutator_lock_)
990       : UninitializedType(nullptr, descriptor, 0, cache_id) {
991     CheckConstructorInvariants(this);
992   }
993 
IsUnresolvedAndUninitializedThisReference()994   bool IsUnresolvedAndUninitializedThisReference() const override { return true; }
995 
IsUnresolvedTypes()996   bool IsUnresolvedTypes() const override { return true; }
997 
998   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
999 
1000  private:
1001   void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override;
1002 };
1003 
1004 // A type of register holding a reference to an Object of type GetClass or a
1005 // sub-class.
1006 class ReferenceType final : public RegType {
1007  public:
ReferenceType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)1008   ReferenceType(ObjPtr<mirror::Class> klass,
1009                 const std::string_view& descriptor,
1010                 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
1011       : RegType(klass, descriptor, cache_id) {
1012     CheckConstructorInvariants(this);
1013   }
1014 
IsReference()1015   bool IsReference() const override { return true; }
1016 
IsNonZeroReferenceTypes()1017   bool IsNonZeroReferenceTypes() const override { return true; }
1018 
HasClassVirtual()1019   bool HasClassVirtual() const override { return true; }
1020 
1021   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
1022 
GetAssignmentTypeImpl()1023   AssignmentType GetAssignmentTypeImpl() const override {
1024     return AssignmentType::kReference;
1025   }
1026 };
1027 
1028 // A type of register holding a reference to an Object of type GetClass and only
1029 // an object of that
1030 // type.
1031 class PreciseReferenceType final : public RegType {
1032  public:
1033   PreciseReferenceType(ObjPtr<mirror::Class> klass,
1034                        const std::string_view& descriptor,
1035                        uint16_t cache_id)
1036       REQUIRES_SHARED(Locks::mutator_lock_);
1037 
IsPreciseReference()1038   bool IsPreciseReference() const override { return true; }
1039 
IsNonZeroReferenceTypes()1040   bool IsNonZeroReferenceTypes() const override { return true; }
1041 
HasClassVirtual()1042   bool HasClassVirtual() const override { return true; }
1043 
1044   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
1045 
GetAssignmentTypeImpl()1046   AssignmentType GetAssignmentTypeImpl() const override {
1047     return AssignmentType::kReference;
1048   }
1049 };
1050 
1051 // Common parent of unresolved types.
1052 class UnresolvedType : public RegType {
1053  public:
UnresolvedType(const std::string_view & descriptor,uint16_t cache_id)1054   UnresolvedType(const std::string_view& descriptor, uint16_t cache_id)
1055       REQUIRES_SHARED(Locks::mutator_lock_)
1056       : RegType(nullptr, descriptor, cache_id) {}
1057 
1058   bool IsNonZeroReferenceTypes() const override;
1059 
GetAssignmentTypeImpl()1060   AssignmentType GetAssignmentTypeImpl() const override {
1061     return AssignmentType::kReference;
1062   }
1063 };
1064 
1065 // Similar to ReferenceType except the Class couldn't be loaded. Assignability
1066 // and other tests made
1067 // of this type must be conservative.
1068 class UnresolvedReferenceType final : public UnresolvedType {
1069  public:
UnresolvedReferenceType(const std::string_view & descriptor,uint16_t cache_id)1070   UnresolvedReferenceType(const std::string_view& descriptor, uint16_t cache_id)
1071       REQUIRES_SHARED(Locks::mutator_lock_)
1072       : UnresolvedType(descriptor, cache_id) {
1073     CheckConstructorInvariants(this);
1074   }
1075 
IsUnresolvedReference()1076   bool IsUnresolvedReference() const override { return true; }
1077 
IsUnresolvedTypes()1078   bool IsUnresolvedTypes() const override { return true; }
1079 
1080   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
1081 
1082  private:
1083   void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override;
1084 };
1085 
1086 // Type representing the super-class of an unresolved type.
1087 class UnresolvedSuperClass final : public UnresolvedType {
1088  public:
UnresolvedSuperClass(uint16_t child_id,RegTypeCache * reg_type_cache,uint16_t cache_id)1089   UnresolvedSuperClass(uint16_t child_id, RegTypeCache* reg_type_cache,
1090                        uint16_t cache_id)
1091       REQUIRES_SHARED(Locks::mutator_lock_)
1092       : UnresolvedType("", cache_id),
1093         unresolved_child_id_(child_id),
1094         reg_type_cache_(reg_type_cache) {
1095     CheckConstructorInvariants(this);
1096   }
1097 
IsUnresolvedSuperClass()1098   bool IsUnresolvedSuperClass() const override { return true; }
1099 
IsUnresolvedTypes()1100   bool IsUnresolvedTypes() const override { return true; }
1101 
GetUnresolvedSuperClassChildId()1102   uint16_t GetUnresolvedSuperClassChildId() const {
1103     DCHECK(IsUnresolvedSuperClass());
1104     return static_cast<uint16_t>(unresolved_child_id_ & 0xFFFF);
1105   }
1106 
1107   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
1108 
1109  private:
1110   void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override;
1111 
1112   const uint16_t unresolved_child_id_;
1113   const RegTypeCache* const reg_type_cache_;
1114 };
1115 
1116 // A merge of unresolved (and resolved) types. If the types were resolved this may be
1117 // Conflict or another known ReferenceType.
1118 class UnresolvedMergedType final : public UnresolvedType {
1119  public:
1120   // Note: the constructor will copy the unresolved BitVector, not use it directly.
1121   UnresolvedMergedType(const RegType& resolved,
1122                        const BitVector& unresolved,
1123                        const RegTypeCache* reg_type_cache,
1124                        uint16_t cache_id)
1125       REQUIRES_SHARED(Locks::mutator_lock_);
1126 
1127   // The resolved part. See description below.
GetResolvedPart()1128   const RegType& GetResolvedPart() const {
1129     return resolved_part_;
1130   }
1131   // The unresolved part.
GetUnresolvedTypes()1132   const BitVector& GetUnresolvedTypes() const {
1133     return unresolved_types_;
1134   }
1135 
IsUnresolvedMergedReference()1136   bool IsUnresolvedMergedReference() const override { return true; }
1137 
IsUnresolvedTypes()1138   bool IsUnresolvedTypes() const override { return true; }
1139 
1140   bool IsArrayTypes() const override REQUIRES_SHARED(Locks::mutator_lock_);
1141   bool IsObjectArrayTypes() const override REQUIRES_SHARED(Locks::mutator_lock_);
1142 
1143   std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
1144 
GetRegTypeCache()1145   const RegTypeCache* GetRegTypeCache() const { return reg_type_cache_; }
1146 
1147  private:
1148   void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override;
1149 
1150   const RegTypeCache* const reg_type_cache_;
1151 
1152   // The original implementation of merged types was a binary tree. Collection of the flattened
1153   // types ("leaves") can be expensive, so we store the expanded list now, as two components:
1154   // 1) A resolved component. We use Zero when there is no resolved component, as that will be
1155   //    an identity merge.
1156   // 2) A bitvector of the unresolved reference types. A bitvector was chosen with the assumption
1157   //    that there should not be too many types in flight in practice. (We also bias the index
1158   //    against the index of Zero, which is one of the later default entries in any cache.)
1159   const RegType& resolved_part_;
1160   const BitVector unresolved_types_;
1161 };
1162 
1163 std::ostream& operator<<(std::ostream& os, const RegType& rhs)
1164     REQUIRES_SHARED(Locks::mutator_lock_);
1165 
1166 }  // namespace verifier
1167 }  // namespace art
1168 
1169 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_H_
1170