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 25 #include "base/arena_object.h" 26 #include "base/bit_vector.h" 27 #include "base/macros.h" 28 #include "base/mutex.h" 29 #include "base/stringpiece.h" 30 #include "gc_root.h" 31 #include "handle_scope.h" 32 #include "object_callbacks.h" 33 #include "primitive.h" 34 35 namespace art { 36 namespace mirror { 37 class Class; 38 } // namespace mirror 39 40 class ArenaBitVector; 41 class ScopedArenaAllocator; 42 43 namespace verifier { 44 45 class RegTypeCache; 46 /* 47 * RegType holds information about the "type" of data held in a register. 48 */ 49 class RegType { 50 public: IsUndefined()51 virtual bool IsUndefined() const { return false; } IsConflict()52 virtual bool IsConflict() const { return false; } IsBoolean()53 virtual bool IsBoolean() const { return false; } IsByte()54 virtual bool IsByte() const { return false; } IsChar()55 virtual bool IsChar() const { return false; } IsShort()56 virtual bool IsShort() const { return false; } IsInteger()57 virtual bool IsInteger() const { return false; } IsLongLo()58 virtual bool IsLongLo() const { return false; } IsLongHi()59 virtual bool IsLongHi() const { return false; } IsFloat()60 virtual bool IsFloat() const { return false; } IsDouble()61 virtual bool IsDouble() const { return false; } IsDoubleLo()62 virtual bool IsDoubleLo() const { return false; } IsDoubleHi()63 virtual bool IsDoubleHi() const { return false; } IsUnresolvedReference()64 virtual bool IsUnresolvedReference() const { return false; } IsUninitializedReference()65 virtual bool IsUninitializedReference() const { return false; } IsUninitializedThisReference()66 virtual bool IsUninitializedThisReference() const { return false; } IsUnresolvedAndUninitializedReference()67 virtual bool IsUnresolvedAndUninitializedReference() const { return false; } IsUnresolvedAndUninitializedThisReference()68 virtual bool IsUnresolvedAndUninitializedThisReference() const { 69 return false; 70 } IsUnresolvedMergedReference()71 virtual bool IsUnresolvedMergedReference() const { return false; } IsUnresolvedSuperClass()72 virtual bool IsUnresolvedSuperClass() const { return false; } IsReference()73 virtual bool IsReference() const { return false; } IsPreciseReference()74 virtual bool IsPreciseReference() const { return false; } IsPreciseConstant()75 virtual bool IsPreciseConstant() const { return false; } IsPreciseConstantLo()76 virtual bool IsPreciseConstantLo() const { return false; } IsPreciseConstantHi()77 virtual bool IsPreciseConstantHi() const { return false; } IsImpreciseConstantLo()78 virtual bool IsImpreciseConstantLo() const { return false; } IsImpreciseConstantHi()79 virtual bool IsImpreciseConstantHi() const { return false; } IsImpreciseConstant()80 virtual bool IsImpreciseConstant() const { return false; } IsConstantTypes()81 virtual bool IsConstantTypes() const { return false; } IsConstant()82 bool IsConstant() const { 83 return IsImpreciseConstant() || IsPreciseConstant(); 84 } IsConstantLo()85 bool IsConstantLo() const { 86 return IsImpreciseConstantLo() || IsPreciseConstantLo(); 87 } IsPrecise()88 bool IsPrecise() const { 89 return IsPreciseConstantLo() || IsPreciseConstant() || 90 IsPreciseConstantHi(); 91 } IsLongConstant()92 bool IsLongConstant() const { return IsConstantLo(); } IsConstantHi()93 bool IsConstantHi() const { 94 return (IsPreciseConstantHi() || IsImpreciseConstantHi()); 95 } IsLongConstantHigh()96 bool IsLongConstantHigh() const { return IsConstantHi(); } IsUninitializedTypes()97 virtual bool IsUninitializedTypes() const { return false; } IsUnresolvedTypes()98 virtual bool IsUnresolvedTypes() const { return false; } 99 IsLowHalf()100 bool IsLowHalf() const { 101 return (IsLongLo() || IsDoubleLo() || IsPreciseConstantLo() || IsImpreciseConstantLo()); 102 } IsHighHalf()103 bool IsHighHalf() const { 104 return (IsLongHi() || IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()); 105 } IsLongOrDoubleTypes()106 bool IsLongOrDoubleTypes() const { return IsLowHalf(); } 107 // Check this is the low half, and that type_h is its matching high-half. CheckWidePair(const RegType & type_h)108 inline bool CheckWidePair(const RegType& type_h) const { 109 if (IsLowHalf()) { 110 return ((IsImpreciseConstantLo() && type_h.IsPreciseConstantHi()) || 111 (IsImpreciseConstantLo() && type_h.IsImpreciseConstantHi()) || 112 (IsPreciseConstantLo() && type_h.IsPreciseConstantHi()) || 113 (IsPreciseConstantLo() && type_h.IsImpreciseConstantHi()) || 114 (IsDoubleLo() && type_h.IsDoubleHi()) || 115 (IsLongLo() && type_h.IsLongHi())); 116 } 117 return false; 118 } 119 // The high half that corresponds to this low half 120 const RegType& HighHalf(RegTypeCache* cache) const 121 SHARED_REQUIRES(Locks::mutator_lock_); 122 123 bool IsConstantBoolean() const; IsConstantChar()124 virtual bool IsConstantChar() const { return false; } IsConstantByte()125 virtual bool IsConstantByte() const { return false; } IsConstantShort()126 virtual bool IsConstantShort() const { return false; } IsOne()127 virtual bool IsOne() const { return false; } IsZero()128 virtual bool IsZero() const { return false; } IsReferenceTypes()129 bool IsReferenceTypes() const { 130 return IsNonZeroReferenceTypes() || IsZero(); 131 } IsNonZeroReferenceTypes()132 virtual bool IsNonZeroReferenceTypes() const { return false; } IsCategory1Types()133 bool IsCategory1Types() const { 134 return IsChar() || IsInteger() || IsFloat() || IsConstant() || IsByte() || 135 IsShort() || IsBoolean(); 136 } IsCategory2Types()137 bool IsCategory2Types() const { 138 return IsLowHalf(); // Don't expect explicit testing of high halves 139 } IsBooleanTypes()140 bool IsBooleanTypes() const { return IsBoolean() || IsConstantBoolean(); } IsByteTypes()141 bool IsByteTypes() const { 142 return IsConstantByte() || IsByte() || IsBoolean(); 143 } IsShortTypes()144 bool IsShortTypes() const { 145 return IsShort() || IsByte() || IsBoolean() || IsConstantShort(); 146 } IsCharTypes()147 bool IsCharTypes() const { 148 return IsChar() || IsBooleanTypes() || IsConstantChar(); 149 } IsIntegralTypes()150 bool IsIntegralTypes() const { 151 return IsInteger() || IsConstant() || IsByte() || IsShort() || IsChar() || 152 IsBoolean(); 153 } 154 // Give the constant value encoded, but this shouldn't be called in the 155 // general case. IsArrayIndexTypes()156 bool IsArrayIndexTypes() const { return IsIntegralTypes(); } 157 // Float type may be derived from any constant type IsFloatTypes()158 bool IsFloatTypes() const { return IsFloat() || IsConstant(); } IsLongTypes()159 bool IsLongTypes() const { return IsLongLo() || IsLongConstant(); } IsLongHighTypes()160 bool IsLongHighTypes() const { 161 return (IsLongHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()); 162 } IsDoubleTypes()163 bool IsDoubleTypes() const { return IsDoubleLo() || IsLongConstant(); } IsDoubleHighTypes()164 bool IsDoubleHighTypes() const { 165 return (IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()); 166 } IsLong()167 virtual bool IsLong() const { return false; } HasClass()168 bool HasClass() const { 169 bool result = !klass_.IsNull(); 170 DCHECK_EQ(result, HasClassVirtual()); 171 return result; 172 } HasClassVirtual()173 virtual bool HasClassVirtual() const { return false; } 174 bool IsJavaLangObject() const SHARED_REQUIRES(Locks::mutator_lock_); 175 virtual bool IsArrayTypes() const SHARED_REQUIRES(Locks::mutator_lock_); 176 virtual bool IsObjectArrayTypes() const SHARED_REQUIRES(Locks::mutator_lock_); 177 Primitive::Type GetPrimitiveType() const; 178 bool IsJavaLangObjectArray() const 179 SHARED_REQUIRES(Locks::mutator_lock_); 180 bool IsInstantiableTypes() const SHARED_REQUIRES(Locks::mutator_lock_); GetDescriptor()181 const StringPiece& GetDescriptor() const { 182 DCHECK(HasClass() || 183 (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && 184 !IsUnresolvedSuperClass())); 185 return descriptor_; 186 } GetClass()187 mirror::Class* GetClass() const SHARED_REQUIRES(Locks::mutator_lock_) { 188 DCHECK(!IsUnresolvedReference()); 189 DCHECK(!klass_.IsNull()) << Dump(); 190 DCHECK(HasClass()); 191 return klass_.Read(); 192 } GetId()193 uint16_t GetId() const { return cache_id_; } 194 const RegType& GetSuperClass(RegTypeCache* cache) const 195 SHARED_REQUIRES(Locks::mutator_lock_); 196 197 virtual std::string Dump() const 198 SHARED_REQUIRES(Locks::mutator_lock_) = 0; 199 200 // Can this type access other? 201 bool CanAccess(const RegType& other) const 202 SHARED_REQUIRES(Locks::mutator_lock_); 203 204 // Can this type access a member with the given properties? 205 bool CanAccessMember(mirror::Class* klass, uint32_t access_flags) const 206 SHARED_REQUIRES(Locks::mutator_lock_); 207 208 // Can this type be assigned by src? 209 // Note: Object and interface types may always be assigned to one another, see 210 // comment on 211 // ClassJoin. 212 bool IsAssignableFrom(const RegType& src) const 213 SHARED_REQUIRES(Locks::mutator_lock_); 214 215 // Can this array type potentially be assigned by src. 216 // This function is necessary as array types are valid even if their components types are not, 217 // e.g., when they component type could not be resolved. The function will return true iff the 218 // types are assignable. It will return false otherwise. In case of return=false, soft_error 219 // will be set to true iff the assignment test failure should be treated as a soft-error, i.e., 220 // when both array types have the same 'depth' and the 'final' component types may be assignable 221 // (both are reference types). 222 bool CanAssignArray(const RegType& src, RegTypeCache& reg_types, 223 Handle<mirror::ClassLoader> class_loader, bool* soft_error) const 224 SHARED_REQUIRES(Locks::mutator_lock_); 225 226 // Can this type be assigned by src? Variant of IsAssignableFrom that doesn't 227 // allow assignment to 228 // an interface from an Object. 229 bool IsStrictlyAssignableFrom(const RegType& src) const 230 SHARED_REQUIRES(Locks::mutator_lock_); 231 232 // Are these RegTypes the same? Equals(const RegType & other)233 bool Equals(const RegType& other) const { return GetId() == other.GetId(); } 234 235 // Compute the merge of this register from one edge (path) with incoming_type 236 // from another. 237 const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const 238 SHARED_REQUIRES(Locks::mutator_lock_); 239 // Same as above, but also handles the case where incoming_type == this. SafeMerge(const RegType & incoming_type,RegTypeCache * reg_types)240 const RegType& SafeMerge(const RegType& incoming_type, RegTypeCache* reg_types) const 241 SHARED_REQUIRES(Locks::mutator_lock_) { 242 if (Equals(incoming_type)) { 243 return *this; 244 } 245 return Merge(incoming_type, reg_types); 246 } 247 248 /* 249 * A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is 250 * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of 251 * 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 252 * is the deepest (lowest upper bound) parent of S and T). 253 * 254 * This operation applies for regular classes and arrays, however, for interface types there 255 * needn't be a partial ordering on the types. We could solve the problem of a lack of a partial 256 * order by introducing sets of types, however, the only operation permissible on an interface is 257 * invoke-interface. In the tradition of Java verifiers [1] we defer the verification of interface 258 * types until an invoke-interface call on the interface typed reference at runtime and allow 259 * the perversion of Object being assignable to an interface type (note, however, that we don't 260 * allow assignment of Object or Interface to any concrete class and are therefore type safe). 261 * 262 * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy 263 */ 264 static mirror::Class* ClassJoin(mirror::Class* s, mirror::Class* t) 265 SHARED_REQUIRES(Locks::mutator_lock_); 266 ~RegType()267 virtual ~RegType() {} 268 269 void VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const 270 SHARED_REQUIRES(Locks::mutator_lock_); 271 new(size_t size)272 static void* operator new(size_t size) noexcept { 273 return ::operator new(size); 274 } 275 276 static void* operator new(size_t size, ArenaAllocator* arena) = delete; 277 static void* operator new(size_t size, ScopedArenaAllocator* arena); 278 279 protected: RegType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)280 RegType(mirror::Class* klass, 281 const StringPiece& descriptor, 282 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 283 : descriptor_(descriptor), 284 klass_(klass), 285 cache_id_(cache_id) { 286 if (kIsDebugBuild) { 287 CheckInvariants(); 288 } 289 } 290 291 void CheckInvariants() const SHARED_REQUIRES(Locks::mutator_lock_); 292 293 const StringPiece descriptor_; 294 mutable GcRoot<mirror::Class> klass_; // Non-const only due to moving classes. 295 const uint16_t cache_id_; 296 297 friend class RegTypeCache; 298 299 private: 300 static bool AssignableFrom(const RegType& lhs, const RegType& rhs, bool strict) 301 SHARED_REQUIRES(Locks::mutator_lock_); 302 303 DISALLOW_COPY_AND_ASSIGN(RegType); 304 }; 305 306 // Bottom type. 307 class ConflictType FINAL : public RegType { 308 public: IsConflict()309 bool IsConflict() const OVERRIDE { return true; } 310 311 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 312 313 // Get the singleton Conflict instance. 314 static const ConflictType* GetInstance() PURE; 315 316 // Create the singleton instance. 317 static const ConflictType* CreateInstance(mirror::Class* klass, 318 const StringPiece& descriptor, 319 uint16_t cache_id) 320 SHARED_REQUIRES(Locks::mutator_lock_); 321 322 // Destroy the singleton instance. 323 static void Destroy(); 324 325 private: ConflictType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)326 ConflictType(mirror::Class* klass, const StringPiece& descriptor, 327 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 328 : RegType(klass, descriptor, cache_id) {} 329 330 static const ConflictType* instance_; 331 }; 332 333 // A variant of the bottom type used to specify an undefined value in the 334 // incoming registers. 335 // Merging with UndefinedType yields ConflictType which is the true bottom. 336 class UndefinedType FINAL : public RegType { 337 public: IsUndefined()338 bool IsUndefined() const OVERRIDE { return true; } 339 340 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 341 342 // Get the singleton Undefined instance. 343 static const UndefinedType* GetInstance() PURE; 344 345 // Create the singleton instance. 346 static const UndefinedType* CreateInstance(mirror::Class* klass, 347 const StringPiece& descriptor, 348 uint16_t cache_id) 349 SHARED_REQUIRES(Locks::mutator_lock_); 350 351 // Destroy the singleton instance. 352 static void Destroy(); 353 354 private: UndefinedType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)355 UndefinedType(mirror::Class* klass, const StringPiece& descriptor, 356 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 357 : RegType(klass, descriptor, cache_id) {} 358 359 static const UndefinedType* instance_; 360 }; 361 362 class PrimitiveType : public RegType { 363 public: 364 PrimitiveType(mirror::Class* klass, const StringPiece& descriptor, 365 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_); 366 HasClassVirtual()367 bool HasClassVirtual() const OVERRIDE { return true; } 368 }; 369 370 class Cat1Type : public PrimitiveType { 371 public: 372 Cat1Type(mirror::Class* klass, const StringPiece& descriptor, 373 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_); 374 }; 375 376 class IntegerType : public Cat1Type { 377 public: IsInteger()378 bool IsInteger() const OVERRIDE { return true; } 379 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 380 static const IntegerType* CreateInstance(mirror::Class* klass, 381 const StringPiece& descriptor, 382 uint16_t cache_id) 383 SHARED_REQUIRES(Locks::mutator_lock_); 384 static const IntegerType* GetInstance() PURE; 385 static void Destroy(); 386 387 private: IntegerType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)388 IntegerType(mirror::Class* klass, const StringPiece& descriptor, 389 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 390 : Cat1Type(klass, descriptor, cache_id) {} 391 static const IntegerType* instance_; 392 }; 393 394 class BooleanType FINAL : public Cat1Type { 395 public: IsBoolean()396 bool IsBoolean() const OVERRIDE { return true; } 397 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 398 static const BooleanType* CreateInstance(mirror::Class* klass, 399 const StringPiece& descriptor, 400 uint16_t cache_id) 401 SHARED_REQUIRES(Locks::mutator_lock_); 402 static const BooleanType* GetInstance() PURE; 403 static void Destroy(); 404 405 private: BooleanType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)406 BooleanType(mirror::Class* klass, const StringPiece& descriptor, 407 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 408 : Cat1Type(klass, descriptor, cache_id) {} 409 410 static const BooleanType* instance_; 411 }; 412 413 class ByteType FINAL : public Cat1Type { 414 public: IsByte()415 bool IsByte() const OVERRIDE { return true; } 416 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 417 static const ByteType* CreateInstance(mirror::Class* klass, 418 const StringPiece& descriptor, 419 uint16_t cache_id) 420 SHARED_REQUIRES(Locks::mutator_lock_); 421 static const ByteType* GetInstance() PURE; 422 static void Destroy(); 423 424 private: ByteType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)425 ByteType(mirror::Class* klass, const StringPiece& descriptor, 426 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 427 : Cat1Type(klass, descriptor, cache_id) {} 428 static const ByteType* instance_; 429 }; 430 431 class ShortType FINAL : public Cat1Type { 432 public: IsShort()433 bool IsShort() const OVERRIDE { return true; } 434 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 435 static const ShortType* CreateInstance(mirror::Class* klass, 436 const StringPiece& descriptor, 437 uint16_t cache_id) 438 SHARED_REQUIRES(Locks::mutator_lock_); 439 static const ShortType* GetInstance() PURE; 440 static void Destroy(); 441 442 private: ShortType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)443 ShortType(mirror::Class* klass, const StringPiece& descriptor, 444 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 445 : Cat1Type(klass, descriptor, cache_id) {} 446 static const ShortType* instance_; 447 }; 448 449 class CharType FINAL : public Cat1Type { 450 public: IsChar()451 bool IsChar() const OVERRIDE { return true; } 452 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 453 static const CharType* CreateInstance(mirror::Class* klass, 454 const StringPiece& descriptor, 455 uint16_t cache_id) 456 SHARED_REQUIRES(Locks::mutator_lock_); 457 static const CharType* GetInstance() PURE; 458 static void Destroy(); 459 460 private: CharType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)461 CharType(mirror::Class* klass, const StringPiece& descriptor, 462 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 463 : Cat1Type(klass, descriptor, cache_id) {} 464 static const CharType* instance_; 465 }; 466 467 class FloatType FINAL : public Cat1Type { 468 public: IsFloat()469 bool IsFloat() const OVERRIDE { return true; } 470 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 471 static const FloatType* CreateInstance(mirror::Class* klass, 472 const StringPiece& descriptor, 473 uint16_t cache_id) 474 SHARED_REQUIRES(Locks::mutator_lock_); 475 static const FloatType* GetInstance() PURE; 476 static void Destroy(); 477 478 private: FloatType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)479 FloatType(mirror::Class* klass, const StringPiece& descriptor, 480 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 481 : Cat1Type(klass, descriptor, cache_id) {} 482 static const FloatType* instance_; 483 }; 484 485 class Cat2Type : public PrimitiveType { 486 public: 487 Cat2Type(mirror::Class* klass, const StringPiece& descriptor, 488 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_); 489 }; 490 491 class LongLoType FINAL : public Cat2Type { 492 public: 493 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); IsLongLo()494 bool IsLongLo() const OVERRIDE { return true; } IsLong()495 bool IsLong() const OVERRIDE { return true; } 496 static const LongLoType* CreateInstance(mirror::Class* klass, 497 const StringPiece& descriptor, 498 uint16_t cache_id) 499 SHARED_REQUIRES(Locks::mutator_lock_); 500 static const LongLoType* GetInstance() PURE; 501 static void Destroy(); 502 503 private: LongLoType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)504 LongLoType(mirror::Class* klass, const StringPiece& descriptor, 505 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 506 : Cat2Type(klass, descriptor, cache_id) {} 507 static const LongLoType* instance_; 508 }; 509 510 class LongHiType FINAL : public Cat2Type { 511 public: 512 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); IsLongHi()513 bool IsLongHi() const OVERRIDE { return true; } 514 static const LongHiType* CreateInstance(mirror::Class* klass, 515 const StringPiece& descriptor, 516 uint16_t cache_id) 517 SHARED_REQUIRES(Locks::mutator_lock_); 518 static const LongHiType* GetInstance() PURE; 519 static void Destroy(); 520 521 private: LongHiType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)522 LongHiType(mirror::Class* klass, const StringPiece& descriptor, 523 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 524 : Cat2Type(klass, descriptor, cache_id) {} 525 static const LongHiType* instance_; 526 }; 527 528 class DoubleLoType FINAL : public Cat2Type { 529 public: 530 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); IsDoubleLo()531 bool IsDoubleLo() const OVERRIDE { return true; } IsDouble()532 bool IsDouble() const OVERRIDE { return true; } 533 static const DoubleLoType* CreateInstance(mirror::Class* klass, 534 const StringPiece& descriptor, 535 uint16_t cache_id) 536 SHARED_REQUIRES(Locks::mutator_lock_); 537 static const DoubleLoType* GetInstance() PURE; 538 static void Destroy(); 539 540 private: DoubleLoType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)541 DoubleLoType(mirror::Class* klass, const StringPiece& descriptor, 542 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 543 : Cat2Type(klass, descriptor, cache_id) {} 544 static const DoubleLoType* instance_; 545 }; 546 547 class DoubleHiType FINAL : public Cat2Type { 548 public: 549 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); IsDoubleHi()550 virtual bool IsDoubleHi() const OVERRIDE { return true; } 551 static const DoubleHiType* CreateInstance(mirror::Class* klass, 552 const StringPiece& descriptor, 553 uint16_t cache_id) 554 SHARED_REQUIRES(Locks::mutator_lock_); 555 static const DoubleHiType* GetInstance() PURE; 556 static void Destroy(); 557 558 private: DoubleHiType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)559 DoubleHiType(mirror::Class* klass, const StringPiece& descriptor, 560 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 561 : Cat2Type(klass, descriptor, cache_id) {} 562 static const DoubleHiType* instance_; 563 }; 564 565 class ConstantType : public RegType { 566 public: ConstantType(uint32_t constant,uint16_t cache_id)567 ConstantType(uint32_t constant, uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 568 : RegType(nullptr, "", cache_id), constant_(constant) { 569 } 570 571 572 // If this is a 32-bit constant, what is the value? This value may be 573 // imprecise in which case 574 // the value represents part of the integer range of values that may be held 575 // in the register. ConstantValue()576 int32_t ConstantValue() const { 577 DCHECK(IsConstantTypes()); 578 return constant_; 579 } 580 ConstantValueLo()581 int32_t ConstantValueLo() const { 582 DCHECK(IsConstantLo()); 583 return constant_; 584 } 585 ConstantValueHi()586 int32_t ConstantValueHi() const { 587 if (IsConstantHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()) { 588 return constant_; 589 } else { 590 DCHECK(false); 591 return 0; 592 } 593 } 594 IsZero()595 bool IsZero() const OVERRIDE { 596 return IsPreciseConstant() && ConstantValue() == 0; 597 } IsOne()598 bool IsOne() const OVERRIDE { 599 return IsPreciseConstant() && ConstantValue() == 1; 600 } 601 IsConstantChar()602 bool IsConstantChar() const OVERRIDE { 603 return IsConstant() && ConstantValue() >= 0 && 604 ConstantValue() <= std::numeric_limits<uint16_t>::max(); 605 } IsConstantByte()606 bool IsConstantByte() const OVERRIDE { 607 return IsConstant() && 608 ConstantValue() >= std::numeric_limits<int8_t>::min() && 609 ConstantValue() <= std::numeric_limits<int8_t>::max(); 610 } IsConstantShort()611 bool IsConstantShort() const OVERRIDE { 612 return IsConstant() && 613 ConstantValue() >= std::numeric_limits<int16_t>::min() && 614 ConstantValue() <= std::numeric_limits<int16_t>::max(); 615 } IsConstantTypes()616 virtual bool IsConstantTypes() const OVERRIDE { return true; } 617 618 private: 619 const uint32_t constant_; 620 }; 621 622 class PreciseConstType FINAL : public ConstantType { 623 public: PreciseConstType(uint32_t constant,uint16_t cache_id)624 PreciseConstType(uint32_t constant, uint16_t cache_id) 625 SHARED_REQUIRES(Locks::mutator_lock_) 626 : ConstantType(constant, cache_id) {} 627 IsPreciseConstant()628 bool IsPreciseConstant() const OVERRIDE { return true; } 629 630 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 631 }; 632 633 class PreciseConstLoType FINAL : public ConstantType { 634 public: PreciseConstLoType(uint32_t constant,uint16_t cache_id)635 PreciseConstLoType(uint32_t constant, uint16_t cache_id) 636 SHARED_REQUIRES(Locks::mutator_lock_) 637 : ConstantType(constant, cache_id) {} IsPreciseConstantLo()638 bool IsPreciseConstantLo() const OVERRIDE { return true; } 639 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 640 }; 641 642 class PreciseConstHiType FINAL : public ConstantType { 643 public: PreciseConstHiType(uint32_t constant,uint16_t cache_id)644 PreciseConstHiType(uint32_t constant, uint16_t cache_id) 645 SHARED_REQUIRES(Locks::mutator_lock_) 646 : ConstantType(constant, cache_id) {} IsPreciseConstantHi()647 bool IsPreciseConstantHi() const OVERRIDE { return true; } 648 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 649 }; 650 651 class ImpreciseConstType FINAL : public ConstantType { 652 public: ImpreciseConstType(uint32_t constat,uint16_t cache_id)653 ImpreciseConstType(uint32_t constat, uint16_t cache_id) 654 SHARED_REQUIRES(Locks::mutator_lock_) 655 : ConstantType(constat, cache_id) { 656 } IsImpreciseConstant()657 bool IsImpreciseConstant() const OVERRIDE { return true; } 658 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 659 }; 660 661 class ImpreciseConstLoType FINAL : public ConstantType { 662 public: ImpreciseConstLoType(uint32_t constant,uint16_t cache_id)663 ImpreciseConstLoType(uint32_t constant, uint16_t cache_id) 664 SHARED_REQUIRES(Locks::mutator_lock_) 665 : ConstantType(constant, cache_id) {} IsImpreciseConstantLo()666 bool IsImpreciseConstantLo() const OVERRIDE { return true; } 667 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 668 }; 669 670 class ImpreciseConstHiType FINAL : public ConstantType { 671 public: ImpreciseConstHiType(uint32_t constant,uint16_t cache_id)672 ImpreciseConstHiType(uint32_t constant, uint16_t cache_id) 673 SHARED_REQUIRES(Locks::mutator_lock_) 674 : ConstantType(constant, cache_id) {} IsImpreciseConstantHi()675 bool IsImpreciseConstantHi() const OVERRIDE { return true; } 676 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 677 }; 678 679 // Common parent of all uninitialized types. Uninitialized types are created by 680 // "new" dex 681 // instructions and must be passed to a constructor. 682 class UninitializedType : public RegType { 683 public: UninitializedType(mirror::Class * klass,const StringPiece & descriptor,uint32_t allocation_pc,uint16_t cache_id)684 UninitializedType(mirror::Class* klass, const StringPiece& descriptor, 685 uint32_t allocation_pc, uint16_t cache_id) 686 : RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {} 687 688 bool IsUninitializedTypes() const OVERRIDE; 689 bool IsNonZeroReferenceTypes() const OVERRIDE; 690 GetAllocationPc()691 uint32_t GetAllocationPc() const { 692 DCHECK(IsUninitializedTypes()); 693 return allocation_pc_; 694 } 695 696 private: 697 const uint32_t allocation_pc_; 698 }; 699 700 // Similar to ReferenceType but not yet having been passed to a constructor. 701 class UninitializedReferenceType FINAL : public UninitializedType { 702 public: UninitializedReferenceType(mirror::Class * klass,const StringPiece & descriptor,uint32_t allocation_pc,uint16_t cache_id)703 UninitializedReferenceType(mirror::Class* klass, 704 const StringPiece& descriptor, 705 uint32_t allocation_pc, uint16_t cache_id) 706 SHARED_REQUIRES(Locks::mutator_lock_) 707 : UninitializedType(klass, descriptor, allocation_pc, cache_id) {} 708 IsUninitializedReference()709 bool IsUninitializedReference() const OVERRIDE { return true; } 710 HasClassVirtual()711 bool HasClassVirtual() const OVERRIDE { return true; } 712 713 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 714 }; 715 716 // Similar to UnresolvedReferenceType but not yet having been passed to a 717 // constructor. 718 class UnresolvedUninitializedRefType FINAL : public UninitializedType { 719 public: UnresolvedUninitializedRefType(const StringPiece & descriptor,uint32_t allocation_pc,uint16_t cache_id)720 UnresolvedUninitializedRefType(const StringPiece& descriptor, 721 uint32_t allocation_pc, uint16_t cache_id) 722 SHARED_REQUIRES(Locks::mutator_lock_) 723 : UninitializedType(nullptr, descriptor, allocation_pc, cache_id) { 724 if (kIsDebugBuild) { 725 CheckInvariants(); 726 } 727 } 728 IsUnresolvedAndUninitializedReference()729 bool IsUnresolvedAndUninitializedReference() const OVERRIDE { return true; } 730 IsUnresolvedTypes()731 bool IsUnresolvedTypes() const OVERRIDE { return true; } 732 733 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 734 735 private: 736 void CheckInvariants() const SHARED_REQUIRES(Locks::mutator_lock_); 737 }; 738 739 // Similar to UninitializedReferenceType but special case for the this argument 740 // of a constructor. 741 class UninitializedThisReferenceType FINAL : public UninitializedType { 742 public: UninitializedThisReferenceType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)743 UninitializedThisReferenceType(mirror::Class* klass, 744 const StringPiece& descriptor, 745 uint16_t cache_id) 746 SHARED_REQUIRES(Locks::mutator_lock_) 747 : UninitializedType(klass, descriptor, 0, cache_id) { 748 if (kIsDebugBuild) { 749 CheckInvariants(); 750 } 751 } 752 IsUninitializedThisReference()753 virtual bool IsUninitializedThisReference() const OVERRIDE { return true; } 754 HasClassVirtual()755 bool HasClassVirtual() const OVERRIDE { return true; } 756 757 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 758 759 private: 760 void CheckInvariants() const SHARED_REQUIRES(Locks::mutator_lock_); 761 }; 762 763 class UnresolvedUninitializedThisRefType FINAL : public UninitializedType { 764 public: UnresolvedUninitializedThisRefType(const StringPiece & descriptor,uint16_t cache_id)765 UnresolvedUninitializedThisRefType(const StringPiece& descriptor, 766 uint16_t cache_id) 767 SHARED_REQUIRES(Locks::mutator_lock_) 768 : UninitializedType(nullptr, descriptor, 0, cache_id) { 769 if (kIsDebugBuild) { 770 CheckInvariants(); 771 } 772 } 773 IsUnresolvedAndUninitializedThisReference()774 bool IsUnresolvedAndUninitializedThisReference() const OVERRIDE { return true; } 775 IsUnresolvedTypes()776 bool IsUnresolvedTypes() const OVERRIDE { return true; } 777 778 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 779 780 private: 781 void CheckInvariants() const SHARED_REQUIRES(Locks::mutator_lock_); 782 }; 783 784 // A type of register holding a reference to an Object of type GetClass or a 785 // sub-class. 786 class ReferenceType FINAL : public RegType { 787 public: ReferenceType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)788 ReferenceType(mirror::Class* klass, const StringPiece& descriptor, 789 uint16_t cache_id) SHARED_REQUIRES(Locks::mutator_lock_) 790 : RegType(klass, descriptor, cache_id) {} 791 IsReference()792 bool IsReference() const OVERRIDE { return true; } 793 IsNonZeroReferenceTypes()794 bool IsNonZeroReferenceTypes() const OVERRIDE { return true; } 795 HasClassVirtual()796 bool HasClassVirtual() const OVERRIDE { return true; } 797 798 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 799 }; 800 801 // A type of register holding a reference to an Object of type GetClass and only 802 // an object of that 803 // type. 804 class PreciseReferenceType FINAL : public RegType { 805 public: 806 PreciseReferenceType(mirror::Class* klass, const StringPiece& descriptor, 807 uint16_t cache_id) 808 SHARED_REQUIRES(Locks::mutator_lock_); 809 IsPreciseReference()810 bool IsPreciseReference() const OVERRIDE { return true; } 811 IsNonZeroReferenceTypes()812 bool IsNonZeroReferenceTypes() const OVERRIDE { return true; } 813 HasClassVirtual()814 bool HasClassVirtual() const OVERRIDE { return true; } 815 816 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 817 }; 818 819 // Common parent of unresolved types. 820 class UnresolvedType : public RegType { 821 public: UnresolvedType(const StringPiece & descriptor,uint16_t cache_id)822 UnresolvedType(const StringPiece& descriptor, uint16_t cache_id) 823 SHARED_REQUIRES(Locks::mutator_lock_) 824 : RegType(nullptr, descriptor, cache_id) {} 825 826 bool IsNonZeroReferenceTypes() const OVERRIDE; 827 }; 828 829 // Similar to ReferenceType except the Class couldn't be loaded. Assignability 830 // and other tests made 831 // of this type must be conservative. 832 class UnresolvedReferenceType FINAL : public UnresolvedType { 833 public: UnresolvedReferenceType(const StringPiece & descriptor,uint16_t cache_id)834 UnresolvedReferenceType(const StringPiece& descriptor, uint16_t cache_id) 835 SHARED_REQUIRES(Locks::mutator_lock_) 836 : UnresolvedType(descriptor, cache_id) { 837 if (kIsDebugBuild) { 838 CheckInvariants(); 839 } 840 } 841 IsUnresolvedReference()842 bool IsUnresolvedReference() const OVERRIDE { return true; } 843 IsUnresolvedTypes()844 bool IsUnresolvedTypes() const OVERRIDE { return true; } 845 846 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 847 848 private: 849 void CheckInvariants() const SHARED_REQUIRES(Locks::mutator_lock_); 850 }; 851 852 // Type representing the super-class of an unresolved type. 853 class UnresolvedSuperClass FINAL : public UnresolvedType { 854 public: UnresolvedSuperClass(uint16_t child_id,RegTypeCache * reg_type_cache,uint16_t cache_id)855 UnresolvedSuperClass(uint16_t child_id, RegTypeCache* reg_type_cache, 856 uint16_t cache_id) 857 SHARED_REQUIRES(Locks::mutator_lock_) 858 : UnresolvedType("", cache_id), 859 unresolved_child_id_(child_id), 860 reg_type_cache_(reg_type_cache) { 861 if (kIsDebugBuild) { 862 CheckInvariants(); 863 } 864 } 865 IsUnresolvedSuperClass()866 bool IsUnresolvedSuperClass() const OVERRIDE { return true; } 867 IsUnresolvedTypes()868 bool IsUnresolvedTypes() const OVERRIDE { return true; } 869 GetUnresolvedSuperClassChildId()870 uint16_t GetUnresolvedSuperClassChildId() const { 871 DCHECK(IsUnresolvedSuperClass()); 872 return static_cast<uint16_t>(unresolved_child_id_ & 0xFFFF); 873 } 874 875 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 876 877 private: 878 void CheckInvariants() const SHARED_REQUIRES(Locks::mutator_lock_); 879 880 const uint16_t unresolved_child_id_; 881 const RegTypeCache* const reg_type_cache_; 882 }; 883 884 // A merge of unresolved (and resolved) types. If the types were resolved this may be 885 // Conflict or another known ReferenceType. 886 class UnresolvedMergedType FINAL : public UnresolvedType { 887 public: 888 // Note: the constructor will copy the unresolved BitVector, not use it directly. 889 UnresolvedMergedType(const RegType& resolved, 890 const BitVector& unresolved, 891 const RegTypeCache* reg_type_cache, 892 uint16_t cache_id) 893 SHARED_REQUIRES(Locks::mutator_lock_); 894 895 // The resolved part. See description below. GetResolvedPart()896 const RegType& GetResolvedPart() const { 897 return resolved_part_; 898 } 899 // The unresolved part. GetUnresolvedTypes()900 const BitVector& GetUnresolvedTypes() const { 901 return unresolved_types_; 902 } 903 IsUnresolvedMergedReference()904 bool IsUnresolvedMergedReference() const OVERRIDE { return true; } 905 IsUnresolvedTypes()906 bool IsUnresolvedTypes() const OVERRIDE { return true; } 907 908 bool IsArrayTypes() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 909 bool IsObjectArrayTypes() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 910 911 std::string Dump() const OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 912 913 private: 914 void CheckInvariants() const SHARED_REQUIRES(Locks::mutator_lock_); 915 916 const RegTypeCache* const reg_type_cache_; 917 918 // The original implementation of merged types was a binary tree. Collection of the flattened 919 // types ("leaves") can be expensive, so we store the expanded list now, as two components: 920 // 1) A resolved component. We use Zero when there is no resolved component, as that will be 921 // an identity merge. 922 // 2) A bitvector of the unresolved reference types. A bitvector was chosen with the assumption 923 // that there should not be too many types in flight in practice. (We also bias the index 924 // against the index of Zero, which is one of the later default entries in any cache.) 925 const RegType& resolved_part_; 926 const BitVector unresolved_types_; 927 }; 928 929 std::ostream& operator<<(std::ostream& os, const RegType& rhs) 930 SHARED_REQUIRES(Locks::mutator_lock_); 931 932 } // namespace verifier 933 } // namespace art 934 935 #endif // ART_RUNTIME_VERIFIER_REG_TYPE_H_ 936