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