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