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