1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_VERIFIER_REG_TYPE_H_ 18 #define ART_RUNTIME_VERIFIER_REG_TYPE_H_ 19 20 #include <stdint.h> 21 #include <limits> 22 #include <set> 23 #include <string> 24 #include <string_view> 25 26 #include "base/arena_object.h" 27 #include "base/bit_vector.h" 28 #include "base/locks.h" 29 #include "base/macros.h" 30 #include "dex/primitive.h" 31 #include "gc_root.h" 32 #include "handle_scope.h" 33 #include "obj_ptr.h" 34 35 namespace art { 36 namespace mirror { 37 class Class; 38 class ClassLoader; 39 } // namespace mirror 40 41 class ArenaBitVector; 42 class ScopedArenaAllocator; 43 44 namespace verifier { 45 46 class MethodVerifier; 47 class RegTypeCache; 48 49 /* 50 * RegType holds information about the "type" of data held in a register. 51 */ 52 class RegType { 53 public: 54 virtual bool IsUndefined() const { return false; } 55 virtual bool IsConflict() const { return false; } 56 virtual bool IsBoolean() const { return false; } 57 virtual bool IsByte() const { return false; } 58 virtual bool IsChar() const { return false; } 59 virtual bool IsShort() const { return false; } 60 virtual bool IsInteger() const { return false; } 61 virtual bool IsLongLo() const { return false; } 62 virtual bool IsLongHi() const { return false; } 63 virtual bool IsFloat() const { return false; } 64 virtual bool IsDouble() const { return false; } 65 virtual bool IsDoubleLo() const { return false; } 66 virtual bool IsDoubleHi() const { return false; } 67 virtual bool IsUnresolvedReference() const { return false; } 68 virtual bool IsUninitializedReference() const { return false; } 69 virtual bool IsUninitializedThisReference() const { return false; } 70 virtual bool IsUnresolvedAndUninitializedReference() const { return false; } 71 virtual bool IsUnresolvedAndUninitializedThisReference() const { 72 return false; 73 } 74 virtual bool IsUnresolvedMergedReference() const { return false; } 75 virtual bool IsUnresolvedSuperClass() const { return false; } 76 virtual bool IsReference() const { return false; } 77 virtual bool IsPreciseReference() const { return false; } 78 virtual bool IsPreciseConstant() const { return false; } 79 virtual bool IsPreciseConstantLo() const { return false; } 80 virtual bool IsPreciseConstantHi() const { return false; } 81 virtual bool IsImpreciseConstantLo() const { return false; } 82 virtual bool IsImpreciseConstantHi() const { return false; } 83 virtual bool IsImpreciseConstant() const { return false; } 84 virtual bool IsConstantTypes() const { return false; } 85 bool IsConstant() const { 86 return IsImpreciseConstant() || IsPreciseConstant(); 87 } 88 bool IsConstantLo() const { 89 return IsImpreciseConstantLo() || IsPreciseConstantLo(); 90 } 91 bool IsPrecise() const { 92 return IsPreciseConstantLo() || IsPreciseConstant() || 93 IsPreciseConstantHi(); 94 } 95 bool IsLongConstant() const { return IsConstantLo(); } 96 bool IsConstantHi() const { 97 return (IsPreciseConstantHi() || IsImpreciseConstantHi()); 98 } 99 bool IsLongConstantHigh() const { return IsConstantHi(); } 100 virtual bool IsUninitializedTypes() const { return false; } 101 virtual bool IsUnresolvedTypes() const { return false; } 102 103 bool IsLowHalf() const { 104 return (IsLongLo() || IsDoubleLo() || IsPreciseConstantLo() || IsImpreciseConstantLo()); 105 } 106 bool IsHighHalf() const { 107 return (IsLongHi() || IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()); 108 } 109 bool IsLongOrDoubleTypes() const { return IsLowHalf(); } 110 // Check this is the low half, and that type_h is its matching high-half. 111 inline bool CheckWidePair(const RegType& type_h) const { 112 if (IsLowHalf()) { 113 return ((IsImpreciseConstantLo() && type_h.IsPreciseConstantHi()) || 114 (IsImpreciseConstantLo() && type_h.IsImpreciseConstantHi()) || 115 (IsPreciseConstantLo() && type_h.IsPreciseConstantHi()) || 116 (IsPreciseConstantLo() && type_h.IsImpreciseConstantHi()) || 117 (IsDoubleLo() && type_h.IsDoubleHi()) || 118 (IsLongLo() && type_h.IsLongHi())); 119 } 120 return false; 121 } 122 // The high half that corresponds to this low half 123 const RegType& HighHalf(RegTypeCache* cache) const 124 REQUIRES_SHARED(Locks::mutator_lock_); 125 126 bool IsConstantBoolean() const; 127 virtual bool IsConstantChar() const { return false; } 128 virtual bool IsConstantByte() const { return false; } 129 virtual bool IsConstantShort() const { return false; } 130 virtual bool IsOne() const { return false; } 131 virtual bool IsZero() const { return false; } 132 virtual bool IsNull() const { return false; } 133 bool IsReferenceTypes() const { 134 return IsNonZeroReferenceTypes() || IsZero() || IsNull(); 135 } 136 bool IsZeroOrNull() const { 137 return IsZero() || IsNull(); 138 } 139 virtual bool IsNonZeroReferenceTypes() const { return false; } 140 bool IsCategory1Types() const { 141 return IsChar() || IsInteger() || IsFloat() || IsConstant() || IsByte() || 142 IsShort() || IsBoolean(); 143 } 144 bool IsCategory2Types() const { 145 return IsLowHalf(); // Don't expect explicit testing of high halves 146 } 147 bool IsBooleanTypes() const { return IsBoolean() || IsConstantBoolean(); } 148 bool IsByteTypes() const { 149 return IsConstantByte() || IsByte() || IsBoolean(); 150 } 151 bool IsShortTypes() const { 152 return IsShort() || IsByte() || IsBoolean() || IsConstantShort(); 153 } 154 bool IsCharTypes() const { 155 return IsChar() || IsBooleanTypes() || IsConstantChar(); 156 } 157 bool IsIntegralTypes() const { 158 return IsInteger() || IsConstant() || IsByte() || IsShort() || IsChar() || 159 IsBoolean(); 160 } 161 // Give the constant value encoded, but this shouldn't be called in the 162 // general case. 163 bool IsArrayIndexTypes() const { return IsIntegralTypes(); } 164 // Float type may be derived from any constant type 165 bool IsFloatTypes() const { return IsFloat() || IsConstant(); } 166 bool IsLongTypes() const { return IsLongLo() || IsLongConstant(); } 167 bool IsLongHighTypes() const { 168 return (IsLongHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()); 169 } 170 bool IsDoubleTypes() const { return IsDoubleLo() || IsLongConstant(); } 171 bool IsDoubleHighTypes() const { 172 return (IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()); 173 } 174 virtual bool IsLong() const { return false; } 175 bool HasClass() const { 176 bool result = !klass_.IsNull(); 177 DCHECK_EQ(result, HasClassVirtual()); 178 return result; 179 } 180 virtual bool HasClassVirtual() const { return false; } 181 bool IsJavaLangObject() const REQUIRES_SHARED(Locks::mutator_lock_); 182 virtual bool IsArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_); 183 virtual bool IsObjectArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_); 184 Primitive::Type GetPrimitiveType() const; 185 bool IsJavaLangObjectArray() const 186 REQUIRES_SHARED(Locks::mutator_lock_); 187 bool IsInstantiableTypes() const REQUIRES_SHARED(Locks::mutator_lock_); 188 const std::string_view& GetDescriptor() const { 189 DCHECK(HasClass() || 190 (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && 191 !IsUnresolvedSuperClass())); 192 return descriptor_; 193 } 194 ObjPtr<mirror::Class> GetClass() const REQUIRES_SHARED(Locks::mutator_lock_) { 195 DCHECK(!IsUnresolvedReference()); 196 DCHECK(!klass_.IsNull()) << Dump(); 197 DCHECK(HasClass()); 198 return klass_.Read(); 199 } 200 uint16_t GetId() const { return cache_id_; } 201 const RegType& GetSuperClass(RegTypeCache* cache) const 202 REQUIRES_SHARED(Locks::mutator_lock_); 203 204 virtual std::string Dump() const 205 REQUIRES_SHARED(Locks::mutator_lock_) = 0; 206 207 // Can this type access other? 208 bool CanAccess(const RegType& other) const 209 REQUIRES_SHARED(Locks::mutator_lock_); 210 211 // Can this type access a member with the given properties? 212 bool CanAccessMember(ObjPtr<mirror::Class> klass, uint32_t access_flags) const 213 REQUIRES_SHARED(Locks::mutator_lock_); 214 215 // Can this type be assigned by src? 216 // Note: Object and interface types may always be assigned to one another, see 217 // comment on 218 // ClassJoin. 219 bool IsAssignableFrom(const RegType& src, MethodVerifier* verifier) const 220 REQUIRES_SHARED(Locks::mutator_lock_); 221 222 // Can this array type potentially be assigned by src. 223 // This function is necessary as array types are valid even if their components types are not, 224 // e.g., when they component type could not be resolved. The function will return true iff the 225 // types are assignable. It will return false otherwise. In case of return=false, soft_error 226 // will be set to true iff the assignment test failure should be treated as a soft-error, i.e., 227 // when both array types have the same 'depth' and the 'final' component types may be assignable 228 // (both are reference types). 229 bool CanAssignArray(const RegType& src, 230 RegTypeCache& reg_types, 231 Handle<mirror::ClassLoader> class_loader, 232 MethodVerifier* verifier, 233 bool* soft_error) const 234 REQUIRES_SHARED(Locks::mutator_lock_); 235 236 // Can this type be assigned by src? Variant of IsAssignableFrom that doesn't 237 // allow assignment to 238 // an interface from an Object. 239 bool IsStrictlyAssignableFrom(const RegType& src, MethodVerifier* verifier) const 240 REQUIRES_SHARED(Locks::mutator_lock_); 241 242 // Are these RegTypes the same? 243 bool Equals(const RegType& other) const { return GetId() == other.GetId(); } 244 245 // Compute the merge of this register from one edge (path) with incoming_type 246 // from another. 247 const RegType& Merge(const RegType& incoming_type, 248 RegTypeCache* reg_types, 249 MethodVerifier* verifier) const 250 REQUIRES_SHARED(Locks::mutator_lock_); 251 // Same as above, but also handles the case where incoming_type == this. 252 const RegType& SafeMerge(const RegType& incoming_type, 253 RegTypeCache* reg_types, 254 MethodVerifier* verifier) const 255 REQUIRES_SHARED(Locks::mutator_lock_) { 256 if (Equals(incoming_type)) { 257 return *this; 258 } 259 return Merge(incoming_type, reg_types, verifier); 260 } 261 262 virtual ~RegType() {} 263 264 void VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const 265 REQUIRES_SHARED(Locks::mutator_lock_); 266 267 static void* operator new(size_t size) noexcept { 268 return ::operator new(size); 269 } 270 271 static void* operator new(size_t size, ArenaAllocator* allocator) = delete; 272 static void* operator new(size_t size, ScopedArenaAllocator* allocator); 273 274 enum class AssignmentType { 275 kBoolean, 276 kByte, 277 kShort, 278 kChar, 279 kInteger, 280 kFloat, 281 kLongLo, 282 kDoubleLo, 283 kConflict, 284 kReference, 285 kNotAssignable, 286 }; 287 288 ALWAYS_INLINE 289 inline AssignmentType GetAssignmentType() const { 290 AssignmentType t = GetAssignmentTypeImpl(); 291 if (kIsDebugBuild) { 292 if (IsBoolean()) { 293 CHECK(AssignmentType::kBoolean == t); 294 } else if (IsByte()) { 295 CHECK(AssignmentType::kByte == t); 296 } else if (IsShort()) { 297 CHECK(AssignmentType::kShort == t); 298 } else if (IsChar()) { 299 CHECK(AssignmentType::kChar == t); 300 } else if (IsInteger()) { 301 CHECK(AssignmentType::kInteger == t); 302 } else if (IsFloat()) { 303 CHECK(AssignmentType::kFloat == t); 304 } else if (IsLongLo()) { 305 CHECK(AssignmentType::kLongLo == t); 306 } else if (IsDoubleLo()) { 307 CHECK(AssignmentType::kDoubleLo == t); 308 } else if (IsConflict()) { 309 CHECK(AssignmentType::kConflict == t); 310 } else if (IsReferenceTypes()) { 311 CHECK(AssignmentType::kReference == t); 312 } else { 313 LOG(FATAL) << "Unreachable"; 314 UNREACHABLE(); 315 } 316 } 317 return t; 318 } 319 320 protected: 321 RegType(ObjPtr<mirror::Class> klass, 322 const std::string_view& descriptor, 323 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 324 : descriptor_(descriptor), 325 klass_(klass), 326 cache_id_(cache_id) {} 327 328 template <typename Class> 329 void CheckConstructorInvariants(Class* this_ ATTRIBUTE_UNUSED) const 330 REQUIRES_SHARED(Locks::mutator_lock_) { 331 static_assert(std::is_final<Class>::value, "Class must be final."); 332 if (kIsDebugBuild) { 333 CheckInvariants(); 334 } 335 } 336 337 virtual AssignmentType GetAssignmentTypeImpl() const = 0; 338 339 const std::string_view descriptor_; 340 mutable GcRoot<mirror::Class> klass_; // Non-const only due to moving classes. 341 const uint16_t cache_id_; 342 343 friend class RegTypeCache; 344 345 private: 346 virtual void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_); 347 348 /* 349 * A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is 350 * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of 351 * S and T such that there isn't a parent of both S and T that isn't also the parent of J (ie J 352 * is the deepest (lowest upper bound) parent of S and T). 353 * 354 * This operation applies for regular classes and arrays, however, for interface types there 355 * needn't be a partial ordering on the types. We could solve the problem of a lack of a partial 356 * order by introducing sets of types, however, the only operation permissible on an interface is 357 * invoke-interface. In the tradition of Java verifiers [1] we defer the verification of interface 358 * types until an invoke-interface call on the interface typed reference at runtime and allow 359 * the perversion of Object being assignable to an interface type (note, however, that we don't 360 * allow assignment of Object or Interface to any concrete class and are therefore type safe). 361 * 362 * Note: This may return null in case of internal errors, e.g., OOME when a new class would have 363 * to be created but there is no heap space. The exception will stay pending, and it is 364 * the job of the caller to handle it. 365 * 366 * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy 367 */ 368 static ObjPtr<mirror::Class> ClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t) 369 REQUIRES_SHARED(Locks::mutator_lock_); 370 371 static bool AssignableFrom(const RegType& lhs, 372 const RegType& rhs, 373 bool strict, 374 MethodVerifier* verifier) 375 REQUIRES_SHARED(Locks::mutator_lock_); 376 377 DISALLOW_COPY_AND_ASSIGN(RegType); 378 }; 379 380 // Bottom type. 381 class ConflictType final : public RegType { 382 public: 383 bool IsConflict() const override { return true; } 384 385 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 386 387 // Get the singleton Conflict instance. 388 static const ConflictType* GetInstance() PURE; 389 390 // Create the singleton instance. 391 static const ConflictType* CreateInstance(ObjPtr<mirror::Class> klass, 392 const std::string_view& descriptor, 393 uint16_t cache_id) 394 REQUIRES_SHARED(Locks::mutator_lock_); 395 396 // Destroy the singleton instance. 397 static void Destroy(); 398 399 AssignmentType GetAssignmentTypeImpl() const override { 400 return AssignmentType::kConflict; 401 } 402 403 private: 404 ConflictType(ObjPtr<mirror::Class> klass, 405 const std::string_view& descriptor, 406 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 407 : RegType(klass, descriptor, cache_id) { 408 CheckConstructorInvariants(this); 409 } 410 411 static const ConflictType* instance_; 412 }; 413 414 // A variant of the bottom type used to specify an undefined value in the 415 // incoming registers. 416 // Merging with UndefinedType yields ConflictType which is the true bottom. 417 class UndefinedType final : public RegType { 418 public: 419 bool IsUndefined() const override { return true; } 420 421 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 422 423 // Get the singleton Undefined instance. 424 static const UndefinedType* GetInstance() PURE; 425 426 // Create the singleton instance. 427 static const UndefinedType* CreateInstance(ObjPtr<mirror::Class> klass, 428 const std::string_view& descriptor, 429 uint16_t cache_id) 430 REQUIRES_SHARED(Locks::mutator_lock_); 431 432 // Destroy the singleton instance. 433 static void Destroy(); 434 435 AssignmentType GetAssignmentTypeImpl() const override { 436 return AssignmentType::kNotAssignable; 437 } 438 439 private: 440 UndefinedType(ObjPtr<mirror::Class> klass, 441 const std::string_view& descriptor, 442 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 443 : RegType(klass, descriptor, cache_id) { 444 CheckConstructorInvariants(this); 445 } 446 447 static const UndefinedType* instance_; 448 }; 449 450 class PrimitiveType : public RegType { 451 public: 452 PrimitiveType(ObjPtr<mirror::Class> klass, 453 const std::string_view& descriptor, 454 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_); 455 456 bool HasClassVirtual() const override { return true; } 457 }; 458 459 class Cat1Type : public PrimitiveType { 460 public: 461 Cat1Type(ObjPtr<mirror::Class> klass, 462 const std::string_view& descriptor, 463 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_); 464 }; 465 466 class IntegerType final : public Cat1Type { 467 public: 468 bool IsInteger() const override { return true; } 469 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 470 static const IntegerType* CreateInstance(ObjPtr<mirror::Class> klass, 471 const std::string_view& descriptor, 472 uint16_t cache_id) 473 REQUIRES_SHARED(Locks::mutator_lock_); 474 static const IntegerType* GetInstance() PURE; 475 static void Destroy(); 476 477 AssignmentType GetAssignmentTypeImpl() const override { 478 return AssignmentType::kInteger; 479 } 480 481 private: 482 IntegerType(ObjPtr<mirror::Class> klass, 483 const std::string_view& descriptor, 484 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 485 : Cat1Type(klass, descriptor, cache_id) { 486 CheckConstructorInvariants(this); 487 } 488 static const IntegerType* instance_; 489 }; 490 491 class BooleanType final : public Cat1Type { 492 public: 493 bool IsBoolean() const override { return true; } 494 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 495 static const BooleanType* CreateInstance(ObjPtr<mirror::Class> klass, 496 const std::string_view& descriptor, 497 uint16_t cache_id) 498 REQUIRES_SHARED(Locks::mutator_lock_); 499 static const BooleanType* GetInstance() PURE; 500 static void Destroy(); 501 502 AssignmentType GetAssignmentTypeImpl() const override { 503 return AssignmentType::kBoolean; 504 } 505 506 private: 507 BooleanType(ObjPtr<mirror::Class> klass, 508 const std::string_view& descriptor, 509 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 510 : Cat1Type(klass, descriptor, cache_id) { 511 CheckConstructorInvariants(this); 512 } 513 514 static const BooleanType* instance_; 515 }; 516 517 class ByteType final : public Cat1Type { 518 public: 519 bool IsByte() const override { return true; } 520 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 521 static const ByteType* CreateInstance(ObjPtr<mirror::Class> klass, 522 const std::string_view& descriptor, 523 uint16_t cache_id) 524 REQUIRES_SHARED(Locks::mutator_lock_); 525 static const ByteType* GetInstance() PURE; 526 static void Destroy(); 527 528 AssignmentType GetAssignmentTypeImpl() const override { 529 return AssignmentType::kByte; 530 } 531 532 private: 533 ByteType(ObjPtr<mirror::Class> klass, 534 const std::string_view& descriptor, 535 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 536 : Cat1Type(klass, descriptor, cache_id) { 537 CheckConstructorInvariants(this); 538 } 539 static const ByteType* instance_; 540 }; 541 542 class ShortType final : public Cat1Type { 543 public: 544 bool IsShort() const override { return true; } 545 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 546 static const ShortType* CreateInstance(ObjPtr<mirror::Class> klass, 547 const std::string_view& descriptor, 548 uint16_t cache_id) 549 REQUIRES_SHARED(Locks::mutator_lock_); 550 static const ShortType* GetInstance() PURE; 551 static void Destroy(); 552 553 AssignmentType GetAssignmentTypeImpl() const override { 554 return AssignmentType::kShort; 555 } 556 557 private: 558 ShortType(ObjPtr<mirror::Class> klass, const std::string_view& descriptor, 559 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 560 : Cat1Type(klass, descriptor, cache_id) { 561 CheckConstructorInvariants(this); 562 } 563 static const ShortType* instance_; 564 }; 565 566 class CharType final : public Cat1Type { 567 public: 568 bool IsChar() const override { return true; } 569 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 570 static const CharType* CreateInstance(ObjPtr<mirror::Class> klass, 571 const std::string_view& descriptor, 572 uint16_t cache_id) 573 REQUIRES_SHARED(Locks::mutator_lock_); 574 static const CharType* GetInstance() PURE; 575 static void Destroy(); 576 577 AssignmentType GetAssignmentTypeImpl() const override { 578 return AssignmentType::kChar; 579 } 580 581 private: 582 CharType(ObjPtr<mirror::Class> klass, 583 const std::string_view& descriptor, 584 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 585 : Cat1Type(klass, descriptor, cache_id) { 586 CheckConstructorInvariants(this); 587 } 588 static const CharType* instance_; 589 }; 590 591 class FloatType final : public Cat1Type { 592 public: 593 bool IsFloat() const override { return true; } 594 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 595 static const FloatType* CreateInstance(ObjPtr<mirror::Class> klass, 596 const std::string_view& descriptor, 597 uint16_t cache_id) 598 REQUIRES_SHARED(Locks::mutator_lock_); 599 static const FloatType* GetInstance() PURE; 600 static void Destroy(); 601 602 AssignmentType GetAssignmentTypeImpl() const override { 603 return AssignmentType::kFloat; 604 } 605 606 private: 607 FloatType(ObjPtr<mirror::Class> klass, 608 const std::string_view& descriptor, 609 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 610 : Cat1Type(klass, descriptor, cache_id) { 611 CheckConstructorInvariants(this); 612 } 613 static const FloatType* instance_; 614 }; 615 616 class Cat2Type : public PrimitiveType { 617 public: 618 Cat2Type(ObjPtr<mirror::Class> klass, 619 const std::string_view& descriptor, 620 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_); 621 }; 622 623 class LongLoType final : public Cat2Type { 624 public: 625 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 626 bool IsLongLo() const override { return true; } 627 bool IsLong() const override { return true; } 628 static const LongLoType* CreateInstance(ObjPtr<mirror::Class> klass, 629 const std::string_view& descriptor, 630 uint16_t cache_id) 631 REQUIRES_SHARED(Locks::mutator_lock_); 632 static const LongLoType* GetInstance() PURE; 633 static void Destroy(); 634 635 AssignmentType GetAssignmentTypeImpl() const override { 636 return AssignmentType::kLongLo; 637 } 638 639 private: 640 LongLoType(ObjPtr<mirror::Class> klass, 641 const std::string_view& descriptor, 642 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 643 : Cat2Type(klass, descriptor, cache_id) { 644 CheckConstructorInvariants(this); 645 } 646 static const LongLoType* instance_; 647 }; 648 649 class LongHiType final : public Cat2Type { 650 public: 651 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 652 bool IsLongHi() const override { return true; } 653 static const LongHiType* CreateInstance(ObjPtr<mirror::Class> klass, 654 const std::string_view& descriptor, 655 uint16_t cache_id) 656 REQUIRES_SHARED(Locks::mutator_lock_); 657 static const LongHiType* GetInstance() PURE; 658 static void Destroy(); 659 660 AssignmentType GetAssignmentTypeImpl() const override { 661 return AssignmentType::kNotAssignable; 662 } 663 664 private: 665 LongHiType(ObjPtr<mirror::Class> klass, 666 const std::string_view& descriptor, 667 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 668 : Cat2Type(klass, descriptor, cache_id) { 669 CheckConstructorInvariants(this); 670 } 671 static const LongHiType* instance_; 672 }; 673 674 class DoubleLoType final : public Cat2Type { 675 public: 676 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 677 bool IsDoubleLo() const override { return true; } 678 bool IsDouble() const override { return true; } 679 static const DoubleLoType* CreateInstance(ObjPtr<mirror::Class> klass, 680 const std::string_view& descriptor, 681 uint16_t cache_id) 682 REQUIRES_SHARED(Locks::mutator_lock_); 683 static const DoubleLoType* GetInstance() PURE; 684 static void Destroy(); 685 686 AssignmentType GetAssignmentTypeImpl() const override { 687 return AssignmentType::kDoubleLo; 688 } 689 690 private: 691 DoubleLoType(ObjPtr<mirror::Class> klass, 692 const std::string_view& descriptor, 693 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 694 : Cat2Type(klass, descriptor, cache_id) { 695 CheckConstructorInvariants(this); 696 } 697 static const DoubleLoType* instance_; 698 }; 699 700 class DoubleHiType final : public Cat2Type { 701 public: 702 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 703 bool IsDoubleHi() const override { return true; } 704 static const DoubleHiType* CreateInstance(ObjPtr<mirror::Class> klass, 705 const std::string_view& descriptor, 706 uint16_t cache_id) 707 REQUIRES_SHARED(Locks::mutator_lock_); 708 static const DoubleHiType* GetInstance() PURE; 709 static void Destroy(); 710 711 AssignmentType GetAssignmentTypeImpl() const override { 712 return AssignmentType::kNotAssignable; 713 } 714 715 private: 716 DoubleHiType(ObjPtr<mirror::Class> klass, 717 const std::string_view& descriptor, 718 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 719 : Cat2Type(klass, descriptor, cache_id) { 720 CheckConstructorInvariants(this); 721 } 722 static const DoubleHiType* instance_; 723 }; 724 725 class ConstantType : public RegType { 726 public: 727 ConstantType(uint32_t constant, uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 728 : RegType(nullptr, "", cache_id), constant_(constant) { 729 } 730 731 732 // If this is a 32-bit constant, what is the value? This value may be 733 // imprecise in which case 734 // the value represents part of the integer range of values that may be held 735 // in the register. 736 int32_t ConstantValue() const { 737 DCHECK(IsConstantTypes()); 738 return constant_; 739 } 740 741 int32_t ConstantValueLo() const { 742 DCHECK(IsConstantLo()); 743 return constant_; 744 } 745 746 int32_t ConstantValueHi() const { 747 if (IsConstantHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()) { 748 return constant_; 749 } else { 750 DCHECK(false); 751 return 0; 752 } 753 } 754 755 bool IsZero() const override { 756 return IsPreciseConstant() && ConstantValue() == 0; 757 } 758 bool IsOne() const override { 759 return IsPreciseConstant() && ConstantValue() == 1; 760 } 761 762 bool IsConstantChar() const override { 763 return IsConstant() && ConstantValue() >= 0 && 764 ConstantValue() <= std::numeric_limits<uint16_t>::max(); 765 } 766 bool IsConstantByte() const override { 767 return IsConstant() && 768 ConstantValue() >= std::numeric_limits<int8_t>::min() && 769 ConstantValue() <= std::numeric_limits<int8_t>::max(); 770 } 771 bool IsConstantShort() const override { 772 return IsConstant() && 773 ConstantValue() >= std::numeric_limits<int16_t>::min() && 774 ConstantValue() <= std::numeric_limits<int16_t>::max(); 775 } 776 bool IsConstantTypes() const override { return true; } 777 778 AssignmentType GetAssignmentTypeImpl() const override { 779 return AssignmentType::kNotAssignable; 780 } 781 782 private: 783 const uint32_t constant_; 784 }; 785 786 class PreciseConstType final : public ConstantType { 787 public: 788 PreciseConstType(uint32_t constant, uint16_t cache_id) 789 REQUIRES_SHARED(Locks::mutator_lock_) 790 : ConstantType(constant, cache_id) { 791 CheckConstructorInvariants(this); 792 } 793 794 bool IsPreciseConstant() const override { return true; } 795 796 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 797 798 AssignmentType GetAssignmentTypeImpl() const override { 799 return AssignmentType::kNotAssignable; 800 } 801 }; 802 803 class PreciseConstLoType final : public ConstantType { 804 public: 805 PreciseConstLoType(uint32_t constant, uint16_t cache_id) 806 REQUIRES_SHARED(Locks::mutator_lock_) 807 : ConstantType(constant, cache_id) { 808 CheckConstructorInvariants(this); 809 } 810 bool IsPreciseConstantLo() const override { return true; } 811 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 812 813 AssignmentType GetAssignmentTypeImpl() const override { 814 return AssignmentType::kNotAssignable; 815 } 816 }; 817 818 class PreciseConstHiType final : public ConstantType { 819 public: 820 PreciseConstHiType(uint32_t constant, uint16_t cache_id) 821 REQUIRES_SHARED(Locks::mutator_lock_) 822 : ConstantType(constant, cache_id) { 823 CheckConstructorInvariants(this); 824 } 825 bool IsPreciseConstantHi() const override { return true; } 826 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 827 828 AssignmentType GetAssignmentTypeImpl() const override { 829 return AssignmentType::kNotAssignable; 830 } 831 }; 832 833 class ImpreciseConstType final : public ConstantType { 834 public: 835 ImpreciseConstType(uint32_t constat, uint16_t cache_id) 836 REQUIRES_SHARED(Locks::mutator_lock_) 837 : ConstantType(constat, cache_id) { 838 CheckConstructorInvariants(this); 839 } 840 bool IsImpreciseConstant() const override { return true; } 841 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 842 843 AssignmentType GetAssignmentTypeImpl() const override { 844 return AssignmentType::kNotAssignable; 845 } 846 }; 847 848 class ImpreciseConstLoType final : public ConstantType { 849 public: 850 ImpreciseConstLoType(uint32_t constant, uint16_t cache_id) 851 REQUIRES_SHARED(Locks::mutator_lock_) 852 : ConstantType(constant, cache_id) { 853 CheckConstructorInvariants(this); 854 } 855 bool IsImpreciseConstantLo() const override { return true; } 856 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 857 858 AssignmentType GetAssignmentTypeImpl() const override { 859 return AssignmentType::kNotAssignable; 860 } 861 }; 862 863 class ImpreciseConstHiType final : public ConstantType { 864 public: 865 ImpreciseConstHiType(uint32_t constant, uint16_t cache_id) 866 REQUIRES_SHARED(Locks::mutator_lock_) 867 : ConstantType(constant, cache_id) { 868 CheckConstructorInvariants(this); 869 } 870 bool IsImpreciseConstantHi() const override { return true; } 871 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 872 873 AssignmentType GetAssignmentTypeImpl() const override { 874 return AssignmentType::kNotAssignable; 875 } 876 }; 877 878 // Special "null" type that captures the semantics of null / bottom. 879 class NullType final : public RegType { 880 public: 881 bool IsNull() const override { 882 return true; 883 } 884 885 // Get the singleton Null instance. 886 static const NullType* GetInstance() PURE; 887 888 // Create the singleton instance. 889 static const NullType* CreateInstance(ObjPtr<mirror::Class> klass, 890 const std::string_view& descriptor, 891 uint16_t cache_id) 892 REQUIRES_SHARED(Locks::mutator_lock_); 893 894 static void Destroy(); 895 896 std::string Dump() const override { 897 return "null"; 898 } 899 900 AssignmentType GetAssignmentTypeImpl() const override { 901 return AssignmentType::kReference; 902 } 903 904 bool IsConstantTypes() const override { 905 return true; 906 } 907 908 private: 909 NullType(ObjPtr<mirror::Class> klass, const std::string_view& descriptor, uint16_t cache_id) 910 REQUIRES_SHARED(Locks::mutator_lock_) 911 : RegType(klass, descriptor, cache_id) { 912 CheckConstructorInvariants(this); 913 } 914 915 static const NullType* instance_; 916 }; 917 918 // Common parent of all uninitialized types. Uninitialized types are created by 919 // "new" dex 920 // instructions and must be passed to a constructor. 921 class UninitializedType : public RegType { 922 public: 923 UninitializedType(ObjPtr<mirror::Class> klass, 924 const std::string_view& descriptor, 925 uint32_t allocation_pc, 926 uint16_t cache_id) 927 : RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {} 928 929 bool IsUninitializedTypes() const override; 930 bool IsNonZeroReferenceTypes() const override; 931 932 uint32_t GetAllocationPc() const { 933 DCHECK(IsUninitializedTypes()); 934 return allocation_pc_; 935 } 936 937 AssignmentType GetAssignmentTypeImpl() const override { 938 return AssignmentType::kReference; 939 } 940 941 private: 942 const uint32_t allocation_pc_; 943 }; 944 945 // Similar to ReferenceType but not yet having been passed to a constructor. 946 class UninitializedReferenceType final : public UninitializedType { 947 public: 948 UninitializedReferenceType(ObjPtr<mirror::Class> klass, 949 const std::string_view& descriptor, 950 uint32_t allocation_pc, 951 uint16_t cache_id) 952 REQUIRES_SHARED(Locks::mutator_lock_) 953 : UninitializedType(klass, descriptor, allocation_pc, cache_id) { 954 CheckConstructorInvariants(this); 955 } 956 957 bool IsUninitializedReference() const override { return true; } 958 959 bool HasClassVirtual() const override { return true; } 960 961 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 962 }; 963 964 // Similar to UnresolvedReferenceType but not yet having been passed to a 965 // constructor. 966 class UnresolvedUninitializedRefType final : public UninitializedType { 967 public: 968 UnresolvedUninitializedRefType(const std::string_view& descriptor, 969 uint32_t allocation_pc, 970 uint16_t cache_id) 971 REQUIRES_SHARED(Locks::mutator_lock_) 972 : UninitializedType(nullptr, descriptor, allocation_pc, cache_id) { 973 CheckConstructorInvariants(this); 974 } 975 976 bool IsUnresolvedAndUninitializedReference() const override { return true; } 977 978 bool IsUnresolvedTypes() const override { return true; } 979 980 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 981 982 private: 983 void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override; 984 }; 985 986 // Similar to UninitializedReferenceType but special case for the this argument 987 // of a constructor. 988 class UninitializedThisReferenceType final : public UninitializedType { 989 public: 990 UninitializedThisReferenceType(ObjPtr<mirror::Class> klass, 991 const std::string_view& descriptor, 992 uint16_t cache_id) 993 REQUIRES_SHARED(Locks::mutator_lock_) 994 : UninitializedType(klass, descriptor, 0, cache_id) { 995 CheckConstructorInvariants(this); 996 } 997 998 bool IsUninitializedThisReference() const override { return true; } 999 1000 bool HasClassVirtual() const override { return true; } 1001 1002 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1003 1004 private: 1005 void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override; 1006 }; 1007 1008 class UnresolvedUninitializedThisRefType final : public UninitializedType { 1009 public: 1010 UnresolvedUninitializedThisRefType(const std::string_view& descriptor, uint16_t cache_id) 1011 REQUIRES_SHARED(Locks::mutator_lock_) 1012 : UninitializedType(nullptr, descriptor, 0, cache_id) { 1013 CheckConstructorInvariants(this); 1014 } 1015 1016 bool IsUnresolvedAndUninitializedThisReference() const override { return true; } 1017 1018 bool IsUnresolvedTypes() const override { return true; } 1019 1020 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1021 1022 private: 1023 void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override; 1024 }; 1025 1026 // A type of register holding a reference to an Object of type GetClass or a 1027 // sub-class. 1028 class ReferenceType final : public RegType { 1029 public: 1030 ReferenceType(ObjPtr<mirror::Class> klass, 1031 const std::string_view& descriptor, 1032 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 1033 : RegType(klass, descriptor, cache_id) { 1034 CheckConstructorInvariants(this); 1035 } 1036 1037 bool IsReference() const override { return true; } 1038 1039 bool IsNonZeroReferenceTypes() const override { return true; } 1040 1041 bool HasClassVirtual() const override { return true; } 1042 1043 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1044 1045 AssignmentType GetAssignmentTypeImpl() const override { 1046 return AssignmentType::kReference; 1047 } 1048 }; 1049 1050 // A type of register holding a reference to an Object of type GetClass and only 1051 // an object of that 1052 // type. 1053 class PreciseReferenceType final : public RegType { 1054 public: 1055 PreciseReferenceType(ObjPtr<mirror::Class> klass, 1056 const std::string_view& descriptor, 1057 uint16_t cache_id) 1058 REQUIRES_SHARED(Locks::mutator_lock_); 1059 1060 bool IsPreciseReference() const override { return true; } 1061 1062 bool IsNonZeroReferenceTypes() const override { return true; } 1063 1064 bool HasClassVirtual() const override { return true; } 1065 1066 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1067 1068 AssignmentType GetAssignmentTypeImpl() const override { 1069 return AssignmentType::kReference; 1070 } 1071 }; 1072 1073 // Common parent of unresolved types. 1074 class UnresolvedType : public RegType { 1075 public: 1076 UnresolvedType(const std::string_view& descriptor, uint16_t cache_id) 1077 REQUIRES_SHARED(Locks::mutator_lock_) 1078 : RegType(nullptr, descriptor, cache_id) {} 1079 1080 bool IsNonZeroReferenceTypes() const override; 1081 1082 AssignmentType GetAssignmentTypeImpl() const override { 1083 return AssignmentType::kReference; 1084 } 1085 }; 1086 1087 // Similar to ReferenceType except the Class couldn't be loaded. Assignability 1088 // and other tests made 1089 // of this type must be conservative. 1090 class UnresolvedReferenceType final : public UnresolvedType { 1091 public: 1092 UnresolvedReferenceType(const std::string_view& descriptor, uint16_t cache_id) 1093 REQUIRES_SHARED(Locks::mutator_lock_) 1094 : UnresolvedType(descriptor, cache_id) { 1095 CheckConstructorInvariants(this); 1096 } 1097 1098 bool IsUnresolvedReference() const override { return true; } 1099 1100 bool IsUnresolvedTypes() const override { return true; } 1101 1102 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1103 1104 private: 1105 void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override; 1106 }; 1107 1108 // Type representing the super-class of an unresolved type. 1109 class UnresolvedSuperClass final : public UnresolvedType { 1110 public: 1111 UnresolvedSuperClass(uint16_t child_id, RegTypeCache* reg_type_cache, 1112 uint16_t cache_id) 1113 REQUIRES_SHARED(Locks::mutator_lock_) 1114 : UnresolvedType("", cache_id), 1115 unresolved_child_id_(child_id), 1116 reg_type_cache_(reg_type_cache) { 1117 CheckConstructorInvariants(this); 1118 } 1119 1120 bool IsUnresolvedSuperClass() const override { return true; } 1121 1122 bool IsUnresolvedTypes() const override { return true; } 1123 1124 uint16_t GetUnresolvedSuperClassChildId() const { 1125 DCHECK(IsUnresolvedSuperClass()); 1126 return static_cast<uint16_t>(unresolved_child_id_ & 0xFFFF); 1127 } 1128 1129 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1130 1131 private: 1132 void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override; 1133 1134 const uint16_t unresolved_child_id_; 1135 const RegTypeCache* const reg_type_cache_; 1136 }; 1137 1138 // A merge of unresolved (and resolved) types. If the types were resolved this may be 1139 // Conflict or another known ReferenceType. 1140 class UnresolvedMergedType final : public UnresolvedType { 1141 public: 1142 // Note: the constructor will copy the unresolved BitVector, not use it directly. 1143 UnresolvedMergedType(const RegType& resolved, 1144 const BitVector& unresolved, 1145 const RegTypeCache* reg_type_cache, 1146 uint16_t cache_id) 1147 REQUIRES_SHARED(Locks::mutator_lock_); 1148 1149 // The resolved part. See description below. 1150 const RegType& GetResolvedPart() const { 1151 return resolved_part_; 1152 } 1153 // The unresolved part. 1154 const BitVector& GetUnresolvedTypes() const { 1155 return unresolved_types_; 1156 } 1157 1158 bool IsUnresolvedMergedReference() const override { return true; } 1159 1160 bool IsUnresolvedTypes() const override { return true; } 1161 1162 bool IsArrayTypes() const override REQUIRES_SHARED(Locks::mutator_lock_); 1163 bool IsObjectArrayTypes() const override REQUIRES_SHARED(Locks::mutator_lock_); 1164 1165 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1166 1167 private: 1168 void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override; 1169 1170 const RegTypeCache* const reg_type_cache_; 1171 1172 // The original implementation of merged types was a binary tree. Collection of the flattened 1173 // types ("leaves") can be expensive, so we store the expanded list now, as two components: 1174 // 1) A resolved component. We use Zero when there is no resolved component, as that will be 1175 // an identity merge. 1176 // 2) A bitvector of the unresolved reference types. A bitvector was chosen with the assumption 1177 // that there should not be too many types in flight in practice. (We also bias the index 1178 // against the index of Zero, which is one of the later default entries in any cache.) 1179 const RegType& resolved_part_; 1180 const BitVector unresolved_types_; 1181 }; 1182 1183 std::ostream& operator<<(std::ostream& os, const RegType& rhs) 1184 REQUIRES_SHARED(Locks::mutator_lock_); 1185 1186 } // namespace verifier 1187 } // namespace art 1188 1189 #endif // ART_RUNTIME_VERIFIER_REG_TYPE_H_ 1190