• 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 "android-base/stringprintf.h"
20 
21 #include "base/arena_bit_vector.h"
22 #include "base/bit_vector-inl.h"
23 #include "base/casts.h"
24 #include "class_linker-inl.h"
25 #include "dex/descriptors_names.h"
26 #include "dex/dex_file-inl.h"
27 #include "method_verifier.h"
28 #include "mirror/class-inl.h"
29 #include "mirror/class.h"
30 #include "mirror/object-inl.h"
31 #include "mirror/object_array-inl.h"
32 #include "reg_type_cache-inl.h"
33 #include "scoped_thread_state_change-inl.h"
34 
35 #include <limits>
36 #include <sstream>
37 
38 namespace art {
39 namespace verifier {
40 
41 using android::base::StringPrintf;
42 
43 const UndefinedType* UndefinedType::instance_ = nullptr;
44 const ConflictType* ConflictType::instance_ = nullptr;
45 const BooleanType* BooleanType::instance_ = nullptr;
46 const ByteType* ByteType::instance_ = nullptr;
47 const ShortType* ShortType::instance_ = nullptr;
48 const CharType* CharType::instance_ = nullptr;
49 const FloatType* FloatType::instance_ = nullptr;
50 const LongLoType* LongLoType::instance_ = nullptr;
51 const LongHiType* LongHiType::instance_ = nullptr;
52 const DoubleLoType* DoubleLoType::instance_ = nullptr;
53 const DoubleHiType* DoubleHiType::instance_ = nullptr;
54 const IntegerType* IntegerType::instance_ = nullptr;
55 const NullType* NullType::instance_ = nullptr;
56 
PrimitiveType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)57 PrimitiveType::PrimitiveType(ObjPtr<mirror::Class> klass,
58                              const std::string_view& descriptor,
59                              uint16_t cache_id)
60     : RegType(klass, descriptor, cache_id) {
61   CHECK(klass != nullptr);
62   CHECK(!descriptor.empty());
63 }
64 
Cat1Type(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)65 Cat1Type::Cat1Type(ObjPtr<mirror::Class> klass,
66                    const std::string_view& descriptor,
67                    uint16_t cache_id)
68     : PrimitiveType(klass, descriptor, cache_id) {
69 }
70 
Cat2Type(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)71 Cat2Type::Cat2Type(ObjPtr<mirror::Class> klass,
72                    const std::string_view& descriptor,
73                    uint16_t cache_id)
74     : PrimitiveType(klass, descriptor, cache_id) {
75 }
76 
Dump() const77 std::string PreciseConstType::Dump() const {
78   std::stringstream result;
79   uint32_t val = ConstantValue();
80   if (val == 0) {
81     CHECK(IsPreciseConstant());
82     result << "Zero/null";
83   } else {
84     result << "Precise ";
85     if (IsConstantShort()) {
86       result << StringPrintf("Constant: %d", val);
87     } else {
88       result << StringPrintf("Constant: 0x%x", val);
89     }
90   }
91   return result.str();
92 }
93 
Dump() const94 std::string BooleanType::Dump() const {
95   return "Boolean";
96 }
97 
Dump() const98 std::string ConflictType::Dump() const {
99     return "Conflict";
100 }
101 
Dump() const102 std::string ByteType::Dump() const {
103   return "Byte";
104 }
105 
Dump() const106 std::string ShortType::Dump() const {
107   return "Short";
108 }
109 
Dump() const110 std::string CharType::Dump() const {
111   return "Char";
112 }
113 
Dump() const114 std::string FloatType::Dump() const {
115   return "Float";
116 }
117 
Dump() const118 std::string LongLoType::Dump() const {
119   return "Long (Low Half)";
120 }
121 
Dump() const122 std::string LongHiType::Dump() const {
123   return "Long (High Half)";
124 }
125 
Dump() const126 std::string DoubleLoType::Dump() const {
127   return "Double (Low Half)";
128 }
129 
Dump() const130 std::string DoubleHiType::Dump() const {
131   return "Double (High Half)";
132 }
133 
Dump() const134 std::string IntegerType::Dump() const {
135   return "Integer";
136 }
137 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)138 const DoubleHiType* DoubleHiType::CreateInstance(ObjPtr<mirror::Class> klass,
139                                                  const std::string_view& descriptor,
140                                                  uint16_t cache_id) {
141   CHECK(instance_ == nullptr);
142   instance_ = new DoubleHiType(klass, descriptor, cache_id);
143   return instance_;
144 }
145 
Destroy()146 void DoubleHiType::Destroy() {
147   if (instance_ != nullptr) {
148     delete instance_;
149     instance_ = nullptr;
150   }
151 }
152 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)153 const DoubleLoType* DoubleLoType::CreateInstance(ObjPtr<mirror::Class> klass,
154                                                  const std::string_view& descriptor,
155                                                  uint16_t cache_id) {
156   CHECK(instance_ == nullptr);
157   instance_ = new DoubleLoType(klass, descriptor, cache_id);
158   return instance_;
159 }
160 
Destroy()161 void DoubleLoType::Destroy() {
162   if (instance_ != nullptr) {
163     delete instance_;
164     instance_ = nullptr;
165   }
166 }
167 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)168 const LongLoType* LongLoType::CreateInstance(ObjPtr<mirror::Class> klass,
169                                              const std::string_view& descriptor,
170                                              uint16_t cache_id) {
171   CHECK(instance_ == nullptr);
172   instance_ = new LongLoType(klass, descriptor, cache_id);
173   return instance_;
174 }
175 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)176 const LongHiType* LongHiType::CreateInstance(ObjPtr<mirror::Class> klass,
177                                              const std::string_view& descriptor,
178                                              uint16_t cache_id) {
179   CHECK(instance_ == nullptr);
180   instance_ = new LongHiType(klass, descriptor, cache_id);
181   return instance_;
182 }
183 
Destroy()184 void LongHiType::Destroy() {
185   if (instance_ != nullptr) {
186     delete instance_;
187     instance_ = nullptr;
188   }
189 }
190 
Destroy()191 void LongLoType::Destroy() {
192   if (instance_ != nullptr) {
193     delete instance_;
194     instance_ = nullptr;
195   }
196 }
197 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)198 const FloatType* FloatType::CreateInstance(ObjPtr<mirror::Class> klass,
199                                            const std::string_view& descriptor,
200                                            uint16_t cache_id) {
201   CHECK(instance_ == nullptr);
202   instance_ = new FloatType(klass, descriptor, cache_id);
203   return instance_;
204 }
205 
Destroy()206 void FloatType::Destroy() {
207   if (instance_ != nullptr) {
208     delete instance_;
209     instance_ = nullptr;
210   }
211 }
212 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)213 const CharType* CharType::CreateInstance(ObjPtr<mirror::Class> klass,
214                                          const std::string_view& descriptor,
215                                          uint16_t cache_id) {
216   CHECK(instance_ == nullptr);
217   instance_ = new CharType(klass, descriptor, cache_id);
218   return instance_;
219 }
220 
Destroy()221 void CharType::Destroy() {
222   if (instance_ != nullptr) {
223     delete instance_;
224     instance_ = nullptr;
225   }
226 }
227 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)228 const ShortType* ShortType::CreateInstance(ObjPtr<mirror::Class> klass,
229                                            const std::string_view& descriptor,
230                                            uint16_t cache_id) {
231   CHECK(instance_ == nullptr);
232   instance_ = new ShortType(klass, descriptor, cache_id);
233   return instance_;
234 }
235 
Destroy()236 void ShortType::Destroy() {
237   if (instance_ != nullptr) {
238     delete instance_;
239     instance_ = nullptr;
240   }
241 }
242 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)243 const ByteType* ByteType::CreateInstance(ObjPtr<mirror::Class> klass,
244                                          const std::string_view& descriptor,
245                                          uint16_t cache_id) {
246   CHECK(instance_ == nullptr);
247   instance_ = new ByteType(klass, descriptor, cache_id);
248   return instance_;
249 }
250 
Destroy()251 void ByteType::Destroy() {
252   if (instance_ != nullptr) {
253     delete instance_;
254     instance_ = nullptr;
255   }
256 }
257 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)258 const IntegerType* IntegerType::CreateInstance(ObjPtr<mirror::Class> klass,
259                                                const std::string_view& descriptor,
260                                                uint16_t cache_id) {
261   CHECK(instance_ == nullptr);
262   instance_ = new IntegerType(klass, descriptor, cache_id);
263   return instance_;
264 }
265 
Destroy()266 void IntegerType::Destroy() {
267   if (instance_ != nullptr) {
268     delete instance_;
269     instance_ = nullptr;
270   }
271 }
272 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)273 const ConflictType* ConflictType::CreateInstance(ObjPtr<mirror::Class> klass,
274                                                  const std::string_view& descriptor,
275                                                  uint16_t cache_id) {
276   CHECK(instance_ == nullptr);
277   instance_ = new ConflictType(klass, descriptor, cache_id);
278   return instance_;
279 }
280 
Destroy()281 void ConflictType::Destroy() {
282   if (instance_ != nullptr) {
283     delete instance_;
284     instance_ = nullptr;
285   }
286 }
287 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)288 const BooleanType* BooleanType::CreateInstance(ObjPtr<mirror::Class> klass,
289                                                const std::string_view& descriptor,
290                                                uint16_t cache_id) {
291   CHECK(BooleanType::instance_ == nullptr);
292   instance_ = new BooleanType(klass, descriptor, cache_id);
293   return BooleanType::instance_;
294 }
295 
Destroy()296 void BooleanType::Destroy() {
297   if (BooleanType::instance_ != nullptr) {
298     delete instance_;
299     instance_ = nullptr;
300   }
301 }
302 
Dump() const303 std::string UndefinedType::Dump() const REQUIRES_SHARED(Locks::mutator_lock_) {
304   return "Undefined";
305 }
306 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)307 const UndefinedType* UndefinedType::CreateInstance(ObjPtr<mirror::Class> klass,
308                                                    const std::string_view& descriptor,
309                                                    uint16_t cache_id) {
310   CHECK(instance_ == nullptr);
311   instance_ = new UndefinedType(klass, descriptor, cache_id);
312   return instance_;
313 }
314 
Destroy()315 void UndefinedType::Destroy() {
316   if (instance_ != nullptr) {
317     delete instance_;
318     instance_ = nullptr;
319   }
320 }
321 
PreciseReferenceType(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)322 PreciseReferenceType::PreciseReferenceType(ObjPtr<mirror::Class> klass,
323                                            const std::string_view& descriptor,
324                                            uint16_t cache_id)
325     : RegType(klass, descriptor, cache_id) {
326   // Note: no check for IsInstantiable() here. We may produce this in case an InstantiationError
327   //       would be thrown at runtime, but we need to continue verification and *not* create a
328   //       hard failure or abort.
329   CheckConstructorInvariants(this);
330 }
331 
Dump() const332 std::string UnresolvedMergedType::Dump() const {
333   std::stringstream result;
334   result << "UnresolvedMergedReferences(" << GetResolvedPart().Dump() << " | ";
335   const BitVector& types = GetUnresolvedTypes();
336 
337   bool first = true;
338   for (uint32_t idx : types.Indexes()) {
339     if (!first) {
340       result << ", ";
341     } else {
342       first = false;
343     }
344     result << reg_type_cache_->GetFromId(idx).Dump();
345   }
346   result << ")";
347   return result.str();
348 }
349 
Dump() const350 std::string UnresolvedSuperClass::Dump() const {
351   std::stringstream result;
352   uint16_t super_type_id = GetUnresolvedSuperClassChildId();
353   result << "UnresolvedSuperClass(" << reg_type_cache_->GetFromId(super_type_id).Dump() << ")";
354   return result.str();
355 }
356 
Dump() const357 std::string UnresolvedReferenceType::Dump() const {
358   std::stringstream result;
359   result << "Unresolved Reference: " << PrettyDescriptor(std::string(GetDescriptor()).c_str());
360   return result.str();
361 }
362 
Dump() const363 std::string UnresolvedUninitializedRefType::Dump() const {
364   std::stringstream result;
365   result << "Unresolved And Uninitialized Reference: "
366       << PrettyDescriptor(std::string(GetDescriptor()).c_str())
367       << " Allocation PC: " << GetAllocationPc();
368   return result.str();
369 }
370 
Dump() const371 std::string UnresolvedUninitializedThisRefType::Dump() const {
372   std::stringstream result;
373   result << "Unresolved And Uninitialized This Reference: "
374       << PrettyDescriptor(std::string(GetDescriptor()).c_str());
375   return result.str();
376 }
377 
Dump() const378 std::string ReferenceType::Dump() const {
379   std::stringstream result;
380   result << "Reference: " << mirror::Class::PrettyDescriptor(GetClass());
381   return result.str();
382 }
383 
Dump() const384 std::string PreciseReferenceType::Dump() const {
385   std::stringstream result;
386   result << "Precise Reference: " << mirror::Class::PrettyDescriptor(GetClass());
387   return result.str();
388 }
389 
Dump() const390 std::string UninitializedReferenceType::Dump() const {
391   std::stringstream result;
392   result << "Uninitialized Reference: " << mirror::Class::PrettyDescriptor(GetClass());
393   result << " Allocation PC: " << GetAllocationPc();
394   return result.str();
395 }
396 
Dump() const397 std::string UninitializedThisReferenceType::Dump() const {
398   std::stringstream result;
399   result << "Uninitialized This Reference: " << mirror::Class::PrettyDescriptor(GetClass());
400   result << "Allocation PC: " << GetAllocationPc();
401   return result.str();
402 }
403 
Dump() const404 std::string ImpreciseConstType::Dump() const {
405   std::stringstream result;
406   uint32_t val = ConstantValue();
407   if (val == 0) {
408     result << "Zero/null";
409   } else {
410     result << "Imprecise ";
411     if (IsConstantShort()) {
412       result << StringPrintf("Constant: %d", val);
413     } else {
414       result << StringPrintf("Constant: 0x%x", val);
415     }
416   }
417   return result.str();
418 }
Dump() const419 std::string PreciseConstLoType::Dump() const {
420   std::stringstream result;
421 
422   int32_t val = ConstantValueLo();
423   result << "Precise ";
424   if (val >= std::numeric_limits<jshort>::min() &&
425       val <= std::numeric_limits<jshort>::max()) {
426     result << StringPrintf("Low-half Constant: %d", val);
427   } else {
428     result << StringPrintf("Low-half Constant: 0x%x", val);
429   }
430   return result.str();
431 }
432 
Dump() const433 std::string ImpreciseConstLoType::Dump() const {
434   std::stringstream result;
435 
436   int32_t val = ConstantValueLo();
437   result << "Imprecise ";
438   if (val >= std::numeric_limits<jshort>::min() &&
439       val <= std::numeric_limits<jshort>::max()) {
440     result << StringPrintf("Low-half Constant: %d", val);
441   } else {
442     result << StringPrintf("Low-half Constant: 0x%x", val);
443   }
444   return result.str();
445 }
446 
Dump() const447 std::string PreciseConstHiType::Dump() const {
448   std::stringstream result;
449   int32_t val = ConstantValueHi();
450   result << "Precise ";
451   if (val >= std::numeric_limits<jshort>::min() &&
452       val <= std::numeric_limits<jshort>::max()) {
453     result << StringPrintf("High-half Constant: %d", val);
454   } else {
455     result << StringPrintf("High-half Constant: 0x%x", val);
456   }
457   return result.str();
458 }
459 
Dump() const460 std::string ImpreciseConstHiType::Dump() const {
461   std::stringstream result;
462   int32_t val = ConstantValueHi();
463   result << "Imprecise ";
464   if (val >= std::numeric_limits<jshort>::min() &&
465       val <= std::numeric_limits<jshort>::max()) {
466     result << StringPrintf("High-half Constant: %d", val);
467   } else {
468     result << StringPrintf("High-half Constant: 0x%x", val);
469   }
470   return result.str();
471 }
472 
HighHalf(RegTypeCache * cache) const473 const RegType& RegType::HighHalf(RegTypeCache* cache) const {
474   DCHECK(IsLowHalf());
475   if (IsLongLo()) {
476     return cache->LongHi();
477   } else if (IsDoubleLo()) {
478     return cache->DoubleHi();
479   } else {
480     DCHECK(IsImpreciseConstantLo());
481     const ConstantType* const_val = down_cast<const ConstantType*>(this);
482     return cache->FromCat2ConstHi(const_val->ConstantValue(), false);
483   }
484 }
485 
GetPrimitiveType() const486 Primitive::Type RegType::GetPrimitiveType() const {
487   if (IsNonZeroReferenceTypes()) {
488     return Primitive::kPrimNot;
489   } else if (IsBooleanTypes()) {
490     return Primitive::kPrimBoolean;
491   } else if (IsByteTypes()) {
492     return Primitive::kPrimByte;
493   } else if (IsShortTypes()) {
494     return Primitive::kPrimShort;
495   } else if (IsCharTypes()) {
496     return Primitive::kPrimChar;
497   } else if (IsFloat()) {
498     return Primitive::kPrimFloat;
499   } else if (IsIntegralTypes()) {
500     return Primitive::kPrimInt;
501   } else if (IsDoubleLo()) {
502     return Primitive::kPrimDouble;
503   } else {
504     DCHECK(IsLongTypes());
505     return Primitive::kPrimLong;
506   }
507 }
508 
IsUninitializedTypes() const509 bool UninitializedType::IsUninitializedTypes() const {
510   return true;
511 }
512 
IsNonZeroReferenceTypes() const513 bool UninitializedType::IsNonZeroReferenceTypes() const {
514   return true;
515 }
516 
IsNonZeroReferenceTypes() const517 bool UnresolvedType::IsNonZeroReferenceTypes() const {
518   return true;
519 }
520 
GetSuperClass(RegTypeCache * cache) const521 const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
522   if (!IsUnresolvedTypes()) {
523     ObjPtr<mirror::Class> super_klass = GetClass()->GetSuperClass();
524     if (super_klass != nullptr) {
525       // A super class of a precise type isn't precise as a precise type indicates the register
526       // holds exactly that type.
527       std::string temp;
528       return cache->FromClass(super_klass->GetDescriptor(&temp), super_klass, false);
529     } else {
530       return cache->Zero();
531     }
532   } else {
533     if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
534         GetDescriptor()[0] == '[') {
535       // Super class of all arrays is Object.
536       return cache->JavaLangObject(true);
537     } else {
538       return cache->FromUnresolvedSuperClass(*this);
539     }
540   }
541 }
542 
IsJavaLangObject() const543 bool RegType::IsJavaLangObject() const REQUIRES_SHARED(Locks::mutator_lock_) {
544   return IsReference() && GetClass()->IsObjectClass();
545 }
546 
IsObjectArrayTypes() const547 bool RegType::IsObjectArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_) {
548   if (IsUnresolvedTypes()) {
549     DCHECK(!IsUnresolvedMergedReference());
550 
551     if (IsUnresolvedSuperClass()) {
552       // Cannot be an array, as the superclass of arrays is java.lang.Object (which cannot be
553       // unresolved).
554       return false;
555     }
556 
557     // Primitive arrays will always resolve.
558     DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
559     return descriptor_[0] == '[';
560   } else if (HasClass()) {
561     ObjPtr<mirror::Class> type = GetClass();
562     return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
563   } else {
564     return false;
565   }
566 }
567 
IsArrayTypes() const568 bool RegType::IsArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_) {
569   if (IsUnresolvedTypes()) {
570     DCHECK(!IsUnresolvedMergedReference());
571 
572     if (IsUnresolvedSuperClass()) {
573       // Cannot be an array, as the superclass of arrays is java.lang.Object (which cannot be
574       // unresolved).
575       return false;
576     }
577     return descriptor_[0] == '[';
578   } else if (HasClass()) {
579     return GetClass()->IsArrayClass();
580   } else {
581     return false;
582   }
583 }
584 
IsJavaLangObjectArray() const585 bool RegType::IsJavaLangObjectArray() const {
586   if (HasClass()) {
587     ObjPtr<mirror::Class> type = GetClass();
588     return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
589   }
590   return false;
591 }
592 
IsInstantiableTypes() const593 bool RegType::IsInstantiableTypes() const {
594   return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
595 }
596 
SelectNonConstant(const RegType & a,const RegType & b)597 static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
598   return a.IsConstantTypes() ? b : a;
599 }
600 
SelectNonConstant2(const RegType & a,const RegType & b)601 static const RegType& SelectNonConstant2(const RegType& a, const RegType& b) {
602   return a.IsConstantTypes() ? (b.IsZero() ? a : b) : a;
603 }
604 
Merge(const RegType & incoming_type,RegTypeCache * reg_types,MethodVerifier * verifier) const605 const RegType& RegType::Merge(const RegType& incoming_type,
606                               RegTypeCache* reg_types,
607                               MethodVerifier* verifier) const {
608   DCHECK(!Equals(incoming_type));  // Trivial equality handled by caller
609   // Perform pointer equality tests for undefined and conflict to avoid virtual method dispatch.
610   const UndefinedType& undefined = reg_types->Undefined();
611   const ConflictType& conflict = reg_types->Conflict();
612   DCHECK_EQ(this == &undefined, IsUndefined());
613   DCHECK_EQ(&incoming_type == &undefined, incoming_type.IsUndefined());
614   DCHECK_EQ(this == &conflict, IsConflict());
615   DCHECK_EQ(&incoming_type == &conflict, incoming_type.IsConflict());
616   if (this == &undefined || &incoming_type == &undefined) {
617     // There is a difference between undefined and conflict. Conflicts may be copied around, but
618     // not used. Undefined registers must not be copied. So any merge with undefined should return
619     // undefined.
620     return undefined;
621   } else if (this == &conflict || &incoming_type == &conflict) {
622     return conflict;  // (Conflict MERGE *) or (* MERGE Conflict) => Conflict
623   } else if (IsConstant() && incoming_type.IsConstant()) {
624     const ConstantType& type1 = *down_cast<const ConstantType*>(this);
625     const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
626     int32_t val1 = type1.ConstantValue();
627     int32_t val2 = type2.ConstantValue();
628     if (val1 >= 0 && val2 >= 0) {
629       // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
630       if (val1 >= val2) {
631         if (!type1.IsPreciseConstant()) {
632           return *this;
633         } else {
634           return reg_types->FromCat1Const(val1, false);
635         }
636       } else {
637         if (!type2.IsPreciseConstant()) {
638           return type2;
639         } else {
640           return reg_types->FromCat1Const(val2, false);
641         }
642       }
643     } else if (val1 < 0 && val2 < 0) {
644       // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
645       if (val1 <= val2) {
646         if (!type1.IsPreciseConstant()) {
647           return *this;
648         } else {
649           return reg_types->FromCat1Const(val1, false);
650         }
651       } else {
652         if (!type2.IsPreciseConstant()) {
653           return type2;
654         } else {
655           return reg_types->FromCat1Const(val2, false);
656         }
657       }
658     } else {
659       // Values are +ve and -ve, choose smallest signed type in which they both fit
660       if (type1.IsConstantByte()) {
661         if (type2.IsConstantByte()) {
662           return reg_types->ByteConstant();
663         } else if (type2.IsConstantShort()) {
664           return reg_types->ShortConstant();
665         } else {
666           return reg_types->IntConstant();
667         }
668       } else if (type1.IsConstantShort()) {
669         if (type2.IsConstantShort()) {
670           return reg_types->ShortConstant();
671         } else {
672           return reg_types->IntConstant();
673         }
674       } else {
675         return reg_types->IntConstant();
676       }
677     }
678   } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
679     const ConstantType& type1 = *down_cast<const ConstantType*>(this);
680     const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
681     int32_t val1 = type1.ConstantValueLo();
682     int32_t val2 = type2.ConstantValueLo();
683     return reg_types->FromCat2ConstLo(val1 | val2, false);
684   } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
685     const ConstantType& type1 = *down_cast<const ConstantType*>(this);
686     const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
687     int32_t val1 = type1.ConstantValueHi();
688     int32_t val2 = type2.ConstantValueHi();
689     return reg_types->FromCat2ConstHi(val1 | val2, false);
690   } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
691     if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
692       return reg_types->Boolean();  // boolean MERGE boolean => boolean
693     }
694     if (IsByteTypes() && incoming_type.IsByteTypes()) {
695       return reg_types->Byte();  // byte MERGE byte => byte
696     }
697     if (IsShortTypes() && incoming_type.IsShortTypes()) {
698       return reg_types->Short();  // short MERGE short => short
699     }
700     if (IsCharTypes() && incoming_type.IsCharTypes()) {
701       return reg_types->Char();  // char MERGE char => char
702     }
703     return reg_types->Integer();  // int MERGE * => int
704   } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
705              (IsLongTypes() && incoming_type.IsLongTypes()) ||
706              (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
707              (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
708              (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
709     // check constant case was handled prior to entry
710     DCHECK(!IsConstant() || !incoming_type.IsConstant());
711     // float/long/double MERGE float/long/double_constant => float/long/double
712     return SelectNonConstant(*this, incoming_type);
713   } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
714     if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
715       // Something that is uninitialized hasn't had its constructor called. Unitialized types are
716       // special. They may only ever be merged with themselves (must be taken care of by the
717       // caller of Merge(), see the DCHECK on entry). So mark any other merge as conflicting here.
718       return conflict;
719     } else if (IsZeroOrNull() || incoming_type.IsZeroOrNull()) {
720       return SelectNonConstant2(*this, incoming_type);  // 0 MERGE ref => ref
721     } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
722       return reg_types->JavaLangObject(false);  // Object MERGE ref => Object
723     } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
724       // We know how to merge an unresolved type with itself, 0 or Object. In this case we
725       // have two sub-classes and don't know how to merge. Create a new string-based unresolved
726       // type that reflects our lack of knowledge and that allows the rest of the unresolved
727       // mechanics to continue.
728       return reg_types->FromUnresolvedMerge(*this, incoming_type, verifier);
729     } else {  // Two reference types, compute Join
730       // Do not cache the classes as ClassJoin() can suspend and invalidate ObjPtr<>s.
731       DCHECK(GetClass() != nullptr && !GetClass()->IsPrimitive());
732       DCHECK(incoming_type.GetClass() != nullptr && !incoming_type.GetClass()->IsPrimitive());
733       ObjPtr<mirror::Class> join_class = ClassJoin(GetClass(), incoming_type.GetClass());
734       if (UNLIKELY(join_class == nullptr)) {
735         // Internal error joining the classes (e.g., OOME). Report an unresolved reference type.
736         // We cannot report an unresolved merge type, as that will attempt to merge the resolved
737         // components, leaving us in an infinite loop.
738         // We do not want to report the originating exception, as that would require a fast path
739         // out all the way to VerifyClass. Instead attempt to continue on without a detailed type.
740         Thread* self = Thread::Current();
741         self->AssertPendingException();
742         self->ClearException();
743 
744         // When compiling on the host, we rather want to abort to ensure determinism for preopting.
745         // (In that case, it is likely a misconfiguration of dex2oat.)
746         if (!kIsTargetBuild && Runtime::Current()->IsAotCompiler()) {
747           LOG(FATAL) << "Could not create class join of "
748                      << GetClass()->PrettyClass()
749                      << " & "
750                      << incoming_type.GetClass()->PrettyClass();
751           UNREACHABLE();
752         }
753 
754         return reg_types->MakeUnresolvedReference();
755       }
756 
757       // Record the dependency that both `GetClass()` and `incoming_type.GetClass()`
758       // are assignable to `join_class`. The `verifier` is null during unit tests.
759       if (verifier != nullptr) {
760         VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
761                                                join_class,
762                                                GetClass(),
763                                                /* is_strict= */ true,
764                                                /* is_assignable= */ true);
765         VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
766                                                join_class,
767                                                incoming_type.GetClass(),
768                                                /* is_strict= */ true,
769                                                /* is_assignable= */ true);
770       }
771       if (GetClass() == join_class && !IsPreciseReference()) {
772         return *this;
773       } else if (incoming_type.GetClass() == join_class && !incoming_type.IsPreciseReference()) {
774         return incoming_type;
775       } else {
776         std::string temp;
777         const char* descriptor = join_class->GetDescriptor(&temp);
778         return reg_types->FromClass(descriptor, join_class, /* precise= */ false);
779       }
780     }
781   } else {
782     return conflict;  // Unexpected types => Conflict
783   }
784 }
785 
786 // See comment in reg_type.h
ClassJoin(ObjPtr<mirror::Class> s,ObjPtr<mirror::Class> t)787 ObjPtr<mirror::Class> RegType::ClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t) {
788   DCHECK(!s->IsPrimitive()) << s->PrettyClass();
789   DCHECK(!t->IsPrimitive()) << t->PrettyClass();
790   if (s == t) {
791     return s;
792   } else if (s->IsAssignableFrom(t)) {
793     return s;
794   } else if (t->IsAssignableFrom(s)) {
795     return t;
796   } else if (s->IsArrayClass() && t->IsArrayClass()) {
797     ObjPtr<mirror::Class> s_ct = s->GetComponentType();
798     ObjPtr<mirror::Class> t_ct = t->GetComponentType();
799     if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
800       // Given the types aren't the same, if either array is of primitive types then the only
801       // common parent is java.lang.Object
802       ObjPtr<mirror::Class> result = s->GetSuperClass();  // short-cut to java.lang.Object
803       DCHECK(result->IsObjectClass());
804       return result;
805     }
806     Thread* self = Thread::Current();
807     ObjPtr<mirror::Class> common_elem = ClassJoin(s_ct, t_ct);
808     if (UNLIKELY(common_elem == nullptr)) {
809       self->AssertPendingException();
810       return nullptr;
811     }
812     // Note: The following lookup invalidates existing ObjPtr<>s.
813     ObjPtr<mirror::Class> array_class =
814         Runtime::Current()->GetClassLinker()->FindArrayClass(self, common_elem);
815     if (UNLIKELY(array_class == nullptr)) {
816       self->AssertPendingException();
817       return nullptr;
818     }
819     return array_class;
820   } else {
821     size_t s_depth = s->Depth();
822     size_t t_depth = t->Depth();
823     // Get s and t to the same depth in the hierarchy
824     if (s_depth > t_depth) {
825       while (s_depth > t_depth) {
826         s = s->GetSuperClass();
827         s_depth--;
828       }
829     } else {
830       while (t_depth > s_depth) {
831         t = t->GetSuperClass();
832         t_depth--;
833       }
834     }
835     // Go up the hierarchy until we get to the common parent
836     while (s != t) {
837       s = s->GetSuperClass();
838       t = t->GetSuperClass();
839     }
840     return s;
841   }
842 }
843 
CheckInvariants() const844 void RegType::CheckInvariants() const {
845   if (IsConstant() || IsConstantLo() || IsConstantHi()) {
846     CHECK(descriptor_.empty()) << *this;
847     CHECK(klass_.IsNull()) << *this;
848   }
849   if (!klass_.IsNull()) {
850     CHECK(!descriptor_.empty()) << *this;
851     std::string temp;
852     CHECK_EQ(descriptor_, klass_.Read()->GetDescriptor(&temp)) << *this;
853   }
854 }
855 
VisitRoots(RootVisitor * visitor,const RootInfo & root_info) const856 void RegType::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const {
857   klass_.VisitRootIfNonNull(visitor, root_info);
858 }
859 
CheckInvariants() const860 void UninitializedThisReferenceType::CheckInvariants() const {
861   CHECK_EQ(GetAllocationPc(), 0U) << *this;
862 }
863 
CheckInvariants() const864 void UnresolvedUninitializedThisRefType::CheckInvariants() const {
865   CHECK_EQ(GetAllocationPc(), 0U) << *this;
866   CHECK(!descriptor_.empty()) << *this;
867   CHECK(klass_.IsNull()) << *this;
868 }
869 
CheckInvariants() const870 void UnresolvedUninitializedRefType::CheckInvariants() const {
871   CHECK(!descriptor_.empty()) << *this;
872   CHECK(klass_.IsNull()) << *this;
873 }
874 
UnresolvedMergedType(const RegType & resolved,const BitVector & unresolved,const RegTypeCache * reg_type_cache,uint16_t cache_id)875 UnresolvedMergedType::UnresolvedMergedType(const RegType& resolved,
876                                            const BitVector& unresolved,
877                                            const RegTypeCache* reg_type_cache,
878                                            uint16_t cache_id)
879     : UnresolvedType("", cache_id),
880       reg_type_cache_(reg_type_cache),
881       resolved_part_(resolved),
882       unresolved_types_(unresolved, false, unresolved.GetAllocator()) {
883   CheckConstructorInvariants(this);
884 }
CheckInvariants() const885 void UnresolvedMergedType::CheckInvariants() const {
886   CHECK(reg_type_cache_ != nullptr);
887 
888   // Unresolved merged types: merged types should be defined.
889   CHECK(descriptor_.empty()) << *this;
890   CHECK(klass_.IsNull()) << *this;
891 
892   CHECK(!resolved_part_.IsConflict());
893   CHECK(resolved_part_.IsReferenceTypes());
894   CHECK(!resolved_part_.IsUnresolvedTypes());
895 
896   CHECK(resolved_part_.IsZero() ||
897         !(resolved_part_.IsArrayTypes() && !resolved_part_.IsObjectArrayTypes()));
898 
899   CHECK_GT(unresolved_types_.NumSetBits(), 0U);
900   bool unresolved_is_array =
901       reg_type_cache_->GetFromId(unresolved_types_.GetHighestBitSet()).IsArrayTypes();
902   for (uint32_t idx : unresolved_types_.Indexes()) {
903     const RegType& t = reg_type_cache_->GetFromId(idx);
904     CHECK_EQ(unresolved_is_array, t.IsArrayTypes());
905   }
906 
907   if (!resolved_part_.IsZero()) {
908     CHECK_EQ(resolved_part_.IsArrayTypes(), unresolved_is_array);
909   }
910 }
911 
IsArrayTypes() const912 bool UnresolvedMergedType::IsArrayTypes() const {
913   // For a merge to be an array, both the resolved and the unresolved part need to be object
914   // arrays.
915   // (Note: we encode a missing resolved part [which doesn't need to be an array] as zero.)
916 
917   if (!resolved_part_.IsZero() && !resolved_part_.IsArrayTypes()) {
918     return false;
919   }
920 
921   // It is enough to check just one of the merged types. Otherwise the merge should have been
922   // collapsed (checked in CheckInvariants on construction).
923   uint32_t idx = unresolved_types_.GetHighestBitSet();
924   const RegType& unresolved = reg_type_cache_->GetFromId(idx);
925   return unresolved.IsArrayTypes();
926 }
IsObjectArrayTypes() const927 bool UnresolvedMergedType::IsObjectArrayTypes() const {
928   // Same as IsArrayTypes, as primitive arrays are always resolved.
929   return IsArrayTypes();
930 }
931 
CheckInvariants() const932 void UnresolvedReferenceType::CheckInvariants() const {
933   CHECK(!descriptor_.empty()) << *this;
934   CHECK(klass_.IsNull()) << *this;
935 }
936 
CheckInvariants() const937 void UnresolvedSuperClass::CheckInvariants() const {
938   // Unresolved merged types: merged types should be defined.
939   CHECK(descriptor_.empty()) << *this;
940   CHECK(klass_.IsNull()) << *this;
941   CHECK_NE(unresolved_child_id_, 0U) << *this;
942 }
943 
operator <<(std::ostream & os,const RegType & rhs)944 std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
945   os << rhs.Dump();
946   return os;
947 }
948 
CanAssignArray(const RegType & src,RegTypeCache & reg_types,Handle<mirror::ClassLoader> class_loader,MethodVerifier * verifier,bool * soft_error) const949 bool RegType::CanAssignArray(const RegType& src,
950                              RegTypeCache& reg_types,
951                              Handle<mirror::ClassLoader> class_loader,
952                              MethodVerifier* verifier,
953                              bool* soft_error) const {
954   if (!IsArrayTypes() || !src.IsArrayTypes()) {
955     *soft_error = false;
956     return false;
957   }
958 
959   if (IsUnresolvedMergedReference() || src.IsUnresolvedMergedReference()) {
960     // An unresolved array type means that it's an array of some reference type. Reference arrays
961     // can never be assigned to primitive-type arrays, and vice versa. So it is a soft error if
962     // both arrays are reference arrays, otherwise a hard error.
963     *soft_error = IsObjectArrayTypes() && src.IsObjectArrayTypes();
964     return false;
965   }
966 
967   const RegType& cmp1 = reg_types.GetComponentType(*this, class_loader.Get());
968   const RegType& cmp2 = reg_types.GetComponentType(src, class_loader.Get());
969 
970   if (cmp1.IsAssignableFrom(cmp2, verifier)) {
971     return true;
972   }
973   if (cmp1.IsUnresolvedTypes()) {
974     if (cmp2.IsIntegralTypes() || cmp2.IsFloatTypes() || cmp2.IsArrayTypes()) {
975       *soft_error = false;
976       return false;
977     }
978     *soft_error = true;
979     return false;
980   }
981   if (cmp2.IsUnresolvedTypes()) {
982     if (cmp1.IsIntegralTypes() || cmp1.IsFloatTypes() || cmp1.IsArrayTypes()) {
983       *soft_error = false;
984       return false;
985     }
986     *soft_error = true;
987     return false;
988   }
989   if (!cmp1.IsArrayTypes() || !cmp2.IsArrayTypes()) {
990     *soft_error = false;
991     return false;
992   }
993   return cmp1.CanAssignArray(cmp2, reg_types, class_loader, verifier, soft_error);
994 }
995 
CreateInstance(ObjPtr<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)996 const NullType* NullType::CreateInstance(ObjPtr<mirror::Class> klass,
997                                          const std::string_view& descriptor,
998                                          uint16_t cache_id) {
999   CHECK(instance_ == nullptr);
1000   instance_ = new NullType(klass, descriptor, cache_id);
1001   return instance_;
1002 }
1003 
Destroy()1004 void NullType::Destroy() {
1005   if (NullType::instance_ != nullptr) {
1006     delete instance_;
1007     instance_ = nullptr;
1008   }
1009 }
1010 
1011 
1012 }  // namespace verifier
1013 }  // namespace art
1014