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: IsUndefined()54 virtual bool IsUndefined() const { return false; } IsConflict()55 virtual bool IsConflict() const { return false; } IsBoolean()56 virtual bool IsBoolean() const { return false; } IsByte()57 virtual bool IsByte() const { return false; } IsChar()58 virtual bool IsChar() const { return false; } IsShort()59 virtual bool IsShort() const { return false; } IsInteger()60 virtual bool IsInteger() const { return false; } IsLongLo()61 virtual bool IsLongLo() const { return false; } IsLongHi()62 virtual bool IsLongHi() const { return false; } IsFloat()63 virtual bool IsFloat() const { return false; } IsDouble()64 virtual bool IsDouble() const { return false; } IsDoubleLo()65 virtual bool IsDoubleLo() const { return false; } IsDoubleHi()66 virtual bool IsDoubleHi() const { return false; } IsUnresolvedReference()67 virtual bool IsUnresolvedReference() const { return false; } IsUninitializedReference()68 virtual bool IsUninitializedReference() const { return false; } IsUninitializedThisReference()69 virtual bool IsUninitializedThisReference() const { return false; } IsUnresolvedAndUninitializedReference()70 virtual bool IsUnresolvedAndUninitializedReference() const { return false; } IsUnresolvedAndUninitializedThisReference()71 virtual bool IsUnresolvedAndUninitializedThisReference() const { 72 return false; 73 } IsUnresolvedMergedReference()74 virtual bool IsUnresolvedMergedReference() const { return false; } IsUnresolvedSuperClass()75 virtual bool IsUnresolvedSuperClass() const { return false; } IsReference()76 virtual bool IsReference() const { return false; } IsPreciseReference()77 virtual bool IsPreciseReference() const { return false; } IsPreciseConstant()78 virtual bool IsPreciseConstant() const { return false; } IsPreciseConstantLo()79 virtual bool IsPreciseConstantLo() const { return false; } IsPreciseConstantHi()80 virtual bool IsPreciseConstantHi() const { return false; } IsImpreciseConstantLo()81 virtual bool IsImpreciseConstantLo() const { return false; } IsImpreciseConstantHi()82 virtual bool IsImpreciseConstantHi() const { return false; } IsImpreciseConstant()83 virtual bool IsImpreciseConstant() const { return false; } IsConstantTypes()84 virtual bool IsConstantTypes() const { return false; } IsConstant()85 bool IsConstant() const { 86 return IsImpreciseConstant() || IsPreciseConstant(); 87 } IsConstantLo()88 bool IsConstantLo() const { 89 return IsImpreciseConstantLo() || IsPreciseConstantLo(); 90 } IsPrecise()91 bool IsPrecise() const { 92 return IsPreciseConstantLo() || IsPreciseConstant() || 93 IsPreciseConstantHi(); 94 } IsLongConstant()95 bool IsLongConstant() const { return IsConstantLo(); } IsConstantHi()96 bool IsConstantHi() const { 97 return (IsPreciseConstantHi() || IsImpreciseConstantHi()); 98 } IsLongConstantHigh()99 bool IsLongConstantHigh() const { return IsConstantHi(); } IsUninitializedTypes()100 virtual bool IsUninitializedTypes() const { return false; } IsUnresolvedTypes()101 virtual bool IsUnresolvedTypes() const { return false; } 102 IsLowHalf()103 bool IsLowHalf() const { 104 return (IsLongLo() || IsDoubleLo() || IsPreciseConstantLo() || IsImpreciseConstantLo()); 105 } IsHighHalf()106 bool IsHighHalf() const { 107 return (IsLongHi() || IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()); 108 } IsLongOrDoubleTypes()109 bool IsLongOrDoubleTypes() const { return IsLowHalf(); } 110 // Check this is the low half, and that type_h is its matching high-half. CheckWidePair(const RegType & type_h)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; IsConstantChar()127 virtual bool IsConstantChar() const { return false; } IsConstantByte()128 virtual bool IsConstantByte() const { return false; } IsConstantShort()129 virtual bool IsConstantShort() const { return false; } IsOne()130 virtual bool IsOne() const { return false; } IsZero()131 virtual bool IsZero() const { return false; } IsNull()132 virtual bool IsNull() const { return false; } IsReferenceTypes()133 bool IsReferenceTypes() const { 134 return IsNonZeroReferenceTypes() || IsZero() || IsNull(); 135 } IsZeroOrNull()136 bool IsZeroOrNull() const { 137 return IsZero() || IsNull(); 138 } IsNonZeroReferenceTypes()139 virtual bool IsNonZeroReferenceTypes() const { return false; } IsCategory1Types()140 bool IsCategory1Types() const { 141 return IsChar() || IsInteger() || IsFloat() || IsConstant() || IsByte() || 142 IsShort() || IsBoolean(); 143 } IsCategory2Types()144 bool IsCategory2Types() const { 145 return IsLowHalf(); // Don't expect explicit testing of high halves 146 } IsBooleanTypes()147 bool IsBooleanTypes() const { return IsBoolean() || IsConstantBoolean(); } IsByteTypes()148 bool IsByteTypes() const { 149 return IsConstantByte() || IsByte() || IsBoolean(); 150 } IsShortTypes()151 bool IsShortTypes() const { 152 return IsShort() || IsByte() || IsBoolean() || IsConstantShort(); 153 } IsCharTypes()154 bool IsCharTypes() const { 155 return IsChar() || IsBooleanTypes() || IsConstantChar(); 156 } IsIntegralTypes()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. IsArrayIndexTypes()163 bool IsArrayIndexTypes() const { return IsIntegralTypes(); } 164 // Float type may be derived from any constant type IsFloatTypes()165 bool IsFloatTypes() const { return IsFloat() || IsConstant(); } IsLongTypes()166 bool IsLongTypes() const { return IsLongLo() || IsLongConstant(); } IsLongHighTypes()167 bool IsLongHighTypes() const { 168 return (IsLongHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()); 169 } IsDoubleTypes()170 bool IsDoubleTypes() const { return IsDoubleLo() || IsLongConstant(); } IsDoubleHighTypes()171 bool IsDoubleHighTypes() const { 172 return (IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()); 173 } IsLong()174 virtual bool IsLong() const { return false; } HasClass()175 bool HasClass() const { 176 bool result = !klass_.IsNull(); 177 DCHECK_EQ(result, HasClassVirtual()); 178 return result; 179 } HasClassVirtual()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_); GetDescriptor()188 const std::string_view& GetDescriptor() const { 189 DCHECK(HasClass() || 190 (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && 191 !IsUnresolvedSuperClass())); 192 return descriptor_; 193 } GetClass()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 } GetId()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? Equals(const RegType & other)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. SafeMerge(const RegType & incoming_type,RegTypeCache * reg_types,MethodVerifier * verifier)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 ~RegType()262 virtual ~RegType() {} 263 264 void VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const 265 REQUIRES_SHARED(Locks::mutator_lock_); 266 new(size_t size)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 GetAssignmentType()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: RegType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)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> CheckConstructorInvariants(Class * this_ ATTRIBUTE_UNUSED)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 static bool AssignableFrom(const RegType& lhs, 350 const RegType& rhs, 351 bool strict, 352 MethodVerifier* verifier) 353 REQUIRES_SHARED(Locks::mutator_lock_); 354 355 DISALLOW_COPY_AND_ASSIGN(RegType); 356 }; 357 358 // Bottom type. 359 class ConflictType final : public RegType { 360 public: IsConflict()361 bool IsConflict() const override { return true; } 362 363 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 364 365 // Get the singleton Conflict instance. 366 static const ConflictType* GetInstance() PURE; 367 368 // Create the singleton instance. 369 static const ConflictType* CreateInstance(ObjPtr<mirror::Class> klass, 370 const std::string_view& descriptor, 371 uint16_t cache_id) 372 REQUIRES_SHARED(Locks::mutator_lock_); 373 374 // Destroy the singleton instance. 375 static void Destroy(); 376 GetAssignmentTypeImpl()377 AssignmentType GetAssignmentTypeImpl() const override { 378 return AssignmentType::kConflict; 379 } 380 381 private: ConflictType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)382 ConflictType(ObjPtr<mirror::Class> klass, 383 const std::string_view& descriptor, 384 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 385 : RegType(klass, descriptor, cache_id) { 386 CheckConstructorInvariants(this); 387 } 388 389 static const ConflictType* instance_; 390 }; 391 392 // A variant of the bottom type used to specify an undefined value in the 393 // incoming registers. 394 // Merging with UndefinedType yields ConflictType which is the true bottom. 395 class UndefinedType final : public RegType { 396 public: IsUndefined()397 bool IsUndefined() const override { return true; } 398 399 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 400 401 // Get the singleton Undefined instance. 402 static const UndefinedType* GetInstance() PURE; 403 404 // Create the singleton instance. 405 static const UndefinedType* CreateInstance(ObjPtr<mirror::Class> klass, 406 const std::string_view& descriptor, 407 uint16_t cache_id) 408 REQUIRES_SHARED(Locks::mutator_lock_); 409 410 // Destroy the singleton instance. 411 static void Destroy(); 412 GetAssignmentTypeImpl()413 AssignmentType GetAssignmentTypeImpl() const override { 414 return AssignmentType::kNotAssignable; 415 } 416 417 private: UndefinedType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)418 UndefinedType(ObjPtr<mirror::Class> klass, 419 const std::string_view& descriptor, 420 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 421 : RegType(klass, descriptor, cache_id) { 422 CheckConstructorInvariants(this); 423 } 424 425 static const UndefinedType* instance_; 426 }; 427 428 class PrimitiveType : public RegType { 429 public: 430 PrimitiveType(ObjPtr<mirror::Class> klass, 431 const std::string_view& descriptor, 432 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_); 433 HasClassVirtual()434 bool HasClassVirtual() const override { return true; } 435 }; 436 437 class Cat1Type : public PrimitiveType { 438 public: 439 Cat1Type(ObjPtr<mirror::Class> klass, 440 const std::string_view& descriptor, 441 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_); 442 }; 443 444 class IntegerType final : public Cat1Type { 445 public: IsInteger()446 bool IsInteger() const override { return true; } 447 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 448 static const IntegerType* CreateInstance(ObjPtr<mirror::Class> klass, 449 const std::string_view& descriptor, 450 uint16_t cache_id) 451 REQUIRES_SHARED(Locks::mutator_lock_); 452 static const IntegerType* GetInstance() PURE; 453 static void Destroy(); 454 GetAssignmentTypeImpl()455 AssignmentType GetAssignmentTypeImpl() const override { 456 return AssignmentType::kInteger; 457 } 458 459 private: IntegerType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)460 IntegerType(ObjPtr<mirror::Class> klass, 461 const std::string_view& descriptor, 462 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 463 : Cat1Type(klass, descriptor, cache_id) { 464 CheckConstructorInvariants(this); 465 } 466 static const IntegerType* instance_; 467 }; 468 469 class BooleanType final : public Cat1Type { 470 public: IsBoolean()471 bool IsBoolean() const override { return true; } 472 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 473 static const BooleanType* CreateInstance(ObjPtr<mirror::Class> klass, 474 const std::string_view& descriptor, 475 uint16_t cache_id) 476 REQUIRES_SHARED(Locks::mutator_lock_); 477 static const BooleanType* GetInstance() PURE; 478 static void Destroy(); 479 GetAssignmentTypeImpl()480 AssignmentType GetAssignmentTypeImpl() const override { 481 return AssignmentType::kBoolean; 482 } 483 484 private: BooleanType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)485 BooleanType(ObjPtr<mirror::Class> klass, 486 const std::string_view& descriptor, 487 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 488 : Cat1Type(klass, descriptor, cache_id) { 489 CheckConstructorInvariants(this); 490 } 491 492 static const BooleanType* instance_; 493 }; 494 495 class ByteType final : public Cat1Type { 496 public: IsByte()497 bool IsByte() const override { return true; } 498 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 499 static const ByteType* CreateInstance(ObjPtr<mirror::Class> klass, 500 const std::string_view& descriptor, 501 uint16_t cache_id) 502 REQUIRES_SHARED(Locks::mutator_lock_); 503 static const ByteType* GetInstance() PURE; 504 static void Destroy(); 505 GetAssignmentTypeImpl()506 AssignmentType GetAssignmentTypeImpl() const override { 507 return AssignmentType::kByte; 508 } 509 510 private: ByteType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)511 ByteType(ObjPtr<mirror::Class> klass, 512 const std::string_view& descriptor, 513 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 514 : Cat1Type(klass, descriptor, cache_id) { 515 CheckConstructorInvariants(this); 516 } 517 static const ByteType* instance_; 518 }; 519 520 class ShortType final : public Cat1Type { 521 public: IsShort()522 bool IsShort() const override { return true; } 523 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 524 static const ShortType* CreateInstance(ObjPtr<mirror::Class> klass, 525 const std::string_view& descriptor, 526 uint16_t cache_id) 527 REQUIRES_SHARED(Locks::mutator_lock_); 528 static const ShortType* GetInstance() PURE; 529 static void Destroy(); 530 GetAssignmentTypeImpl()531 AssignmentType GetAssignmentTypeImpl() const override { 532 return AssignmentType::kShort; 533 } 534 535 private: ShortType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)536 ShortType(ObjPtr<mirror::Class> klass, const std::string_view& descriptor, 537 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 538 : Cat1Type(klass, descriptor, cache_id) { 539 CheckConstructorInvariants(this); 540 } 541 static const ShortType* instance_; 542 }; 543 544 class CharType final : public Cat1Type { 545 public: IsChar()546 bool IsChar() const override { return true; } 547 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 548 static const CharType* CreateInstance(ObjPtr<mirror::Class> klass, 549 const std::string_view& descriptor, 550 uint16_t cache_id) 551 REQUIRES_SHARED(Locks::mutator_lock_); 552 static const CharType* GetInstance() PURE; 553 static void Destroy(); 554 GetAssignmentTypeImpl()555 AssignmentType GetAssignmentTypeImpl() const override { 556 return AssignmentType::kChar; 557 } 558 559 private: CharType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)560 CharType(ObjPtr<mirror::Class> klass, 561 const std::string_view& descriptor, 562 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 563 : Cat1Type(klass, descriptor, cache_id) { 564 CheckConstructorInvariants(this); 565 } 566 static const CharType* instance_; 567 }; 568 569 class FloatType final : public Cat1Type { 570 public: IsFloat()571 bool IsFloat() const override { return true; } 572 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 573 static const FloatType* CreateInstance(ObjPtr<mirror::Class> klass, 574 const std::string_view& descriptor, 575 uint16_t cache_id) 576 REQUIRES_SHARED(Locks::mutator_lock_); 577 static const FloatType* GetInstance() PURE; 578 static void Destroy(); 579 GetAssignmentTypeImpl()580 AssignmentType GetAssignmentTypeImpl() const override { 581 return AssignmentType::kFloat; 582 } 583 584 private: FloatType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)585 FloatType(ObjPtr<mirror::Class> klass, 586 const std::string_view& descriptor, 587 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 588 : Cat1Type(klass, descriptor, cache_id) { 589 CheckConstructorInvariants(this); 590 } 591 static const FloatType* instance_; 592 }; 593 594 class Cat2Type : public PrimitiveType { 595 public: 596 Cat2Type(ObjPtr<mirror::Class> klass, 597 const std::string_view& descriptor, 598 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_); 599 }; 600 601 class LongLoType final : public Cat2Type { 602 public: 603 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); IsLongLo()604 bool IsLongLo() const override { return true; } IsLong()605 bool IsLong() const override { return true; } 606 static const LongLoType* CreateInstance(ObjPtr<mirror::Class> klass, 607 const std::string_view& descriptor, 608 uint16_t cache_id) 609 REQUIRES_SHARED(Locks::mutator_lock_); 610 static const LongLoType* GetInstance() PURE; 611 static void Destroy(); 612 GetAssignmentTypeImpl()613 AssignmentType GetAssignmentTypeImpl() const override { 614 return AssignmentType::kLongLo; 615 } 616 617 private: LongLoType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)618 LongLoType(ObjPtr<mirror::Class> klass, 619 const std::string_view& descriptor, 620 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 621 : Cat2Type(klass, descriptor, cache_id) { 622 CheckConstructorInvariants(this); 623 } 624 static const LongLoType* instance_; 625 }; 626 627 class LongHiType final : public Cat2Type { 628 public: 629 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); IsLongHi()630 bool IsLongHi() const override { return true; } 631 static const LongHiType* CreateInstance(ObjPtr<mirror::Class> klass, 632 const std::string_view& descriptor, 633 uint16_t cache_id) 634 REQUIRES_SHARED(Locks::mutator_lock_); 635 static const LongHiType* GetInstance() PURE; 636 static void Destroy(); 637 GetAssignmentTypeImpl()638 AssignmentType GetAssignmentTypeImpl() const override { 639 return AssignmentType::kNotAssignable; 640 } 641 642 private: LongHiType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)643 LongHiType(ObjPtr<mirror::Class> klass, 644 const std::string_view& descriptor, 645 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 646 : Cat2Type(klass, descriptor, cache_id) { 647 CheckConstructorInvariants(this); 648 } 649 static const LongHiType* instance_; 650 }; 651 652 class DoubleLoType final : public Cat2Type { 653 public: 654 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); IsDoubleLo()655 bool IsDoubleLo() const override { return true; } IsDouble()656 bool IsDouble() const override { return true; } 657 static const DoubleLoType* CreateInstance(ObjPtr<mirror::Class> klass, 658 const std::string_view& descriptor, 659 uint16_t cache_id) 660 REQUIRES_SHARED(Locks::mutator_lock_); 661 static const DoubleLoType* GetInstance() PURE; 662 static void Destroy(); 663 GetAssignmentTypeImpl()664 AssignmentType GetAssignmentTypeImpl() const override { 665 return AssignmentType::kDoubleLo; 666 } 667 668 private: DoubleLoType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)669 DoubleLoType(ObjPtr<mirror::Class> klass, 670 const std::string_view& descriptor, 671 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 672 : Cat2Type(klass, descriptor, cache_id) { 673 CheckConstructorInvariants(this); 674 } 675 static const DoubleLoType* instance_; 676 }; 677 678 class DoubleHiType final : public Cat2Type { 679 public: 680 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); IsDoubleHi()681 bool IsDoubleHi() const override { return true; } 682 static const DoubleHiType* CreateInstance(ObjPtr<mirror::Class> klass, 683 const std::string_view& descriptor, 684 uint16_t cache_id) 685 REQUIRES_SHARED(Locks::mutator_lock_); 686 static const DoubleHiType* GetInstance() PURE; 687 static void Destroy(); 688 GetAssignmentTypeImpl()689 AssignmentType GetAssignmentTypeImpl() const override { 690 return AssignmentType::kNotAssignable; 691 } 692 693 private: DoubleHiType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)694 DoubleHiType(ObjPtr<mirror::Class> klass, 695 const std::string_view& descriptor, 696 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 697 : Cat2Type(klass, descriptor, cache_id) { 698 CheckConstructorInvariants(this); 699 } 700 static const DoubleHiType* instance_; 701 }; 702 703 class ConstantType : public RegType { 704 public: ConstantType(uint32_t constant,uint16_t cache_id)705 ConstantType(uint32_t constant, uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 706 : RegType(nullptr, "", cache_id), constant_(constant) { 707 } 708 709 710 // If this is a 32-bit constant, what is the value? This value may be 711 // imprecise in which case 712 // the value represents part of the integer range of values that may be held 713 // in the register. ConstantValue()714 int32_t ConstantValue() const { 715 DCHECK(IsConstantTypes()); 716 return constant_; 717 } 718 ConstantValueLo()719 int32_t ConstantValueLo() const { 720 DCHECK(IsConstantLo()); 721 return constant_; 722 } 723 ConstantValueHi()724 int32_t ConstantValueHi() const { 725 if (IsConstantHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()) { 726 return constant_; 727 } else { 728 DCHECK(false); 729 return 0; 730 } 731 } 732 IsZero()733 bool IsZero() const override { 734 return IsPreciseConstant() && ConstantValue() == 0; 735 } IsOne()736 bool IsOne() const override { 737 return IsPreciseConstant() && ConstantValue() == 1; 738 } 739 IsConstantChar()740 bool IsConstantChar() const override { 741 return IsConstant() && ConstantValue() >= 0 && 742 ConstantValue() <= std::numeric_limits<uint16_t>::max(); 743 } IsConstantByte()744 bool IsConstantByte() const override { 745 return IsConstant() && 746 ConstantValue() >= std::numeric_limits<int8_t>::min() && 747 ConstantValue() <= std::numeric_limits<int8_t>::max(); 748 } IsConstantShort()749 bool IsConstantShort() const override { 750 return IsConstant() && 751 ConstantValue() >= std::numeric_limits<int16_t>::min() && 752 ConstantValue() <= std::numeric_limits<int16_t>::max(); 753 } IsConstantTypes()754 bool IsConstantTypes() const override { return true; } 755 GetAssignmentTypeImpl()756 AssignmentType GetAssignmentTypeImpl() const override { 757 return AssignmentType::kNotAssignable; 758 } 759 760 private: 761 const uint32_t constant_; 762 }; 763 764 class PreciseConstType final : public ConstantType { 765 public: PreciseConstType(uint32_t constant,uint16_t cache_id)766 PreciseConstType(uint32_t constant, uint16_t cache_id) 767 REQUIRES_SHARED(Locks::mutator_lock_) 768 : ConstantType(constant, cache_id) { 769 CheckConstructorInvariants(this); 770 } 771 IsPreciseConstant()772 bool IsPreciseConstant() const override { return true; } 773 774 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 775 GetAssignmentTypeImpl()776 AssignmentType GetAssignmentTypeImpl() const override { 777 return AssignmentType::kNotAssignable; 778 } 779 }; 780 781 class PreciseConstLoType final : public ConstantType { 782 public: PreciseConstLoType(uint32_t constant,uint16_t cache_id)783 PreciseConstLoType(uint32_t constant, uint16_t cache_id) 784 REQUIRES_SHARED(Locks::mutator_lock_) 785 : ConstantType(constant, cache_id) { 786 CheckConstructorInvariants(this); 787 } IsPreciseConstantLo()788 bool IsPreciseConstantLo() const override { return true; } 789 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 790 GetAssignmentTypeImpl()791 AssignmentType GetAssignmentTypeImpl() const override { 792 return AssignmentType::kNotAssignable; 793 } 794 }; 795 796 class PreciseConstHiType final : public ConstantType { 797 public: PreciseConstHiType(uint32_t constant,uint16_t cache_id)798 PreciseConstHiType(uint32_t constant, uint16_t cache_id) 799 REQUIRES_SHARED(Locks::mutator_lock_) 800 : ConstantType(constant, cache_id) { 801 CheckConstructorInvariants(this); 802 } IsPreciseConstantHi()803 bool IsPreciseConstantHi() const override { return true; } 804 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 805 GetAssignmentTypeImpl()806 AssignmentType GetAssignmentTypeImpl() const override { 807 return AssignmentType::kNotAssignable; 808 } 809 }; 810 811 class ImpreciseConstType final : public ConstantType { 812 public: ImpreciseConstType(uint32_t constat,uint16_t cache_id)813 ImpreciseConstType(uint32_t constat, uint16_t cache_id) 814 REQUIRES_SHARED(Locks::mutator_lock_) 815 : ConstantType(constat, cache_id) { 816 CheckConstructorInvariants(this); 817 } IsImpreciseConstant()818 bool IsImpreciseConstant() const override { return true; } 819 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 820 GetAssignmentTypeImpl()821 AssignmentType GetAssignmentTypeImpl() const override { 822 return AssignmentType::kNotAssignable; 823 } 824 }; 825 826 class ImpreciseConstLoType final : public ConstantType { 827 public: ImpreciseConstLoType(uint32_t constant,uint16_t cache_id)828 ImpreciseConstLoType(uint32_t constant, uint16_t cache_id) 829 REQUIRES_SHARED(Locks::mutator_lock_) 830 : ConstantType(constant, cache_id) { 831 CheckConstructorInvariants(this); 832 } IsImpreciseConstantLo()833 bool IsImpreciseConstantLo() const override { return true; } 834 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 835 GetAssignmentTypeImpl()836 AssignmentType GetAssignmentTypeImpl() const override { 837 return AssignmentType::kNotAssignable; 838 } 839 }; 840 841 class ImpreciseConstHiType final : public ConstantType { 842 public: ImpreciseConstHiType(uint32_t constant,uint16_t cache_id)843 ImpreciseConstHiType(uint32_t constant, uint16_t cache_id) 844 REQUIRES_SHARED(Locks::mutator_lock_) 845 : ConstantType(constant, cache_id) { 846 CheckConstructorInvariants(this); 847 } IsImpreciseConstantHi()848 bool IsImpreciseConstantHi() const override { return true; } 849 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 850 GetAssignmentTypeImpl()851 AssignmentType GetAssignmentTypeImpl() const override { 852 return AssignmentType::kNotAssignable; 853 } 854 }; 855 856 // Special "null" type that captures the semantics of null / bottom. 857 class NullType final : public RegType { 858 public: IsNull()859 bool IsNull() const override { 860 return true; 861 } 862 863 // Get the singleton Null instance. 864 static const NullType* GetInstance() PURE; 865 866 // Create the singleton instance. 867 static const NullType* CreateInstance(ObjPtr<mirror::Class> klass, 868 const std::string_view& descriptor, 869 uint16_t cache_id) 870 REQUIRES_SHARED(Locks::mutator_lock_); 871 872 static void Destroy(); 873 Dump()874 std::string Dump() const override { 875 return "null"; 876 } 877 GetAssignmentTypeImpl()878 AssignmentType GetAssignmentTypeImpl() const override { 879 return AssignmentType::kReference; 880 } 881 IsConstantTypes()882 bool IsConstantTypes() const override { 883 return true; 884 } 885 886 private: NullType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)887 NullType(ObjPtr<mirror::Class> klass, const std::string_view& descriptor, uint16_t cache_id) 888 REQUIRES_SHARED(Locks::mutator_lock_) 889 : RegType(klass, descriptor, cache_id) { 890 CheckConstructorInvariants(this); 891 } 892 893 static const NullType* instance_; 894 }; 895 896 // Common parent of all uninitialized types. Uninitialized types are created by 897 // "new" dex 898 // instructions and must be passed to a constructor. 899 class UninitializedType : public RegType { 900 public: UninitializedType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint32_t allocation_pc,uint16_t cache_id)901 UninitializedType(ObjPtr<mirror::Class> klass, 902 const std::string_view& descriptor, 903 uint32_t allocation_pc, 904 uint16_t cache_id) 905 : RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {} 906 907 bool IsUninitializedTypes() const override; 908 bool IsNonZeroReferenceTypes() const override; 909 GetAllocationPc()910 uint32_t GetAllocationPc() const { 911 DCHECK(IsUninitializedTypes()); 912 return allocation_pc_; 913 } 914 GetAssignmentTypeImpl()915 AssignmentType GetAssignmentTypeImpl() const override { 916 return AssignmentType::kReference; 917 } 918 919 private: 920 const uint32_t allocation_pc_; 921 }; 922 923 // Similar to ReferenceType but not yet having been passed to a constructor. 924 class UninitializedReferenceType final : public UninitializedType { 925 public: UninitializedReferenceType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint32_t allocation_pc,uint16_t cache_id)926 UninitializedReferenceType(ObjPtr<mirror::Class> klass, 927 const std::string_view& descriptor, 928 uint32_t allocation_pc, 929 uint16_t cache_id) 930 REQUIRES_SHARED(Locks::mutator_lock_) 931 : UninitializedType(klass, descriptor, allocation_pc, cache_id) { 932 CheckConstructorInvariants(this); 933 } 934 IsUninitializedReference()935 bool IsUninitializedReference() const override { return true; } 936 HasClassVirtual()937 bool HasClassVirtual() const override { return true; } 938 939 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 940 }; 941 942 // Similar to UnresolvedReferenceType but not yet having been passed to a 943 // constructor. 944 class UnresolvedUninitializedRefType final : public UninitializedType { 945 public: UnresolvedUninitializedRefType(const std::string_view & descriptor,uint32_t allocation_pc,uint16_t cache_id)946 UnresolvedUninitializedRefType(const std::string_view& descriptor, 947 uint32_t allocation_pc, 948 uint16_t cache_id) 949 REQUIRES_SHARED(Locks::mutator_lock_) 950 : UninitializedType(nullptr, descriptor, allocation_pc, cache_id) { 951 CheckConstructorInvariants(this); 952 } 953 IsUnresolvedAndUninitializedReference()954 bool IsUnresolvedAndUninitializedReference() const override { return true; } 955 IsUnresolvedTypes()956 bool IsUnresolvedTypes() const override { return true; } 957 958 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 959 960 private: 961 void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override; 962 }; 963 964 // Similar to UninitializedReferenceType but special case for the this argument 965 // of a constructor. 966 class UninitializedThisReferenceType final : public UninitializedType { 967 public: UninitializedThisReferenceType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)968 UninitializedThisReferenceType(ObjPtr<mirror::Class> klass, 969 const std::string_view& descriptor, 970 uint16_t cache_id) 971 REQUIRES_SHARED(Locks::mutator_lock_) 972 : UninitializedType(klass, descriptor, 0, cache_id) { 973 CheckConstructorInvariants(this); 974 } 975 IsUninitializedThisReference()976 bool IsUninitializedThisReference() const override { return true; } 977 HasClassVirtual()978 bool HasClassVirtual() 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 class UnresolvedUninitializedThisRefType final : public UninitializedType { 987 public: UnresolvedUninitializedThisRefType(const std::string_view & descriptor,uint16_t cache_id)988 UnresolvedUninitializedThisRefType(const std::string_view& descriptor, uint16_t cache_id) 989 REQUIRES_SHARED(Locks::mutator_lock_) 990 : UninitializedType(nullptr, descriptor, 0, cache_id) { 991 CheckConstructorInvariants(this); 992 } 993 IsUnresolvedAndUninitializedThisReference()994 bool IsUnresolvedAndUninitializedThisReference() const override { return true; } 995 IsUnresolvedTypes()996 bool IsUnresolvedTypes() const override { return true; } 997 998 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 999 1000 private: 1001 void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override; 1002 }; 1003 1004 // A type of register holding a reference to an Object of type GetClass or a 1005 // sub-class. 1006 class ReferenceType final : public RegType { 1007 public: ReferenceType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)1008 ReferenceType(ObjPtr<mirror::Class> klass, 1009 const std::string_view& descriptor, 1010 uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_) 1011 : RegType(klass, descriptor, cache_id) { 1012 CheckConstructorInvariants(this); 1013 } 1014 IsReference()1015 bool IsReference() const override { return true; } 1016 IsNonZeroReferenceTypes()1017 bool IsNonZeroReferenceTypes() const override { return true; } 1018 HasClassVirtual()1019 bool HasClassVirtual() const override { return true; } 1020 1021 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1022 GetAssignmentTypeImpl()1023 AssignmentType GetAssignmentTypeImpl() const override { 1024 return AssignmentType::kReference; 1025 } 1026 }; 1027 1028 // A type of register holding a reference to an Object of type GetClass and only 1029 // an object of that 1030 // type. 1031 class PreciseReferenceType final : public RegType { 1032 public: 1033 PreciseReferenceType(ObjPtr<mirror::Class> klass, 1034 const std::string_view& descriptor, 1035 uint16_t cache_id) 1036 REQUIRES_SHARED(Locks::mutator_lock_); 1037 IsPreciseReference()1038 bool IsPreciseReference() const override { return true; } 1039 IsNonZeroReferenceTypes()1040 bool IsNonZeroReferenceTypes() const override { return true; } 1041 HasClassVirtual()1042 bool HasClassVirtual() const override { return true; } 1043 1044 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1045 GetAssignmentTypeImpl()1046 AssignmentType GetAssignmentTypeImpl() const override { 1047 return AssignmentType::kReference; 1048 } 1049 }; 1050 1051 // Common parent of unresolved types. 1052 class UnresolvedType : public RegType { 1053 public: UnresolvedType(const std::string_view & descriptor,uint16_t cache_id)1054 UnresolvedType(const std::string_view& descriptor, uint16_t cache_id) 1055 REQUIRES_SHARED(Locks::mutator_lock_) 1056 : RegType(nullptr, descriptor, cache_id) {} 1057 1058 bool IsNonZeroReferenceTypes() const override; 1059 GetAssignmentTypeImpl()1060 AssignmentType GetAssignmentTypeImpl() const override { 1061 return AssignmentType::kReference; 1062 } 1063 }; 1064 1065 // Similar to ReferenceType except the Class couldn't be loaded. Assignability 1066 // and other tests made 1067 // of this type must be conservative. 1068 class UnresolvedReferenceType final : public UnresolvedType { 1069 public: UnresolvedReferenceType(const std::string_view & descriptor,uint16_t cache_id)1070 UnresolvedReferenceType(const std::string_view& descriptor, uint16_t cache_id) 1071 REQUIRES_SHARED(Locks::mutator_lock_) 1072 : UnresolvedType(descriptor, cache_id) { 1073 CheckConstructorInvariants(this); 1074 } 1075 IsUnresolvedReference()1076 bool IsUnresolvedReference() const override { return true; } 1077 IsUnresolvedTypes()1078 bool IsUnresolvedTypes() const override { return true; } 1079 1080 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1081 1082 private: 1083 void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override; 1084 }; 1085 1086 // Type representing the super-class of an unresolved type. 1087 class UnresolvedSuperClass final : public UnresolvedType { 1088 public: UnresolvedSuperClass(uint16_t child_id,RegTypeCache * reg_type_cache,uint16_t cache_id)1089 UnresolvedSuperClass(uint16_t child_id, RegTypeCache* reg_type_cache, 1090 uint16_t cache_id) 1091 REQUIRES_SHARED(Locks::mutator_lock_) 1092 : UnresolvedType("", cache_id), 1093 unresolved_child_id_(child_id), 1094 reg_type_cache_(reg_type_cache) { 1095 CheckConstructorInvariants(this); 1096 } 1097 IsUnresolvedSuperClass()1098 bool IsUnresolvedSuperClass() const override { return true; } 1099 IsUnresolvedTypes()1100 bool IsUnresolvedTypes() const override { return true; } 1101 GetUnresolvedSuperClassChildId()1102 uint16_t GetUnresolvedSuperClassChildId() const { 1103 DCHECK(IsUnresolvedSuperClass()); 1104 return static_cast<uint16_t>(unresolved_child_id_ & 0xFFFF); 1105 } 1106 1107 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1108 1109 private: 1110 void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override; 1111 1112 const uint16_t unresolved_child_id_; 1113 const RegTypeCache* const reg_type_cache_; 1114 }; 1115 1116 // A merge of unresolved (and resolved) types. If the types were resolved this may be 1117 // Conflict or another known ReferenceType. 1118 class UnresolvedMergedType final : public UnresolvedType { 1119 public: 1120 // Note: the constructor will copy the unresolved BitVector, not use it directly. 1121 UnresolvedMergedType(const RegType& resolved, 1122 const BitVector& unresolved, 1123 const RegTypeCache* reg_type_cache, 1124 uint16_t cache_id) 1125 REQUIRES_SHARED(Locks::mutator_lock_); 1126 1127 // The resolved part. See description below. GetResolvedPart()1128 const RegType& GetResolvedPart() const { 1129 return resolved_part_; 1130 } 1131 // The unresolved part. GetUnresolvedTypes()1132 const BitVector& GetUnresolvedTypes() const { 1133 return unresolved_types_; 1134 } 1135 IsUnresolvedMergedReference()1136 bool IsUnresolvedMergedReference() const override { return true; } 1137 IsUnresolvedTypes()1138 bool IsUnresolvedTypes() const override { return true; } 1139 1140 bool IsArrayTypes() const override REQUIRES_SHARED(Locks::mutator_lock_); 1141 bool IsObjectArrayTypes() const override REQUIRES_SHARED(Locks::mutator_lock_); 1142 1143 std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_); 1144 GetRegTypeCache()1145 const RegTypeCache* GetRegTypeCache() const { return reg_type_cache_; } 1146 1147 private: 1148 void CheckInvariants() const REQUIRES_SHARED(Locks::mutator_lock_) override; 1149 1150 const RegTypeCache* const reg_type_cache_; 1151 1152 // The original implementation of merged types was a binary tree. Collection of the flattened 1153 // types ("leaves") can be expensive, so we store the expanded list now, as two components: 1154 // 1) A resolved component. We use Zero when there is no resolved component, as that will be 1155 // an identity merge. 1156 // 2) A bitvector of the unresolved reference types. A bitvector was chosen with the assumption 1157 // that there should not be too many types in flight in practice. (We also bias the index 1158 // against the index of Zero, which is one of the later default entries in any cache.) 1159 const RegType& resolved_part_; 1160 const BitVector unresolved_types_; 1161 }; 1162 1163 std::ostream& operator<<(std::ostream& os, const RegType& rhs) 1164 REQUIRES_SHARED(Locks::mutator_lock_); 1165 1166 } // namespace verifier 1167 } // namespace art 1168 1169 #endif // ART_RUNTIME_VERIFIER_REG_TYPE_H_ 1170