• 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/logging.h"
30 #include "base/macros.h"
31 #include "dex/primitive.h"
32 #include "gc_root.h"
33 #include "handle.h"
34 #include "handle_scope.h"
35 #include "obj_ptr.h"
36 
37 namespace art HIDDEN {
38 namespace mirror {
39 class Class;
40 class ClassLoader;
41 }  // namespace mirror
42 
43 class ArenaAllocator;
44 class ArenaBitVector;
45 
46 namespace verifier {
47 
48 class MethodVerifier;
49 class RegTypeCache;
50 
51 #define FOR_EACH_CONCRETE_REG_TYPE(V)                                         \
52   V(Undefined)                                                                \
53   V(Conflict)                                                                 \
54   V(Boolean)                                                                  \
55   V(Byte)                                                                     \
56   V(Char)                                                                     \
57   V(Short)                                                                    \
58   V(Integer)                                                                  \
59   V(LongLo)                                                                   \
60   V(LongHi)                                                                   \
61   V(Float)                                                                    \
62   V(DoubleLo)                                                                 \
63   V(DoubleHi)                                                                 \
64   /* Category 1 groups of constant types are ordered by increasing range */   \
65   /* within the non-negative and can-be-negative groups, so that merging */   \
66   /* can simply use the type with the higher kind value. */                   \
67   V(Zero)                                                                     \
68   V(BooleanConstant)                                                          \
69   V(PositiveByteConstant)                                                     \
70   V(PositiveShortConstant)                                                    \
71   V(CharConstant)                                                             \
72   V(ByteConstant)                                                             \
73   V(ShortConstant)                                                            \
74   V(IntegerConstant)                                                          \
75   V(ConstantLo)                                                               \
76   V(ConstantHi)                                                               \
77   V(Null)                                                                     \
78   V(JavaLangObject)                                                           \
79   V(UnresolvedReference)                                                      \
80   V(UninitializedReference)                                                   \
81   V(UninitializedThisReference)                                               \
82   V(UnresolvedUninitializedReference)                                         \
83   V(UnresolvedUninitializedThisReference)                                     \
84   V(UnresolvedMergedReference)                                                \
85   V(Reference)                                                                \
86 
87 #define FORWARD_DECLARE_REG_TYPE(name) class name##Type;
FOR_EACH_CONCRETE_REG_TYPE(FORWARD_DECLARE_REG_TYPE)88 FOR_EACH_CONCRETE_REG_TYPE(FORWARD_DECLARE_REG_TYPE)
89 #undef FORWARD_DECLARE_REG_TYPE
90 
91 /*
92  * RegType holds information about the "type" of data held in a register.
93  */
94 class RegType {
95  public:
96   enum Kind : uint8_t {
97 #define DEFINE_REG_TYPE_ENUMERATOR(name) \
98     k##name,
99     FOR_EACH_CONCRETE_REG_TYPE(DEFINE_REG_TYPE_ENUMERATOR)
100 #undef DEFINE_REG_TYPE_ENUMERATOR
101   };
102 
103   static constexpr size_t NumberOfKinds() {
104 #define ADD_ONE_FOR_CONCRETE_REG_TYPE(name) + 1
105     return 0 FOR_EACH_CONCRETE_REG_TYPE(ADD_ONE_FOR_CONCRETE_REG_TYPE);
106 #undef ADD_ONE_FOR_CONCRETE_REG_TYPE
107   }
108 
109   constexpr Kind GetKind() const { return kind_; }
110 
111 #define DEFINE_IS_CONCRETE_REG_TYPE(name) \
112   constexpr bool Is##name() const { return GetKind() == Kind::k##name; }
113   FOR_EACH_CONCRETE_REG_TYPE(DEFINE_IS_CONCRETE_REG_TYPE)
114 #undef DEFINE_IS_CONCRETE_REG_TYPE
115 
116   constexpr bool IsConstantTypes() const {
117     return IsConstant() || IsConstantLo() || IsConstantHi() || IsNull();
118   }
119   constexpr bool IsConstant() const {
120     return IsZero() ||
121            IsBooleanConstant() ||
122            IsPositiveByteConstant() ||
123            IsPositiveShortConstant() ||
124            IsCharConstant() ||
125            IsByteConstant() ||
126            IsShortConstant() ||
127            IsIntegerConstant();
128   }
129 
130   constexpr bool IsNonZeroReferenceTypes() const;
131   constexpr bool IsUninitializedTypes() const;
132   constexpr bool IsUnresolvedTypes() const;
133 
134   static constexpr bool IsLowHalf(Kind kind) {
135     return kind == Kind::kLongLo || kind == Kind::kDoubleLo || kind == Kind::kConstantLo;
136   }
137   static constexpr bool IsHighHalf(Kind kind) {
138     return kind == Kind::kLongHi || kind == Kind::kDoubleHi || kind == Kind::kConstantHi;
139   }
140 
141   constexpr bool IsLowHalf() const { return IsLowHalf(GetKind()); }
142   constexpr bool IsHighHalf() const { return IsHighHalf(GetKind()); }
143   constexpr bool IsLongOrDoubleTypes() const { return IsLowHalf(); }
144 
145   static constexpr Kind ToHighHalf(Kind low) {
146     static_assert(Kind::kConstantLo + 1 == Kind::kConstantHi);
147     static_assert(Kind::kDoubleLo + 1 == Kind::kDoubleHi);
148     static_assert(Kind::kLongLo + 1 == Kind::kLongHi);
149     DCHECK(low == Kind::kConstantLo || low == Kind::kDoubleLo || low == Kind::kLongLo);
150     return enum_cast<Kind>(low + 1);
151   }
152 
153   // Check that `low` is the low half, and that `high` is its matching high-half.
154   static inline bool CheckWidePair(Kind low, Kind high) {
155     return (low == Kind::kConstantLo || low == Kind::kDoubleLo || low == Kind::kLongLo) &&
156            high == ToHighHalf(low);
157   }
158   // Check this is the low half, and that type_h is its matching high-half.
159   inline bool CheckWidePair(const RegType& type_h) const {
160     return CheckWidePair(GetKind(), type_h.GetKind());
161   }
162 
163   // The high half that corresponds to this low half
164   const RegType& HighHalf(RegTypeCache* cache) const
165       REQUIRES_SHARED(Locks::mutator_lock_);
166 
167   constexpr bool IsReferenceTypes() const {
168     return IsNonZeroReferenceTypes() || IsZero() || IsNull();
169   }
170   constexpr bool IsZeroOrNull() const {
171     return IsZero() || IsNull();
172   }
173   static constexpr bool IsCategory1Types(Kind kind) {
174     return IsIntegralTypes(kind) || kind == kFloat;
175   }
176   constexpr bool IsCategory1Types() const {
177     return IsCategory1Types(GetKind());
178   }
179   constexpr bool IsCategory2Types() const {
180     return IsLowHalf();  // Don't expect explicit testing of high halves
181   }
182   static constexpr bool IsBooleanTypes(Kind kind) {
183     return kind == Kind::kBoolean || kind == Kind::kZero || kind == Kind::kBooleanConstant;
184   }
185   constexpr bool IsBooleanTypes() const { return IsBooleanTypes(GetKind()); }
186   static constexpr bool IsByteTypes(Kind kind) {
187     return kind == kByte ||
188            kind == kPositiveByteConstant ||
189            kind == kByteConstant ||
190            IsBooleanTypes(kind);
191   }
192   constexpr bool IsByteTypes() const {
193     return IsByteTypes(GetKind());
194   }
195   static constexpr bool IsShortTypes(Kind kind) {
196     return kind == kShort ||
197            kind == kPositiveShortConstant ||
198            kind == kShortConstant ||
199            IsByteTypes(kind);
200   }
201   constexpr bool IsShortTypes() const {
202     return IsShortTypes(GetKind());
203   }
204   constexpr bool IsCharTypes() const {
205     return IsChar() ||
206            IsCharConstant() ||
207            IsPositiveShortConstant() ||
208            IsPositiveByteConstant() ||
209            IsBooleanTypes();
210   }
211   static constexpr bool IsIntegralTypes(Kind kind) {
212     return kind == kInteger ||
213            kind == kIntegerConstant ||
214            kind == kChar ||
215            kind == kCharConstant ||
216            IsShortTypes(kind);
217   }
218   constexpr bool IsIntegralTypes() const {
219     return IsIntegralTypes(GetKind());
220   }
221   // Give the constant value encoded, but this shouldn't be called in the
222   // general case.
223   bool IsArrayIndexTypes() const { return IsIntegralTypes(); }
224   // Float type may be derived from any constant type
225   constexpr bool IsFloatTypes() const { return IsFloat() || IsConstant(); }
226   constexpr bool IsLongTypes() const { return IsLongLo() || IsConstantLo(); }
227   constexpr bool IsLongHighTypes() const { return (IsLongHi() || IsConstantHi()); }
228   constexpr bool IsDoubleTypes() const { return IsDoubleLo() || IsConstantLo(); }
229   constexpr bool IsDoubleHighTypes() const { return (IsDoubleHi() || IsConstantHi()); }
230   bool HasClass() const {
231     // The only type with a class is `ReferenceType`. There is no class for
232     // unresolved types and we do not record the class in uninitialized types.
233     // We do not need the class for primitive types.
234     return IsReference();
235   }
236   bool IsArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_);
237   bool IsObjectArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_);
238   Primitive::Type GetPrimitiveType() const;
239   bool IsJavaLangObjectArray() const
240       REQUIRES_SHARED(Locks::mutator_lock_);
241   bool IsInstantiableTypes() const REQUIRES_SHARED(Locks::mutator_lock_);
242   constexpr const std::string_view& GetDescriptor() const {
243     DCHECK(IsJavaLangObject() ||
244            IsReference() ||
245            IsUninitializedTypes() ||
246            (IsUnresolvedTypes() && !IsUnresolvedMergedReference()));
247     return descriptor_;
248   }
249   ObjPtr<mirror::Class> GetClass() const REQUIRES_SHARED(Locks::mutator_lock_);
250   Handle<mirror::Class> GetClassHandle() const REQUIRES_SHARED(Locks::mutator_lock_);
251   uint16_t GetId() const { return cache_id_; }
252 
253   std::string Dump() const REQUIRES_SHARED(Locks::mutator_lock_);
254 
255   enum class Assignability : uint8_t {
256     kAssignable,
257     kNotAssignable,
258     kNarrowingConversion,
259     kReference,
260     kInvalid,
261   };
262 
263   ALWAYS_INLINE static inline Assignability AssignabilityFrom(Kind lhs, Kind rhs);
264 
265   // Are these RegTypes the same?
266   bool Equals(const RegType& other) const { return GetId() == other.GetId(); }
267 
268   // Compute the merge of this register from one edge (path) with incoming_type
269   // from another.
270   const RegType& Merge(const RegType& incoming_type,
271                        RegTypeCache* reg_types,
272                        MethodVerifier* verifier) const
273       REQUIRES_SHARED(Locks::mutator_lock_);
274   // Same as above, but also handles the case where incoming_type == this.
275   const RegType& SafeMerge(const RegType& incoming_type,
276                            RegTypeCache* reg_types,
277                            MethodVerifier* verifier) const
278       REQUIRES_SHARED(Locks::mutator_lock_) {
279     if (Equals(incoming_type)) {
280       return *this;
281     }
282     return Merge(incoming_type, reg_types, verifier);
283   }
284 
285   constexpr ~RegType() {}
286 
287   static void* operator new(size_t size) noexcept {
288     return ::operator new(size);
289   }
290 
291   static void* operator new(size_t size, ArenaAllocator* allocator);
292   static void* operator new(size_t size, ScopedArenaAllocator* allocator) = delete;
293 
294  protected:
295   constexpr RegType(const std::string_view& descriptor, uint16_t cache_id, Kind kind)
296       REQUIRES_SHARED(Locks::mutator_lock_)
297       : descriptor_(descriptor),
298         cache_id_(cache_id),
299         kind_(kind) {}
300 
301   template <typename Class>
302   constexpr void CheckConstructorInvariants([[maybe_unused]] Class* this_) const
303       REQUIRES_SHARED(Locks::mutator_lock_);
304 
305   const std::string_view descriptor_;
306   const uint16_t cache_id_;
307   const Kind kind_;
308 
309   friend class RegTypeCache;
310 
311  private:
312   DISALLOW_COPY_AND_ASSIGN(RegType);
313 };
314 
315 std::ostream& operator<<(std::ostream& os, RegType::Kind kind);
316 std::ostream& operator<<(std::ostream& os, RegType::Assignability assignability);
317 
318 // Bottom type.
319 class ConflictType final : public RegType {
320  public:
321   constexpr ConflictType(uint16_t cache_id)
322       REQUIRES_SHARED(Locks::mutator_lock_);
323 };
324 
325 // A variant of the bottom type used to specify an undefined value in the
326 // incoming registers.
327 // Merging with UndefinedType yields ConflictType which is the true bottom.
328 class UndefinedType final : public RegType {
329  public:
330   constexpr UndefinedType(uint16_t cache_id)
331       REQUIRES_SHARED(Locks::mutator_lock_);
332 };
333 
334 class PrimitiveType : public RegType {
335  public:
PrimitiveType(const std::string_view & descriptor,uint16_t cache_id,Kind kind)336   constexpr PrimitiveType(const std::string_view& descriptor, uint16_t cache_id, Kind kind)
337       REQUIRES_SHARED(Locks::mutator_lock_)
338       : RegType(descriptor, cache_id, kind) {
339     DCHECK_EQ(descriptor.length(), 1u);
340   }
341 };
342 
343 class Cat1Type : public PrimitiveType {
344  public:
Cat1Type(const std::string_view & descriptor,uint16_t cache_id,Kind kind)345   constexpr Cat1Type(const std::string_view& descriptor, uint16_t cache_id, Kind kind)
346       REQUIRES_SHARED(Locks::mutator_lock_)
347       : PrimitiveType(descriptor, cache_id, kind) {}
348 };
349 
350 class IntegerType final : public Cat1Type {
351  public:
352   constexpr IntegerType(const std::string_view& descriptor, uint16_t cache_id)
353       REQUIRES_SHARED(Locks::mutator_lock_);
354 };
355 
356 class BooleanType final : public Cat1Type {
357  public:
358   constexpr BooleanType(const std::string_view& descriptor, uint16_t cache_id)
359       REQUIRES_SHARED(Locks::mutator_lock_);
360 };
361 
362 class ByteType final : public Cat1Type {
363  public:
364   constexpr ByteType(const std::string_view& descriptor, uint16_t cache_id)
365       REQUIRES_SHARED(Locks::mutator_lock_);
366 };
367 
368 class ShortType final : public Cat1Type {
369  public:
370   constexpr ShortType(const std::string_view& descriptor, uint16_t cache_id)
371       REQUIRES_SHARED(Locks::mutator_lock_);
372 };
373 
374 class CharType final : public Cat1Type {
375  public:
376   constexpr CharType(const std::string_view& descriptor, uint16_t cache_id)
377       REQUIRES_SHARED(Locks::mutator_lock_);
378 };
379 
380 class FloatType final : public Cat1Type {
381  public:
382   constexpr FloatType(const std::string_view& descriptor, uint16_t cache_id)
383       REQUIRES_SHARED(Locks::mutator_lock_);
384 };
385 
386 class Cat2Type : public PrimitiveType {
387  public:
Cat2Type(const std::string_view & descriptor,uint16_t cache_id,Kind kind)388   constexpr Cat2Type(const std::string_view& descriptor, uint16_t cache_id, Kind kind)
389       REQUIRES_SHARED(Locks::mutator_lock_)
390       : PrimitiveType(descriptor, cache_id, kind) {}
391 };
392 
393 class LongLoType final : public Cat2Type {
394  public:
395   constexpr LongLoType(const std::string_view& descriptor, uint16_t cache_id)
396       REQUIRES_SHARED(Locks::mutator_lock_);
397 };
398 
399 class LongHiType final : public Cat2Type {
400  public:
401   constexpr LongHiType(const std::string_view& descriptor, uint16_t cache_id)
402       REQUIRES_SHARED(Locks::mutator_lock_);
403 };
404 
405 class DoubleLoType final : public Cat2Type {
406  public:
407   constexpr DoubleLoType(const std::string_view& descriptor, uint16_t cache_id)
408       REQUIRES_SHARED(Locks::mutator_lock_);
409 };
410 
411 class DoubleHiType final : public Cat2Type {
412  public:
413   constexpr DoubleHiType(const std::string_view& descriptor, uint16_t cache_id)
414       REQUIRES_SHARED(Locks::mutator_lock_);
415 };
416 
417 class ConstantType : public RegType {
418  public:
ConstantType(uint16_t cache_id,Kind kind)419   constexpr ConstantType(uint16_t cache_id, Kind kind)
420       REQUIRES_SHARED(Locks::mutator_lock_)
421       : RegType("", cache_id, kind) {}
422 };
423 
424 // Constant 0, or merged constants 0. Can be interpreted as `null`.
425 class ZeroType final : public ConstantType {
426  public:
427   constexpr explicit ZeroType(uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
428 };
429 
430 // Constant 1, or merged constants 0 - 1.
431 class BooleanConstantType final : public ConstantType {
432  public:
433   constexpr explicit BooleanConstantType(uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
434 };
435 
436 // Constants 2 - 0x7f, or merged constants 0 - 0x7f.
437 class PositiveByteConstantType final : public ConstantType {
438  public:
439   constexpr explicit PositiveByteConstantType(uint16_t cache_id)
440       REQUIRES_SHARED(Locks::mutator_lock_);
441 };
442 
443 // Constants 0x80 - 0x7fff, or merged constants 0 - 0x7fff.
444 class PositiveShortConstantType final : public ConstantType {
445  public:
446   constexpr explicit PositiveShortConstantType(uint16_t cache_id)
447       REQUIRES_SHARED(Locks::mutator_lock_);
448 };
449 
450 // Constants 0x8000 - 0xffff, or merged constants 0 - 0xffff.
451 class CharConstantType final : public ConstantType {
452  public:
453   constexpr explicit CharConstantType(uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
454 };
455 
456 // Constants -0x80 - -1, or merged constants -x80 - 0x7f.
457 class ByteConstantType final : public ConstantType {
458  public:
459   constexpr explicit ByteConstantType(uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
460 };
461 
462 // Constants -0x8000 - -0x81, or merged constants -x8000 - 0x7fff.
463 class ShortConstantType final : public ConstantType {
464  public:
465   constexpr explicit ShortConstantType(uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
466 };
467 
468 // Constants -0x80000000 - -0x8001, or merged constants -0x80000000 - 0x7fffffff.
469 class IntegerConstantType final : public ConstantType {
470  public:
471   constexpr explicit IntegerConstantType(uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
472 };
473 
474 class ConstantLoType final : public ConstantType {
475  public:
476   constexpr explicit ConstantLoType(uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
477 };
478 
479 class ConstantHiType final : public ConstantType {
480  public:
481   constexpr explicit ConstantHiType(uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
482 };
483 
484 // Special "null" type that captures the semantics of null / bottom.
485 class NullType final : public ConstantType {
486  public:
487   constexpr NullType(uint16_t cache_id)
488       REQUIRES_SHARED(Locks::mutator_lock_);
489 };
490 
491 // The reference type for `java.lang.Object` class is specialized to allow compile-time
492 // evaluation of merged types and assignablility. Note that we do not record the trivial
493 // assignability for `java.lang.Object` in the `VerifierDeps`.
494 class JavaLangObjectType final : public RegType {
495  public:
496   constexpr JavaLangObjectType(std::string_view descriptor,
497                                uint16_t cache_id,
498                                const UninitializedReferenceType* uninitialized_type)
499       REQUIRES_SHARED(Locks::mutator_lock_);
500 
GetUninitializedType()501   const UninitializedReferenceType* GetUninitializedType() const {
502     return uninitialized_type_;
503   }
504 
505  private:
506   const UninitializedReferenceType* const uninitialized_type_;
507 };
508 
509 // Common parent of all uninitialized types. Uninitialized types are created by
510 // "new" dex
511 // instructions and must be passed to a constructor.
512 class UninitializedType : public RegType {
513  public:
UninitializedType(const std::string_view & descriptor,uint16_t cache_id,Kind kind)514   constexpr UninitializedType(const std::string_view& descriptor, uint16_t cache_id, Kind kind)
515       REQUIRES_SHARED(Locks::mutator_lock_)
516       : RegType(descriptor, cache_id, kind) {}
517 };
518 
519 // A type of register holding a reference to an Object of type GetClass or a
520 // sub-class.
521 class ReferenceType final : public RegType {
522  public:
ReferenceType(Handle<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)523   ReferenceType(Handle<mirror::Class> klass,
524                 const std::string_view& descriptor,
525                 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
526       : RegType(descriptor, cache_id, Kind::kReference),
527         klass_(klass),
528         uninitialized_type_(nullptr) {
529     CheckConstructorInvariants(this);
530   }
531 
GetClassImpl()532   ObjPtr<mirror::Class> GetClassImpl() const REQUIRES_SHARED(Locks::mutator_lock_) {
533     DCHECK(!klass_.IsNull());
534     return klass_.Get();
535   }
536 
GetClassHandleImpl()537   Handle<mirror::Class> GetClassHandleImpl() const REQUIRES_SHARED(Locks::mutator_lock_) {
538     DCHECK(!klass_.IsNull());
539     return klass_;
540   }
541 
GetUninitializedType()542   const UninitializedReferenceType* GetUninitializedType() const {
543     return uninitialized_type_;
544   }
545 
SetUninitializedType(const UninitializedReferenceType * uninitialized_type)546   void SetUninitializedType(const UninitializedReferenceType* uninitialized_type) const {
547     uninitialized_type_ = uninitialized_type;
548   }
549 
550   void CheckClassDescriptor() const REQUIRES_SHARED(Locks::mutator_lock_);
551 
552  private:
553   const Handle<mirror::Class> klass_;
554 
555   // The corresponding uninitialized type created from this type for a `new-instance` instruction.
556   // This member is mutable because it's a part of the type cache, not part of the type itself.
557   mutable const UninitializedReferenceType* uninitialized_type_;
558 };
559 
560 // Similar to ReferenceType but not yet having been passed to a constructor.
561 class UninitializedReferenceType final : public UninitializedType {
562  public:
563   constexpr UninitializedReferenceType(uint16_t cache_id, const RegType* initialized_type)
564       REQUIRES_SHARED(Locks::mutator_lock_);
565 
GetInitializedType()566   const RegType* GetInitializedType() const {
567     return initialized_type_;
568   }
569 
570  private:
571   // The corresponding initialized type to transition to after a constructor call.
572   const RegType* const initialized_type_;
573 };
574 
575 // Similar to UninitializedReferenceType but special case for the this argument
576 // of a constructor.
577 class UninitializedThisReferenceType final : public UninitializedType {
578  public:
UninitializedThisReferenceType(uint16_t cache_id,const ReferenceType * initialized_type)579   UninitializedThisReferenceType(uint16_t cache_id, const ReferenceType* initialized_type)
580       REQUIRES_SHARED(Locks::mutator_lock_)
581       : UninitializedType(initialized_type->GetDescriptor(),
582                           cache_id,
583                           Kind::kUninitializedThisReference),
584         initialized_type_(initialized_type) {
585     CheckConstructorInvariants(this);
586   }
587 
GetInitializedType()588   const ReferenceType* GetInitializedType() const {
589     return initialized_type_;
590   }
591 
592  private:
593   // The corresponding initialized type to transition to after a constructor call.
594   const ReferenceType* initialized_type_;
595 };
596 
597 // Common parent of unresolved types.
598 class UnresolvedType : public RegType {
599  public:
UnresolvedType(const std::string_view & descriptor,uint16_t cache_id,Kind kind)600   UnresolvedType(const std::string_view& descriptor, uint16_t cache_id, Kind kind)
601       REQUIRES_SHARED(Locks::mutator_lock_)
602       : RegType(descriptor, cache_id, kind) {}
603 };
604 
605 // Similar to ReferenceType except the Class couldn't be loaded. Assignability
606 // and other tests made
607 // of this type must be conservative.
608 class UnresolvedReferenceType final : public UnresolvedType {
609  public:
UnresolvedReferenceType(const std::string_view & descriptor,uint16_t cache_id)610   UnresolvedReferenceType(const std::string_view& descriptor, uint16_t cache_id)
611       REQUIRES_SHARED(Locks::mutator_lock_)
612       : UnresolvedType(descriptor, cache_id, Kind::kUnresolvedReference),
613         uninitialized_type_(nullptr) {
614     CheckConstructorInvariants(this);
615   }
616 
GetUninitializedType()617   const UnresolvedUninitializedReferenceType* GetUninitializedType() const {
618     return uninitialized_type_;
619   }
620 
SetUninitializedType(const UnresolvedUninitializedReferenceType * uninitialized_type)621   void SetUninitializedType(const UnresolvedUninitializedReferenceType* uninitialized_type) const {
622     uninitialized_type_ = uninitialized_type;
623   }
624 
625  private:
626   // The corresponding uninitialized type created from this type for a `new-instance` instruction.
627   // This member is mutable because it's a part of the type cache, not part of the type itself.
628   mutable const UnresolvedUninitializedReferenceType* uninitialized_type_;
629 };
630 
631 // Similar to UnresolvedReferenceType but not yet having been passed to a
632 // constructor.
633 class UnresolvedUninitializedReferenceType final : public UninitializedType {
634  public:
UnresolvedUninitializedReferenceType(uint16_t cache_id,const UnresolvedReferenceType * initialized_type)635   UnresolvedUninitializedReferenceType(uint16_t cache_id,
636                                        const UnresolvedReferenceType* initialized_type)
637       REQUIRES_SHARED(Locks::mutator_lock_)
638       : UninitializedType(initialized_type->GetDescriptor(),
639                           cache_id,
640                           Kind::kUnresolvedUninitializedReference),
641         initialized_type_(initialized_type) {
642     CheckConstructorInvariants(this);
643   }
644 
GetInitializedType()645   const UnresolvedReferenceType* GetInitializedType() const {
646     return initialized_type_;
647   }
648 
649  private:
650   // The corresponding initialized type to transition to after a constructor call.
651   const UnresolvedReferenceType* const initialized_type_;
652 };
653 
654 class UnresolvedUninitializedThisReferenceType final : public UninitializedType {
655  public:
UnresolvedUninitializedThisReferenceType(uint16_t cache_id,const UnresolvedReferenceType * initialized_type)656   UnresolvedUninitializedThisReferenceType(uint16_t cache_id,
657                                            const UnresolvedReferenceType* initialized_type)
658       REQUIRES_SHARED(Locks::mutator_lock_)
659       : UninitializedType(initialized_type->GetDescriptor(),
660                           cache_id,
661                           Kind::kUnresolvedUninitializedThisReference),
662         initialized_type_(initialized_type) {
663     CheckConstructorInvariants(this);
664   }
665 
GetInitializedType()666   const UnresolvedReferenceType* GetInitializedType() const {
667     return initialized_type_;
668   }
669 
670  private:
671   // The corresponding initialized type to transition to after a constructor call.
672   const UnresolvedReferenceType* initialized_type_;
673 };
674 
675 // A merge of unresolved (and resolved) types. If the types were resolved this may be
676 // Conflict or another known ReferenceType.
677 class UnresolvedMergedReferenceType final : public UnresolvedType {
678  public:
679   // Note: the constructor will copy the unresolved BitVector, not use it directly.
680   UnresolvedMergedReferenceType(const RegType& resolved,
681                                 const BitVector& unresolved,
682                                 const RegTypeCache* reg_type_cache,
683                                 uint16_t cache_id)
684       REQUIRES_SHARED(Locks::mutator_lock_);
685 
686   // The resolved part. See description below.
GetResolvedPart()687   const RegType& GetResolvedPart() const {
688     return resolved_part_;
689   }
690   // The unresolved part.
GetUnresolvedTypes()691   const BitVector& GetUnresolvedTypes() const {
692     return unresolved_types_;
693   }
694 
695   bool IsArrayTypesImpl() const REQUIRES_SHARED(Locks::mutator_lock_);
696   bool IsObjectArrayTypesImpl() const REQUIRES_SHARED(Locks::mutator_lock_);
697   std::string DumpImpl() const REQUIRES_SHARED(Locks::mutator_lock_);
698 
GetRegTypeCache()699   const RegTypeCache* GetRegTypeCache() const { return reg_type_cache_; }
700 
701  private:
702   void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_);
703 
704   const RegTypeCache* const reg_type_cache_;
705 
706   // The original implementation of merged types was a binary tree. Collection of the flattened
707   // types ("leaves") can be expensive, so we store the expanded list now, as two components:
708   // 1) A resolved component. We use Zero when there is no resolved component, as that will be
709   //    an identity merge.
710   // 2) A bitvector of the unresolved reference types. A bitvector was chosen with the assumption
711   //    that there should not be too many types in flight in practice. (We also bias the index
712   //    against the index of Zero, which is one of the later default entries in any cache.)
713   const RegType& resolved_part_;
714   const BitVector unresolved_types_;
715 };
716 
717 std::ostream& operator<<(std::ostream& os, const RegType& rhs)
718     REQUIRES_SHARED(Locks::mutator_lock_);
719 
720 namespace detail {
721 
722 template <class ConcreteRegType>
723 struct RegTypeToKind { /* No `kind` defined in unspecialized template. */ };
724 
725 #define DEFINE_REG_TYPE_TO_KIND(name) \
726   template<> struct RegTypeToKind<name##Type> { \
727     static constexpr RegType::Kind kind = RegType::Kind::k##name; \
728   };
729 FOR_EACH_CONCRETE_REG_TYPE(DEFINE_REG_TYPE_TO_KIND);
730 #undef DEFINE_REG_TYPE_TO_KIND
731 
732 template <template <class ConcreteRegType> class Traits>
EvaluateTrait(RegType::Kind kind)733 constexpr bool EvaluateTrait(RegType::Kind kind) {
734   switch (kind) {
735 #define DEFINE_EVALUATE_TRAIT_CASE(name) \
736     case RegType::Kind::k##name:         \
737       return Traits<name##Type>::value;
738     FOR_EACH_CONCRETE_REG_TYPE(DEFINE_EVALUATE_TRAIT_CASE);
739 #undef DEFINE_EVALUATE_TRAIT_CASE
740   }
741 }
742 
743 template <class ConcreteRegType>
744 struct IsUninitializedTypes
745     : std::bool_constant<std::is_base_of_v<UninitializedType, ConcreteRegType>> {};
746 
747 template <class ConcreteRegType>
748 struct IsUnresolvedTypes : std::bool_constant<
749     std::is_base_of_v<UnresolvedType, ConcreteRegType> ||
750     // Unresolved uninitialized types do not inherit `UnresolvedType`.
751     // (We're using single-inheritance and they inherit `UninitializedType`.)
752     std::is_same_v<UnresolvedUninitializedReferenceType, ConcreteRegType> ||
753     std::is_same_v<UnresolvedUninitializedThisReferenceType, ConcreteRegType>> {};
754 
755 template <class ConcreteRegType>
756 struct IsNonZeroReferenceTypes
757     : std::bool_constant<std::is_same_v<JavaLangObjectType, ConcreteRegType> ||
758                          std::is_same_v<ReferenceType, ConcreteRegType> ||
759                          std::is_base_of_v<UnresolvedType, ConcreteRegType> ||
760                          std::is_base_of_v<UninitializedType, ConcreteRegType>> {};
761 
762 }  // namespace detail
763 
764 template <typename Class>
CheckConstructorInvariants(Class * this_)765 inline constexpr void RegType::CheckConstructorInvariants([[maybe_unused]] Class* this_) const {
766   static_assert(std::is_final<Class>::value, "Class must be final.");
767   DCHECK_EQ(GetKind(), detail::RegTypeToKind<Class>::kind);
768   if constexpr (std::is_same_v<Class, UndefinedType> ||
769                 std::is_same_v<Class, ConflictType> ||
770                 std::is_same_v<Class, NullType> ||
771                 std::is_base_of_v<ConstantType, Class>) {
772     DCHECK(descriptor_.empty()) << *this;
773   } else if constexpr (std::is_base_of_v<PrimitiveType, Class>) {
774     DCHECK_EQ(descriptor_.length(), 1u) << *this;
775   } else if constexpr (std::is_same_v<Class, JavaLangObjectType>) {
776     DCHECK(!descriptor_.empty()) << *this;
777   } else if constexpr (std::is_same_v<Class, UnresolvedMergedReferenceType>) {
778     // `UnresolvedMergedReferenceType` is an unresolved type but it has an empty descriptor.
779     DCHECK(descriptor_.empty()) << *this;
780   } else if constexpr (detail::IsUnresolvedTypes<Class>::value ||  // NOLINT
781                        std::is_base_of_v<UninitializedType, Class>) {
782     DCHECK(!descriptor_.empty()) << *this;
783   } else if (kIsDebugBuild) {
784     CHECK(IsReference());
785     down_cast<const ReferenceType&>(*this).CheckClassDescriptor();
786   }
787 }
788 
UndefinedType(uint16_t cache_id)789 constexpr UndefinedType::UndefinedType(uint16_t cache_id)
790     : RegType("", cache_id, Kind::kUndefined) {
791   CheckConstructorInvariants(this);
792 }
793 
ConflictType(uint16_t cache_id)794 constexpr ConflictType::ConflictType(uint16_t cache_id)
795     : RegType("", cache_id, Kind::kConflict) {
796   CheckConstructorInvariants(this);
797 }
798 
IntegerType(const std::string_view & descriptor,uint16_t cache_id)799 constexpr IntegerType::IntegerType(const std::string_view& descriptor, uint16_t cache_id)
800     : Cat1Type(descriptor, cache_id, Kind::kInteger) {
801   CheckConstructorInvariants(this);
802 }
803 
BooleanType(const std::string_view & descriptor,uint16_t cache_id)804 constexpr BooleanType::BooleanType(const std::string_view& descriptor, uint16_t cache_id)
805     : Cat1Type(descriptor, cache_id, Kind::kBoolean) {
806   CheckConstructorInvariants(this);
807 }
808 
ByteType(const std::string_view & descriptor,uint16_t cache_id)809 constexpr ByteType::ByteType(const std::string_view& descriptor, uint16_t cache_id)
810     : Cat1Type(descriptor, cache_id, Kind::kByte) {
811   CheckConstructorInvariants(this);
812 }
813 
ShortType(const std::string_view & descriptor,uint16_t cache_id)814 constexpr ShortType::ShortType(const std::string_view& descriptor, uint16_t cache_id)
815     : Cat1Type(descriptor, cache_id, Kind::kShort) {
816   CheckConstructorInvariants(this);
817 }
818 
CharType(const std::string_view & descriptor,uint16_t cache_id)819 constexpr CharType::CharType(const std::string_view& descriptor, uint16_t cache_id)
820     : Cat1Type(descriptor, cache_id, Kind::kChar) {
821   CheckConstructorInvariants(this);
822 }
823 
FloatType(const std::string_view & descriptor,uint16_t cache_id)824 constexpr FloatType::FloatType(const std::string_view& descriptor, uint16_t cache_id)
825     : Cat1Type(descriptor, cache_id, Kind::kFloat) {
826   CheckConstructorInvariants(this);
827 }
828 
LongLoType(const std::string_view & descriptor,uint16_t cache_id)829 constexpr LongLoType::LongLoType(const std::string_view& descriptor, uint16_t cache_id)
830     : Cat2Type(descriptor, cache_id, Kind::kLongLo) {
831   CheckConstructorInvariants(this);
832 }
833 
LongHiType(const std::string_view & descriptor,uint16_t cache_id)834 constexpr LongHiType::LongHiType(const std::string_view& descriptor, uint16_t cache_id)
835     : Cat2Type(descriptor, cache_id, Kind::kLongHi) {
836   CheckConstructorInvariants(this);
837 }
838 
DoubleLoType(const std::string_view & descriptor,uint16_t cache_id)839 constexpr DoubleLoType::DoubleLoType(const std::string_view& descriptor, uint16_t cache_id)
840     : Cat2Type(descriptor, cache_id, Kind::kDoubleLo) {
841   CheckConstructorInvariants(this);
842 }
843 
DoubleHiType(const std::string_view & descriptor,uint16_t cache_id)844 constexpr DoubleHiType::DoubleHiType(const std::string_view& descriptor, uint16_t cache_id)
845     : Cat2Type(descriptor, cache_id, Kind::kDoubleHi) {
846   CheckConstructorInvariants(this);
847 }
848 
ZeroType(uint16_t cache_id)849 constexpr ZeroType::ZeroType(uint16_t cache_id)
850     : ConstantType(cache_id, Kind::kZero) {
851   CheckConstructorInvariants(this);
852 }
853 
BooleanConstantType(uint16_t cache_id)854 constexpr BooleanConstantType::BooleanConstantType(uint16_t cache_id)
855     : ConstantType(cache_id, Kind::kBooleanConstant) {
856   CheckConstructorInvariants(this);
857 }
858 
PositiveByteConstantType(uint16_t cache_id)859 constexpr PositiveByteConstantType::PositiveByteConstantType(uint16_t cache_id)
860     : ConstantType(cache_id, Kind::kPositiveByteConstant) {
861   CheckConstructorInvariants(this);
862 }
863 
PositiveShortConstantType(uint16_t cache_id)864 constexpr PositiveShortConstantType::PositiveShortConstantType(uint16_t cache_id)
865     : ConstantType(cache_id, Kind::kPositiveShortConstant) {
866   CheckConstructorInvariants(this);
867 }
868 
CharConstantType(uint16_t cache_id)869 constexpr CharConstantType::CharConstantType(uint16_t cache_id)
870     : ConstantType(cache_id, Kind::kCharConstant) {
871   CheckConstructorInvariants(this);
872 }
873 
ByteConstantType(uint16_t cache_id)874 constexpr ByteConstantType::ByteConstantType(uint16_t cache_id)
875     : ConstantType(cache_id, Kind::kByteConstant) {
876   CheckConstructorInvariants(this);
877 }
878 
ShortConstantType(uint16_t cache_id)879 constexpr ShortConstantType::ShortConstantType(uint16_t cache_id)
880     : ConstantType(cache_id, Kind::kShortConstant) {
881   CheckConstructorInvariants(this);
882 }
883 
IntegerConstantType(uint16_t cache_id)884 constexpr IntegerConstantType::IntegerConstantType(uint16_t cache_id)
885     : ConstantType(cache_id, Kind::kIntegerConstant) {
886   CheckConstructorInvariants(this);
887 }
888 
ConstantLoType(uint16_t cache_id)889 constexpr ConstantLoType::ConstantLoType(uint16_t cache_id)
890     : ConstantType(cache_id, Kind::kConstantLo) {
891   CheckConstructorInvariants(this);
892 }
893 
ConstantHiType(uint16_t cache_id)894 constexpr ConstantHiType::ConstantHiType(uint16_t cache_id)
895     : ConstantType(cache_id, Kind::kConstantHi) {
896   CheckConstructorInvariants(this);
897 }
898 
NullType(uint16_t cache_id)899 constexpr NullType::NullType(uint16_t cache_id)
900     : ConstantType(cache_id, Kind::kNull) {
901   CheckConstructorInvariants(this);
902 }
903 
JavaLangObjectType(std::string_view descriptor,uint16_t cache_id,const UninitializedReferenceType * uninitialized_type)904 constexpr JavaLangObjectType::JavaLangObjectType(
905     std::string_view descriptor,
906     uint16_t cache_id,
907     const UninitializedReferenceType* uninitialized_type)
908     : RegType(descriptor, cache_id, Kind::kJavaLangObject),
909       uninitialized_type_(uninitialized_type) {
910   CheckConstructorInvariants(this);
911 }
912 
UninitializedReferenceType(uint16_t cache_id,const RegType * initialized_type)913 constexpr UninitializedReferenceType::UninitializedReferenceType(uint16_t cache_id,
914                                                                  const RegType* initialized_type)
915     : UninitializedType(initialized_type->GetDescriptor(),
916                         cache_id,
917                         Kind::kUninitializedReference),
918       initialized_type_(initialized_type) {
919   CheckConstructorInvariants(this);
920 }
921 
IsNonZeroReferenceTypes()922 constexpr bool RegType::IsNonZeroReferenceTypes() const {
923   return detail::EvaluateTrait<detail::IsNonZeroReferenceTypes>(GetKind());
924 }
925 
IsUninitializedTypes()926 constexpr bool RegType::IsUninitializedTypes() const {
927   return detail::EvaluateTrait<detail::IsUninitializedTypes>(GetKind());
928 }
929 
IsUnresolvedTypes()930 constexpr bool RegType::IsUnresolvedTypes() const {
931   return detail::EvaluateTrait<detail::IsUnresolvedTypes>(GetKind());
932 }
933 
934 }  // namespace verifier
935 }  // namespace art
936 
937 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_H_
938