• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "reg_type-inl.h"
18 
19 #include "base/bit_vector-inl.h"
20 #include "base/casts.h"
21 #include "class_linker-inl.h"
22 #include "dex_file-inl.h"
23 #include "mirror/class.h"
24 #include "mirror/class-inl.h"
25 #include "mirror/object-inl.h"
26 #include "mirror/object_array-inl.h"
27 #include "reg_type_cache-inl.h"
28 #include "scoped_thread_state_change.h"
29 
30 #include <limits>
31 #include <sstream>
32 
33 namespace art {
34 namespace verifier {
35 
36 const UndefinedType* UndefinedType::instance_ = nullptr;
37 const ConflictType* ConflictType::instance_ = nullptr;
38 const BooleanType* BooleanType::instance_ = nullptr;
39 const ByteType* ByteType::instance_ = nullptr;
40 const ShortType* ShortType::instance_ = nullptr;
41 const CharType* CharType::instance_ = nullptr;
42 const FloatType* FloatType::instance_ = nullptr;
43 const LongLoType* LongLoType::instance_ = nullptr;
44 const LongHiType* LongHiType::instance_ = nullptr;
45 const DoubleLoType* DoubleLoType::instance_ = nullptr;
46 const DoubleHiType* DoubleHiType::instance_ = nullptr;
47 const IntegerType* IntegerType::instance_ = nullptr;
48 
PrimitiveType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)49 PrimitiveType::PrimitiveType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
50     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
51     : RegType(klass, descriptor, cache_id) {
52   CHECK(klass != nullptr);
53   CHECK(!descriptor.empty());
54 }
55 
Cat1Type(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)56 Cat1Type::Cat1Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
57     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
58     : PrimitiveType(klass, descriptor, cache_id) {
59 }
60 
Cat2Type(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)61 Cat2Type::Cat2Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
62     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
63     : PrimitiveType(klass, descriptor, cache_id) {
64 }
65 
Dump() const66 std::string PreciseConstType::Dump() const {
67   std::stringstream result;
68   uint32_t val = ConstantValue();
69   if (val == 0) {
70     CHECK(IsPreciseConstant());
71     result << "Zero/null";
72   } else {
73     result << "Precise ";
74     if (IsConstantShort()) {
75       result << StringPrintf("Constant: %d", val);
76     } else {
77       result << StringPrintf("Constant: 0x%x", val);
78     }
79   }
80   return result.str();
81 }
82 
Dump() const83 std::string BooleanType::Dump() const {
84   return "Boolean";
85 }
86 
Dump() const87 std::string ConflictType::Dump() const {
88     return "Conflict";
89 }
90 
Dump() const91 std::string ByteType::Dump() const {
92   return "Byte";
93 }
94 
Dump() const95 std::string ShortType::Dump() const {
96   return "Short";
97 }
98 
Dump() const99 std::string CharType::Dump() const {
100   return "Char";
101 }
102 
Dump() const103 std::string FloatType::Dump() const {
104   return "Float";
105 }
106 
Dump() const107 std::string LongLoType::Dump() const {
108   return "Long (Low Half)";
109 }
110 
Dump() const111 std::string LongHiType::Dump() const {
112   return "Long (High Half)";
113 }
114 
Dump() const115 std::string DoubleLoType::Dump() const {
116   return "Double (Low Half)";
117 }
118 
Dump() const119 std::string DoubleHiType::Dump() const {
120   return "Double (High Half)";
121 }
122 
Dump() const123 std::string IntegerType::Dump() const {
124     return "Integer";
125 }
126 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)127 const DoubleHiType* DoubleHiType::CreateInstance(mirror::Class* klass,
128                                                  const std::string& descriptor,
129                                                  uint16_t cache_id) {
130   CHECK(instance_ == nullptr);
131   instance_ = new DoubleHiType(klass, descriptor, cache_id);
132   return instance_;
133 }
134 
Destroy()135 void DoubleHiType::Destroy() {
136   if (instance_ != nullptr) {
137     delete instance_;
138     instance_ = nullptr;
139   }
140 }
141 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)142 const DoubleLoType* DoubleLoType::CreateInstance(mirror::Class* klass,
143                                                  const std::string& descriptor,
144                                                  uint16_t cache_id) {
145   CHECK(instance_ == nullptr);
146   instance_ = new DoubleLoType(klass, descriptor, cache_id);
147   return instance_;
148 }
149 
Destroy()150 void DoubleLoType::Destroy() {
151   if (instance_ != nullptr) {
152     delete instance_;
153     instance_ = nullptr;
154   }
155 }
156 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)157 const LongLoType* LongLoType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
158                                              uint16_t cache_id) {
159   CHECK(instance_ == nullptr);
160   instance_ = new LongLoType(klass, descriptor, cache_id);
161   return instance_;
162 }
163 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)164 const LongHiType* LongHiType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
165                                              uint16_t cache_id) {
166   CHECK(instance_ == nullptr);
167   instance_ = new LongHiType(klass, descriptor, cache_id);
168   return instance_;
169 }
170 
Destroy()171 void LongHiType::Destroy() {
172   if (instance_ != nullptr) {
173     delete instance_;
174     instance_ = nullptr;
175   }
176 }
177 
Destroy()178 void LongLoType::Destroy() {
179   if (instance_ != nullptr) {
180     delete instance_;
181     instance_ = nullptr;
182   }
183 }
184 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)185 const FloatType* FloatType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
186                                            uint16_t cache_id) {
187   CHECK(instance_ == nullptr);
188   instance_ = new FloatType(klass, descriptor, cache_id);
189   return instance_;
190 }
191 
Destroy()192 void FloatType::Destroy() {
193   if (instance_ != nullptr) {
194     delete instance_;
195     instance_ = nullptr;
196   }
197 }
198 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)199 const CharType* CharType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
200                                          uint16_t cache_id) {
201   CHECK(instance_ == nullptr);
202   instance_ = new CharType(klass, descriptor, cache_id);
203   return instance_;
204 }
205 
Destroy()206 void CharType::Destroy() {
207   if (instance_ != nullptr) {
208     delete instance_;
209     instance_ = nullptr;
210   }
211 }
212 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)213 const ShortType* ShortType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
214                                            uint16_t cache_id) {
215   CHECK(instance_ == nullptr);
216   instance_ = new ShortType(klass, descriptor, cache_id);
217   return instance_;
218 }
219 
Destroy()220 void ShortType::Destroy() {
221   if (instance_ != nullptr) {
222     delete instance_;
223     instance_ = nullptr;
224   }
225 }
226 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)227 const ByteType* ByteType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
228                                          uint16_t cache_id) {
229   CHECK(instance_ == nullptr);
230   instance_ = new ByteType(klass, descriptor, cache_id);
231   return instance_;
232 }
233 
Destroy()234 void ByteType::Destroy() {
235   if (instance_ != nullptr) {
236     delete instance_;
237     instance_ = nullptr;
238   }
239 }
240 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)241 const IntegerType* IntegerType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
242                                                uint16_t cache_id) {
243   CHECK(instance_ == nullptr);
244   instance_ = new IntegerType(klass, descriptor, cache_id);
245   return instance_;
246 }
247 
Destroy()248 void IntegerType::Destroy() {
249   if (instance_ != nullptr) {
250     delete instance_;
251     instance_ = nullptr;
252   }
253 }
254 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)255 const ConflictType* ConflictType::CreateInstance(mirror::Class* klass,
256                                                  const std::string& descriptor,
257                                                  uint16_t cache_id) {
258   CHECK(instance_ == nullptr);
259   instance_ = new ConflictType(klass, descriptor, cache_id);
260   return instance_;
261 }
262 
Destroy()263 void ConflictType::Destroy() {
264   if (instance_ != nullptr) {
265     delete instance_;
266     instance_ = nullptr;
267   }
268 }
269 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)270 const BooleanType* BooleanType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
271                                          uint16_t cache_id) {
272   CHECK(BooleanType::instance_ == nullptr);
273   instance_ = new BooleanType(klass, descriptor, cache_id);
274   return BooleanType::instance_;
275 }
276 
Destroy()277 void BooleanType::Destroy() {
278   if (BooleanType::instance_ != nullptr) {
279     delete instance_;
280     instance_ = nullptr;
281   }
282 }
283 
Dump() const284 std::string UndefinedType::Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
285   return "Undefined";
286 }
287 
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)288 const UndefinedType* UndefinedType::CreateInstance(mirror::Class* klass,
289                                                    const std::string& descriptor,
290                                                    uint16_t cache_id) {
291   CHECK(instance_ == nullptr);
292   instance_ = new UndefinedType(klass, descriptor, cache_id);
293   return instance_;
294 }
295 
Destroy()296 void UndefinedType::Destroy() {
297   if (instance_ != nullptr) {
298     delete instance_;
299     instance_ = nullptr;
300   }
301 }
302 
PreciseReferenceType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)303 PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, const std::string& descriptor,
304                                            uint16_t cache_id)
305     : RegType(klass, descriptor, cache_id) {
306   DCHECK(klass->IsInstantiable());
307 }
308 
Dump() const309 std::string UnresolvedMergedType::Dump() const {
310   std::stringstream result;
311   result << "UnresolvedMergedReferences(" << GetResolvedPart().Dump() << " | ";
312   const BitVector& types = GetUnresolvedTypes();
313 
314   bool first = true;
315   for (uint32_t idx : types.Indexes()) {
316     if (!first) {
317       result << ", ";
318     } else {
319       first = false;
320     }
321     result << reg_type_cache_->GetFromId(idx).Dump();
322   }
323   result << ")";
324   return result.str();
325 }
326 
Dump() const327 std::string UnresolvedSuperClass::Dump() const {
328   std::stringstream result;
329   uint16_t super_type_id = GetUnresolvedSuperClassChildId();
330   result << "UnresolvedSuperClass(" << reg_type_cache_->GetFromId(super_type_id).Dump() << ")";
331   return result.str();
332 }
333 
Dump() const334 std::string UnresolvedReferenceType::Dump() const {
335   std::stringstream result;
336   result << "Unresolved Reference" << ": " << PrettyDescriptor(GetDescriptor().c_str());
337   return result.str();
338 }
339 
Dump() const340 std::string UnresolvedUninitializedRefType::Dump() const {
341   std::stringstream result;
342   result << "Unresolved And Uninitialized Reference" << ": "
343       << PrettyDescriptor(GetDescriptor().c_str())
344       << " Allocation PC: " << GetAllocationPc();
345   return result.str();
346 }
347 
Dump() const348 std::string UnresolvedUninitializedThisRefType::Dump() const {
349   std::stringstream result;
350   result << "Unresolved And Uninitialized This Reference"
351       << PrettyDescriptor(GetDescriptor().c_str());
352   return result.str();
353 }
354 
Dump() const355 std::string ReferenceType::Dump() const {
356   std::stringstream result;
357   result << "Reference" << ": " << PrettyDescriptor(GetClass());
358   return result.str();
359 }
360 
Dump() const361 std::string PreciseReferenceType::Dump() const {
362   std::stringstream result;
363   result << "Precise Reference" << ": "<< PrettyDescriptor(GetClass());
364   return result.str();
365 }
366 
Dump() const367 std::string UninitializedReferenceType::Dump() const {
368   std::stringstream result;
369   result << "Uninitialized Reference" << ": " << PrettyDescriptor(GetClass());
370   result << " Allocation PC: " << GetAllocationPc();
371   return result.str();
372 }
373 
Dump() const374 std::string UninitializedThisReferenceType::Dump() const {
375   std::stringstream result;
376   result << "Uninitialized This Reference" << ": " << PrettyDescriptor(GetClass());
377   result << "Allocation PC: " << GetAllocationPc();
378   return result.str();
379 }
380 
Dump() const381 std::string ImpreciseConstType::Dump() const {
382   std::stringstream result;
383   uint32_t val = ConstantValue();
384   if (val == 0) {
385     result << "Zero/null";
386   } else {
387     result << "Imprecise ";
388     if (IsConstantShort()) {
389       result << StringPrintf("Constant: %d", val);
390     } else {
391       result << StringPrintf("Constant: 0x%x", val);
392     }
393   }
394   return result.str();
395 }
Dump() const396 std::string PreciseConstLoType::Dump() const {
397   std::stringstream result;
398 
399   int32_t val = ConstantValueLo();
400   result << "Precise ";
401   if (val >= std::numeric_limits<jshort>::min() &&
402       val <= std::numeric_limits<jshort>::max()) {
403     result << StringPrintf("Low-half Constant: %d", val);
404   } else {
405     result << StringPrintf("Low-half Constant: 0x%x", val);
406   }
407   return result.str();
408 }
409 
Dump() const410 std::string ImpreciseConstLoType::Dump() const {
411   std::stringstream result;
412 
413   int32_t val = ConstantValueLo();
414   result << "Imprecise ";
415   if (val >= std::numeric_limits<jshort>::min() &&
416       val <= std::numeric_limits<jshort>::max()) {
417     result << StringPrintf("Low-half Constant: %d", val);
418   } else {
419     result << StringPrintf("Low-half Constant: 0x%x", val);
420   }
421   return result.str();
422 }
423 
Dump() const424 std::string PreciseConstHiType::Dump() const {
425   std::stringstream result;
426   int32_t val = ConstantValueHi();
427   result << "Precise ";
428   if (val >= std::numeric_limits<jshort>::min() &&
429       val <= std::numeric_limits<jshort>::max()) {
430     result << StringPrintf("High-half Constant: %d", val);
431   } else {
432     result << StringPrintf("High-half Constant: 0x%x", val);
433   }
434   return result.str();
435 }
436 
Dump() const437 std::string ImpreciseConstHiType::Dump() const {
438   std::stringstream result;
439   int32_t val = ConstantValueHi();
440   result << "Imprecise ";
441   if (val >= std::numeric_limits<jshort>::min() &&
442       val <= std::numeric_limits<jshort>::max()) {
443     result << StringPrintf("High-half Constant: %d", val);
444   } else {
445     result << StringPrintf("High-half Constant: 0x%x", val);
446   }
447   return result.str();
448 }
449 
HighHalf(RegTypeCache * cache) const450 const RegType& RegType::HighHalf(RegTypeCache* cache) const {
451   DCHECK(IsLowHalf());
452   if (IsLongLo()) {
453     return cache->LongHi();
454   } else if (IsDoubleLo()) {
455     return cache->DoubleHi();
456   } else {
457     DCHECK(IsImpreciseConstantLo());
458     const ConstantType* const_val = down_cast<const ConstantType*>(this);
459     return cache->FromCat2ConstHi(const_val->ConstantValue(), false);
460   }
461 }
462 
GetPrimitiveType() const463 Primitive::Type RegType::GetPrimitiveType() const {
464   if (IsNonZeroReferenceTypes()) {
465     return Primitive::kPrimNot;
466   } else if (IsBooleanTypes()) {
467     return Primitive::kPrimBoolean;
468   } else if (IsByteTypes()) {
469     return Primitive::kPrimByte;
470   } else if (IsShortTypes()) {
471     return Primitive::kPrimShort;
472   } else if (IsCharTypes()) {
473     return Primitive::kPrimChar;
474   } else if (IsFloat()) {
475     return Primitive::kPrimFloat;
476   } else if (IsIntegralTypes()) {
477     return Primitive::kPrimInt;
478   } else if (IsDoubleLo()) {
479     return Primitive::kPrimDouble;
480   } else {
481     DCHECK(IsLongTypes());
482     return Primitive::kPrimLong;
483   }
484 }
485 
IsUninitializedTypes() const486 bool UninitializedType::IsUninitializedTypes() const {
487   return true;
488 }
489 
IsNonZeroReferenceTypes() const490 bool UninitializedType::IsNonZeroReferenceTypes() const {
491   return true;
492 }
493 
IsNonZeroReferenceTypes() const494 bool UnresolvedType::IsNonZeroReferenceTypes() const {
495   return true;
496 }
497 
GetSuperClass(RegTypeCache * cache) const498 const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
499   if (!IsUnresolvedTypes()) {
500     mirror::Class* super_klass = GetClass()->GetSuperClass();
501     if (super_klass != nullptr) {
502       // A super class of a precise type isn't precise as a precise type indicates the register
503       // holds exactly that type.
504       std::string temp;
505       return cache->FromClass(super_klass->GetDescriptor(&temp), super_klass, false);
506     } else {
507       return cache->Zero();
508     }
509   } else {
510     if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
511         GetDescriptor()[0] == '[') {
512       // Super class of all arrays is Object.
513       return cache->JavaLangObject(true);
514     } else {
515       return cache->FromUnresolvedSuperClass(*this);
516     }
517   }
518 }
519 
IsObjectArrayTypes() const520 bool RegType::IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
521   if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
522     // Primitive arrays will always resolve
523     DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
524     return descriptor_[0] == '[';
525   } else if (HasClass()) {
526     mirror::Class* type = GetClass();
527     return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
528   } else {
529     return false;
530   }
531 }
532 
IsJavaLangObject() const533 bool RegType::IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
534   return IsReference() && GetClass()->IsObjectClass();
535 }
536 
IsArrayTypes() const537 bool RegType::IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
538   if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
539     return descriptor_[0] == '[';
540   } else if (HasClass()) {
541     return GetClass()->IsArrayClass();
542   } else {
543     return false;
544   }
545 }
546 
IsJavaLangObjectArray() const547 bool RegType::IsJavaLangObjectArray() const {
548   if (HasClass()) {
549     mirror::Class* type = GetClass();
550     return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
551   }
552   return false;
553 }
554 
IsInstantiableTypes() const555 bool RegType::IsInstantiableTypes() const {
556   return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
557 }
558 
SelectNonConstant(const RegType & a,const RegType & b)559 static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
560   return a.IsConstantTypes() ? b : a;
561 }
562 
Merge(const RegType & incoming_type,RegTypeCache * reg_types) const563 const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
564   DCHECK(!Equals(incoming_type));  // Trivial equality handled by caller
565   // Perform pointer equality tests for conflict to avoid virtual method dispatch.
566   const ConflictType& conflict = reg_types->Conflict();
567   if (IsUndefined() || incoming_type.IsUndefined()) {
568     // There is a difference between undefined and conflict. Conflicts may be copied around, but
569     // not used. Undefined registers must not be copied. So any merge with undefined should return
570     // undefined.
571     if (IsUndefined()) {
572       return *this;
573     }
574     return incoming_type;
575   } else if (this == &conflict) {
576     DCHECK(IsConflict());
577     return *this;  // Conflict MERGE * => Conflict
578   } else if (&incoming_type == &conflict) {
579     DCHECK(incoming_type.IsConflict());
580     return incoming_type;  // * MERGE Conflict => Conflict
581   } else if (IsUndefined() || incoming_type.IsUndefined()) {
582     return conflict;  // Unknown MERGE * => Conflict
583   } else if (IsConstant() && incoming_type.IsConstant()) {
584     const ConstantType& type1 = *down_cast<const ConstantType*>(this);
585     const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
586     int32_t val1 = type1.ConstantValue();
587     int32_t val2 = type2.ConstantValue();
588     if (val1 >= 0 && val2 >= 0) {
589       // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
590       if (val1 >= val2) {
591         if (!type1.IsPreciseConstant()) {
592           return *this;
593         } else {
594           return reg_types->FromCat1Const(val1, false);
595         }
596       } else {
597         if (!type2.IsPreciseConstant()) {
598           return type2;
599         } else {
600           return reg_types->FromCat1Const(val2, false);
601         }
602       }
603     } else if (val1 < 0 && val2 < 0) {
604       // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
605       if (val1 <= val2) {
606         if (!type1.IsPreciseConstant()) {
607           return *this;
608         } else {
609           return reg_types->FromCat1Const(val1, false);
610         }
611       } else {
612         if (!type2.IsPreciseConstant()) {
613           return type2;
614         } else {
615           return reg_types->FromCat1Const(val2, false);
616         }
617       }
618     } else {
619       // Values are +ve and -ve, choose smallest signed type in which they both fit
620       if (type1.IsConstantByte()) {
621         if (type2.IsConstantByte()) {
622           return reg_types->ByteConstant();
623         } else if (type2.IsConstantShort()) {
624           return reg_types->ShortConstant();
625         } else {
626           return reg_types->IntConstant();
627         }
628       } else if (type1.IsConstantShort()) {
629         if (type2.IsConstantShort()) {
630           return reg_types->ShortConstant();
631         } else {
632           return reg_types->IntConstant();
633         }
634       } else {
635         return reg_types->IntConstant();
636       }
637     }
638   } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
639     const ConstantType& type1 = *down_cast<const ConstantType*>(this);
640     const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
641     int32_t val1 = type1.ConstantValueLo();
642     int32_t val2 = type2.ConstantValueLo();
643     return reg_types->FromCat2ConstLo(val1 | val2, false);
644   } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
645     const ConstantType& type1 = *down_cast<const ConstantType*>(this);
646     const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
647     int32_t val1 = type1.ConstantValueHi();
648     int32_t val2 = type2.ConstantValueHi();
649     return reg_types->FromCat2ConstHi(val1 | val2, false);
650   } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
651     if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
652       return reg_types->Boolean();  // boolean MERGE boolean => boolean
653     }
654     if (IsByteTypes() && incoming_type.IsByteTypes()) {
655       return reg_types->Byte();  // byte MERGE byte => byte
656     }
657     if (IsShortTypes() && incoming_type.IsShortTypes()) {
658       return reg_types->Short();  // short MERGE short => short
659     }
660     if (IsCharTypes() && incoming_type.IsCharTypes()) {
661       return reg_types->Char();  // char MERGE char => char
662     }
663     return reg_types->Integer();  // int MERGE * => int
664   } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
665              (IsLongTypes() && incoming_type.IsLongTypes()) ||
666              (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
667              (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
668              (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
669     // check constant case was handled prior to entry
670     DCHECK(!IsConstant() || !incoming_type.IsConstant());
671     // float/long/double MERGE float/long/double_constant => float/long/double
672     return SelectNonConstant(*this, incoming_type);
673   } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
674     if (IsZero() || incoming_type.IsZero()) {
675       return SelectNonConstant(*this, incoming_type);  // 0 MERGE ref => ref
676     } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
677       return reg_types->JavaLangObject(false);  // Object MERGE ref => Object
678     } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
679       // We know how to merge an unresolved type with itself, 0 or Object. In this case we
680       // have two sub-classes and don't know how to merge. Create a new string-based unresolved
681       // type that reflects our lack of knowledge and that allows the rest of the unresolved
682       // mechanics to continue.
683       return reg_types->FromUnresolvedMerge(*this, incoming_type);
684     } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
685       // Something that is uninitialized hasn't had its constructor called. Mark any merge
686       // of this type with something that is initialized as conflicting. The cases of a merge
687       // with itself, 0 or Object are handled above.
688       return conflict;
689     } else {  // Two reference types, compute Join
690       mirror::Class* c1 = GetClass();
691       mirror::Class* c2 = incoming_type.GetClass();
692       DCHECK(c1 != nullptr && !c1->IsPrimitive());
693       DCHECK(c2 != nullptr && !c2->IsPrimitive());
694       mirror::Class* join_class = ClassJoin(c1, c2);
695       if (c1 == join_class && !IsPreciseReference()) {
696         return *this;
697       } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
698         return incoming_type;
699       } else {
700         std::string temp;
701         return reg_types->FromClass(join_class->GetDescriptor(&temp), join_class, false);
702       }
703     }
704   } else {
705     return conflict;  // Unexpected types => Conflict
706   }
707 }
708 
709 // See comment in reg_type.h
ClassJoin(mirror::Class * s,mirror::Class * t)710 mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
711   DCHECK(!s->IsPrimitive()) << PrettyClass(s);
712   DCHECK(!t->IsPrimitive()) << PrettyClass(t);
713   if (s == t) {
714     return s;
715   } else if (s->IsAssignableFrom(t)) {
716     return s;
717   } else if (t->IsAssignableFrom(s)) {
718     return t;
719   } else if (s->IsArrayClass() && t->IsArrayClass()) {
720     mirror::Class* s_ct = s->GetComponentType();
721     mirror::Class* t_ct = t->GetComponentType();
722     if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
723       // Given the types aren't the same, if either array is of primitive types then the only
724       // common parent is java.lang.Object
725       mirror::Class* result = s->GetSuperClass();  // short-cut to java.lang.Object
726       DCHECK(result->IsObjectClass());
727       return result;
728     }
729     mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
730     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
731     mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), &common_elem);
732     DCHECK(array_class != nullptr);
733     return array_class;
734   } else {
735     size_t s_depth = s->Depth();
736     size_t t_depth = t->Depth();
737     // Get s and t to the same depth in the hierarchy
738     if (s_depth > t_depth) {
739       while (s_depth > t_depth) {
740         s = s->GetSuperClass();
741         s_depth--;
742       }
743     } else {
744       while (t_depth > s_depth) {
745         t = t->GetSuperClass();
746         t_depth--;
747       }
748     }
749     // Go up the hierarchy until we get to the common parent
750     while (s != t) {
751       s = s->GetSuperClass();
752       t = t->GetSuperClass();
753     }
754     return s;
755   }
756 }
757 
CheckInvariants() const758 void RegType::CheckInvariants() const {
759   if (IsConstant() || IsConstantLo() || IsConstantHi()) {
760     CHECK(descriptor_.empty()) << *this;
761     CHECK(klass_.IsNull()) << *this;
762   }
763   if (!klass_.IsNull()) {
764     CHECK(!descriptor_.empty()) << *this;
765   }
766 }
767 
VisitRoots(RootVisitor * visitor,const RootInfo & root_info) const768 void RegType::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const {
769   klass_.VisitRootIfNonNull(visitor, root_info);
770 }
771 
CheckInvariants() const772 void UninitializedThisReferenceType::CheckInvariants() const {
773   CHECK_EQ(GetAllocationPc(), 0U) << *this;
774 }
775 
CheckInvariants() const776 void UnresolvedUninitializedThisRefType::CheckInvariants() const {
777   CHECK_EQ(GetAllocationPc(), 0U) << *this;
778   CHECK(!descriptor_.empty()) << *this;
779   CHECK(klass_.IsNull()) << *this;
780 }
781 
CheckInvariants() const782 void UnresolvedUninitializedRefType::CheckInvariants() const {
783   CHECK(!descriptor_.empty()) << *this;
784   CHECK(klass_.IsNull()) << *this;
785 }
786 
UnresolvedMergedType(const RegType & resolved,const BitVector & unresolved,const RegTypeCache * reg_type_cache,uint16_t cache_id)787 UnresolvedMergedType::UnresolvedMergedType(const RegType& resolved,
788                                            const BitVector& unresolved,
789                                            const RegTypeCache* reg_type_cache,
790                                            uint16_t cache_id)
791     : UnresolvedType("", cache_id),
792       reg_type_cache_(reg_type_cache),
793       resolved_part_(resolved),
794       unresolved_types_(unresolved, false, unresolved.GetAllocator()) {
795   if (kIsDebugBuild) {
796     CheckInvariants();
797   }
798 }
CheckInvariants() const799 void UnresolvedMergedType::CheckInvariants() const {
800   // Unresolved merged types: merged types should be defined.
801   CHECK(descriptor_.empty()) << *this;
802   CHECK(klass_.IsNull()) << *this;
803   CHECK(resolved_part_.IsReferenceTypes());
804   CHECK(!resolved_part_.IsUnresolvedTypes());
805 }
806 
CheckInvariants() const807 void UnresolvedReferenceType::CheckInvariants() const {
808   CHECK(!descriptor_.empty()) << *this;
809   CHECK(klass_.IsNull()) << *this;
810 }
811 
CheckInvariants() const812 void UnresolvedSuperClass::CheckInvariants() const {
813   // Unresolved merged types: merged types should be defined.
814   CHECK(descriptor_.empty()) << *this;
815   CHECK(klass_.IsNull()) << *this;
816   CHECK_NE(unresolved_child_id_, 0U) << *this;
817 }
818 
operator <<(std::ostream & os,const RegType & rhs)819 std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
820   os << rhs.Dump();
821   return os;
822 }
823 
CanAssignArray(const RegType & src,RegTypeCache & reg_types,Handle<mirror::ClassLoader> class_loader,bool * soft_error) const824 bool RegType::CanAssignArray(const RegType& src, RegTypeCache& reg_types,
825                              Handle<mirror::ClassLoader> class_loader, bool* soft_error) const {
826   if (!IsArrayTypes() || !src.IsArrayTypes()) {
827     *soft_error = false;
828     return false;
829   }
830 
831   const RegType& cmp1 = reg_types.GetComponentType(*this, class_loader.Get());
832   const RegType& cmp2 = reg_types.GetComponentType(src, class_loader.Get());
833 
834   if (cmp1.IsAssignableFrom(cmp2)) {
835     return true;
836   }
837   if (cmp1.IsUnresolvedTypes()) {
838     if (cmp2.IsIntegralTypes() || cmp2.IsFloatTypes() || cmp2.IsArrayTypes()) {
839       *soft_error = false;
840       return false;
841     }
842     *soft_error = true;
843     return false;
844   }
845   if (cmp2.IsUnresolvedTypes()) {
846     if (cmp1.IsIntegralTypes() || cmp1.IsFloatTypes() || cmp1.IsArrayTypes()) {
847       *soft_error = false;
848       return false;
849     }
850     *soft_error = true;
851     return false;
852   }
853   if (!cmp1.IsArrayTypes() || !cmp2.IsArrayTypes()) {
854     *soft_error = false;
855     return false;
856   }
857   return cmp1.CanAssignArray(cmp2, reg_types, class_loader, soft_error);
858 }
859 
860 
861 }  // namespace verifier
862 }  // namespace art
863