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