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