xref: /aosp_15_r20/art/runtime/verifier/reg_type.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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 HIDDEN {
39 namespace verifier {
40 
41 using android::base::StringPrintf;
42 
operator <<(std::ostream & os,RegType::Kind kind)43 std::ostream& operator<<(std::ostream& os, RegType::Kind kind) {
44   const char* kind_name;
45   switch (kind) {
46 #define DEFINE_REG_TYPE_CASE(name) \
47     case RegType::Kind::k##name:   \
48       kind_name = #name;           \
49       break;
50     FOR_EACH_CONCRETE_REG_TYPE(DEFINE_REG_TYPE_CASE)
51 #undef DEFINE_REG_TYPE_CASE
52     default:
53       return os << "Corrupted RegType::Kind: " << static_cast<uint32_t>(kind);
54   }
55   return os << kind_name;
56 }
57 
operator <<(std::ostream & os,RegType::Assignability assignability)58 std::ostream& operator<<(std::ostream& os, RegType::Assignability assignability) {
59   const char* assignability_name;
60   switch (assignability) {
61     case RegType::Assignability::kAssignable:
62       assignability_name = "Assignable";
63       break;
64     case RegType::Assignability::kNotAssignable:
65       assignability_name = "NotAssignable";
66       break;
67     case RegType::Assignability::kNarrowingConversion:
68       assignability_name = "NarrowingConversion";
69       break;
70     case RegType::Assignability::kReference:
71       assignability_name = "Reference";
72       break;
73     case RegType::Assignability::kInvalid:
74       assignability_name = "Invalid";
75       break;
76     default:
77       return os << "Corrupted RegType::Assignability: " << static_cast<uint32_t>(assignability);
78   }
79   return os << assignability_name;
80 }
81 
Dump() const82 std::string RegType::Dump() const {
83   std::string_view reference_tag;
84   switch (GetKind()) {
85     case Kind::kUndefined: return "Undefined";
86     case Kind::kConflict: return "Conflict";
87     case Kind::kBoolean: return "Boolean";
88     case Kind::kByte: return "Byte";
89     case Kind::kShort: return "Short";
90     case Kind::kChar: return "Char";
91     case Kind::kInteger: return "Integer";
92     case Kind::kLongLo: return "Long (Low Half)";
93     case Kind::kLongHi: return "Long (High Half)";
94     case Kind::kFloat: return "Float";
95     case Kind::kDoubleLo: return "Double (Low Half)";
96     case Kind::kDoubleHi: return "Double (High Half)";
97     case Kind::kZero: return "Zero/null";
98     case Kind::kBooleanConstant: return "BooleanConstant";
99     case Kind::kPositiveByteConstant: return "PositiveByteConstant";
100     case Kind::kPositiveShortConstant: return "PositiveShortConstant";
101     case Kind::kCharConstant: return "CharConstant";
102     case Kind::kByteConstant: return "ByteConstant";
103     case Kind::kShortConstant: return "ShortConstant";
104     case Kind::kIntegerConstant: return "IntegerConstant";
105     case Kind::kConstantLo: return "Low-half Constant";
106     case Kind::kConstantHi: return "High-half Constant";
107     case Kind::kNull: return "null";
108     case Kind::kJavaLangObject: return "Reference java.lang.Object";
109 
110     case Kind::kUnresolvedReference:
111       reference_tag = "Unresolved Reference: ";
112       break;
113     case Kind::kUninitializedReference:
114       reference_tag = "Uninitialized Reference: ";
115       break;
116     case Kind::kUninitializedThisReference:
117       reference_tag = "Uninitialized This Reference: ";
118       break;
119     case Kind::kUnresolvedUninitializedReference:
120       reference_tag = "Unresolved And Uninitialized Reference: ";
121       break;
122     case Kind::kUnresolvedUninitializedThisReference:
123       reference_tag = "Unresolved And Uninitialized This Reference: ";
124       break;
125     case Kind::kReference:
126       reference_tag = "Reference: ";
127       break;
128 
129     case Kind::kUnresolvedMergedReference:
130       return down_cast<const UnresolvedMergedReferenceType&>(*this).DumpImpl();
131   }
132   DCHECK(!reference_tag.empty());
133   std::string result(reference_tag);
134   AppendPrettyDescriptor(std::string(GetDescriptor()).c_str(), &result);
135   return result;
136 }
137 
DumpImpl() const138 std::string UnresolvedMergedReferenceType::DumpImpl() const {
139   std::stringstream result;
140   result << "UnresolvedMergedReferences(" << GetResolvedPart().Dump() << " | ";
141   const BitVector& types = GetUnresolvedTypes();
142 
143   bool first = true;
144   for (uint32_t idx : types.Indexes()) {
145     if (!first) {
146       result << ", ";
147     } else {
148       first = false;
149     }
150     result << reg_type_cache_->GetFromId(idx).Dump();
151   }
152   result << ")";
153   return result.str();
154 }
155 
HighHalf(RegTypeCache * cache) const156 const RegType& RegType::HighHalf(RegTypeCache* cache) const {
157   DCHECK(IsLowHalf());
158   if (IsLongLo()) {
159     return cache->LongHi();
160   } else if (IsDoubleLo()) {
161     return cache->DoubleHi();
162   } else {
163     DCHECK(IsConstantLo());
164     return cache->ConstantHi();
165   }
166 }
167 
GetPrimitiveType() const168 Primitive::Type RegType::GetPrimitiveType() const {
169   if (IsNonZeroReferenceTypes()) {
170     return Primitive::kPrimNot;
171   } else if (IsBooleanTypes()) {
172     return Primitive::kPrimBoolean;
173   } else if (IsByteTypes()) {
174     return Primitive::kPrimByte;
175   } else if (IsShortTypes()) {
176     return Primitive::kPrimShort;
177   } else if (IsCharTypes()) {
178     return Primitive::kPrimChar;
179   } else if (IsFloat()) {
180     return Primitive::kPrimFloat;
181   } else if (IsIntegralTypes()) {
182     return Primitive::kPrimInt;
183   } else if (IsDoubleLo()) {
184     return Primitive::kPrimDouble;
185   } else {
186     DCHECK(IsLongTypes());
187     return Primitive::kPrimLong;
188   }
189 }
190 
IsObjectArrayTypes() const191 bool RegType::IsObjectArrayTypes() const {
192   if (IsUnresolvedMergedReference()) {
193     return down_cast<const UnresolvedMergedReferenceType&>(*this).IsObjectArrayTypesImpl();
194   } else if (IsUnresolvedTypes()) {
195     // Primitive arrays will always resolve.
196     DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
197     return descriptor_[0] == '[';
198   } else if (HasClass()) {
199     ObjPtr<mirror::Class> type = GetClass();
200     return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
201   } else {
202     return false;
203   }
204 }
205 
IsArrayTypes() const206 bool RegType::IsArrayTypes() const {
207   if (IsUnresolvedMergedReference()) {
208     return down_cast<const UnresolvedMergedReferenceType&>(*this).IsArrayTypesImpl();
209   } else if (IsUnresolvedTypes()) {
210     return descriptor_[0] == '[';
211   } else if (HasClass()) {
212     return GetClass()->IsArrayClass();
213   } else {
214     return false;
215   }
216 }
217 
IsJavaLangObjectArray() const218 bool RegType::IsJavaLangObjectArray() const {
219   if (HasClass()) {
220     ObjPtr<mirror::Class> type = GetClass();
221     return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
222   }
223   return false;
224 }
225 
IsInstantiableTypes() const226 bool RegType::IsInstantiableTypes() const {
227   DCHECK(IsJavaLangObject() || IsReference() || IsUnresolvedReference()) << *this;
228   return !IsReference() || GetClass()->IsInstantiable();
229 }
230 
SelectNonConstant(const RegType & a,const RegType & b)231 static constexpr const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
232   return a.IsConstantTypes() ? b : a;
233 }
234 
SelectNonConstant2(const RegType & a,const RegType & b)235 static const RegType& SelectNonConstant2(const RegType& a, const RegType& b) {
236   return a.IsConstantTypes() ? (b.IsZero() ? a : b) : a;
237 }
238 
239 namespace {
240 
241 ObjPtr<mirror::Class> ArrayClassJoin(ObjPtr<mirror::Class> s,
242                                      ObjPtr<mirror::Class> t,
243                                      ClassLinker* class_linker)
244     REQUIRES_SHARED(Locks::mutator_lock_);
245 
246 ObjPtr<mirror::Class> InterfaceClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t)
247     REQUIRES_SHARED(Locks::mutator_lock_);
248 
249 /*
250  * A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is
251  * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of
252  * 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
253  * is the deepest (lowest upper bound) parent of S and T).
254  *
255  * This operation applies for regular classes and arrays, however, for interface types there
256  * needn't be a partial ordering on the types. We could solve the problem of a lack of a partial
257  * order by introducing sets of types, however, the only operation permissible on an interface is
258  * invoke-interface. In the tradition of Java verifiers [1] we defer the verification of interface
259  * types until an invoke-interface call on the interface typed reference at runtime and allow
260  * the perversion of Object being assignable to an interface type (note, however, that we don't
261  * allow assignment of Object or Interface to any concrete class and are therefore type safe).
262  *
263  * Note: This may return null in case of internal errors, e.g., OOME when a new class would have
264  *       to be created but there is no heap space. The exception will stay pending, and it is
265  *       the job of the caller to handle it.
266  *
267  * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
268  */
ClassJoin(ObjPtr<mirror::Class> s,ObjPtr<mirror::Class> t,ClassLinker * class_linker)269 ObjPtr<mirror::Class> ClassJoin(ObjPtr<mirror::Class> s,
270                                 ObjPtr<mirror::Class> t,
271                                 ClassLinker* class_linker)
272     REQUIRES_SHARED(Locks::mutator_lock_) {
273   DCHECK(!s->IsPrimitive()) << s->PrettyClass();
274   DCHECK(!t->IsPrimitive()) << t->PrettyClass();
275   if (s == t) {
276     return s;
277   } else if (s->IsAssignableFrom(t)) {
278     return s;
279   } else if (t->IsAssignableFrom(s)) {
280     return t;
281   } else if (s->IsArrayClass() && t->IsArrayClass()) {
282     return ArrayClassJoin(s, t, class_linker);
283   } else if (s->IsInterface() || t->IsInterface()) {
284     return InterfaceClassJoin(s, t);
285   } else {
286     size_t s_depth = s->Depth();
287     size_t t_depth = t->Depth();
288     // Get s and t to the same depth in the hierarchy
289     if (s_depth > t_depth) {
290       while (s_depth > t_depth) {
291         s = s->GetSuperClass();
292         s_depth--;
293       }
294     } else {
295       while (t_depth > s_depth) {
296         t = t->GetSuperClass();
297         t_depth--;
298       }
299     }
300     // Go up the hierarchy until we get to the common parent
301     while (s != t) {
302       s = s->GetSuperClass();
303       t = t->GetSuperClass();
304     }
305     return s;
306   }
307 }
308 
ArrayClassJoin(ObjPtr<mirror::Class> s,ObjPtr<mirror::Class> t,ClassLinker * class_linker)309 ObjPtr<mirror::Class> ArrayClassJoin(ObjPtr<mirror::Class> s,
310                                      ObjPtr<mirror::Class> t,
311                                      ClassLinker* class_linker) {
312   ObjPtr<mirror::Class> s_ct = s->GetComponentType();
313   ObjPtr<mirror::Class> t_ct = t->GetComponentType();
314   if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
315     // Given the types aren't the same, if either array is of primitive types then the only
316     // common parent is java.lang.Object
317     ObjPtr<mirror::Class> result = s->GetSuperClass();  // short-cut to java.lang.Object
318     DCHECK(result->IsObjectClass());
319     return result;
320   }
321   Thread* self = Thread::Current();
322   ObjPtr<mirror::Class> common_elem = ClassJoin(s_ct, t_ct, class_linker);
323   if (UNLIKELY(common_elem == nullptr)) {
324     self->AssertPendingException();
325     return nullptr;
326   }
327   // Note: The following lookup invalidates existing ObjPtr<>s.
328   ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(self, common_elem);
329   if (UNLIKELY(array_class == nullptr)) {
330     self->AssertPendingException();
331     return nullptr;
332   }
333   return array_class;
334 }
335 
InterfaceClassJoin(ObjPtr<mirror::Class> s,ObjPtr<mirror::Class> t)336 ObjPtr<mirror::Class> InterfaceClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t) {
337   // This is expensive, as we do not have good data structures to do this even halfway
338   // efficiently.
339   //
340   // We're not following JVMS for interface verification (not everything is assignable to an
341   // interface, we trade this for IMT dispatch). We also don't have set types to make up for
342   // it. So we choose one arbitrary common ancestor interface by walking the interface tables
343   // backwards.
344   //
345   // For comparison, runtimes following the JVMS will punt all interface type checking to
346   // runtime.
347   ObjPtr<mirror::IfTable> s_if = s->GetIfTable();
348   int32_t s_if_count = s->GetIfTableCount();
349   ObjPtr<mirror::IfTable> t_if = t->GetIfTable();
350   int32_t t_if_count = t->GetIfTableCount();
351 
352   // Note: we'll be using index == count to stand for the argument itself.
353   for (int32_t s_it = s_if_count; s_it >= 0; --s_it) {
354     ObjPtr<mirror::Class> s_cl = s_it == s_if_count ? s : s_if->GetInterface(s_it);
355     if (!s_cl->IsInterface()) {
356       continue;
357     }
358 
359     for (int32_t t_it = t_if_count; t_it >= 0; --t_it) {
360       ObjPtr<mirror::Class> t_cl = t_it == t_if_count ? t : t_if->GetInterface(t_it);
361       if (!t_cl->IsInterface()) {
362         continue;
363       }
364 
365       if (s_cl == t_cl) {
366         // Found something arbitrary in common.
367         return s_cl;
368       }
369     }
370   }
371 
372   // Return java.lang.Object.
373   ObjPtr<mirror::Class> obj_class = s->IsInterface() ? s->GetSuperClass() : t->GetSuperClass();
374   DCHECK(obj_class->IsObjectClass());
375   return obj_class;
376 }
377 
378 class RegTypeMergeImpl final : public RegType {
379  public:
RegTypeMergeImpl(RegType::Kind kind)380   explicit constexpr RegTypeMergeImpl(RegType::Kind kind)
381       : RegType("", /* unused cache id */ 0, kind) {}
382 
383   constexpr RegType::Kind MergeKind(RegType::Kind incoming_kind) const;
384 };
385 
MergeKind(RegType::Kind incoming_kind) const386 constexpr RegType::Kind RegTypeMergeImpl::MergeKind(RegType::Kind incoming_kind) const {
387   const RegTypeMergeImpl incoming_type(incoming_kind);
388   if (IsUndefined() || incoming_type.IsUndefined()) {
389     // There is a difference between undefined and conflict. Conflicts may be copied around, but
390     // not used. Undefined registers must not be copied. So any merge with undefined should return
391     // undefined.
392     return Kind::kUndefined;
393   } else if (IsConflict() || incoming_type.IsConflict()) {
394     return Kind::kConflict;  // (Conflict MERGE *) or (* MERGE Conflict) => Conflict
395   } else if (IsConstant() && incoming_type.IsConstant()) {
396     // Kind enumerator values within the non-negative and can-be-negative constant groups are
397     // ordered by increasing range, so the type with the higher kind can be used within these
398     // groups as the merged kind and merging across the groups is also quite simple.
399     static_assert(Kind::kZero < Kind::kBooleanConstant);
400     static_assert(Kind::kBooleanConstant < Kind::kPositiveByteConstant);
401     static_assert(Kind::kPositiveByteConstant < Kind::kPositiveShortConstant);
402     static_assert(Kind::kPositiveShortConstant < Kind::kCharConstant);
403     static_assert(Kind::kByteConstant < Kind::kShortConstant);
404     static_assert(Kind::kShortConstant < Kind::kIntegerConstant);
405 
406     auto is_non_negative = [](const RegType& reg_type) constexpr {
407       bool result = reg_type.IsZero() ||
408                     reg_type.IsBooleanConstant() ||
409                     reg_type.IsPositiveByteConstant() ||
410                     reg_type.IsPositiveShortConstant() ||
411                     reg_type.IsCharConstant();
412       DCHECK_NE(
413           result,
414           reg_type.IsByteConstant() || reg_type.IsShortConstant() || reg_type.IsIntegerConstant());
415       return result;
416     };
417 
418     bool is_non_negative_this = is_non_negative(*this);
419     if (is_non_negative_this == is_non_negative(incoming_type)) {
420       return GetKind() >= incoming_type.GetKind() ? GetKind() : incoming_type.GetKind();
421     }
422     Kind non_negative_kind = is_non_negative_this ? GetKind() : incoming_type.GetKind();
423     Kind can_be_negative_kind = is_non_negative_this ? incoming_type.GetKind() : GetKind();
424     if (can_be_negative_kind == Kind::kByteConstant &&
425         non_negative_kind <= Kind::kPositiveByteConstant) {
426       return Kind::kByteConstant;
427     } else if (can_be_negative_kind <= Kind::kShortConstant &&
428                non_negative_kind <= Kind::kPositiveShortConstant) {
429       return Kind::kShortConstant;
430     } else {
431       return Kind::kIntegerConstant;
432     }
433   } else if ((IsConstantLo() && incoming_type.IsConstantLo()) ||
434              (IsConstantHi() && incoming_type.IsConstantHi())) {
435     return GetKind();
436   } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
437     if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
438       return Kind::kBoolean;  // boolean MERGE boolean => boolean
439     }
440     if (IsByteTypes() && incoming_type.IsByteTypes()) {
441       return Kind::kByte;  // byte MERGE byte => byte
442     }
443     if (IsShortTypes() && incoming_type.IsShortTypes()) {
444       return Kind::kShort;  // short MERGE short => short
445     }
446     if (IsCharTypes() && incoming_type.IsCharTypes()) {
447       return Kind::kChar;  // char MERGE char => char
448     }
449     return Kind::kInteger;  // int MERGE * => int
450   } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
451              (IsLongTypes() && incoming_type.IsLongTypes()) ||
452              (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
453              (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
454              (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
455     // check constant case was handled prior to entry
456     DCHECK_IMPLIES(IsConstant(), !incoming_type.IsConstant());
457     // float/long/double MERGE float/long/double_constant => float/long/double
458     return SelectNonConstant(*this, incoming_type).GetKind();
459   } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
460     if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
461       // Something that is uninitialized hasn't had its constructor called. Unitialized types are
462       // special. They may only ever be merged with themselves (must be taken care of by the
463       // caller of Merge(), see the DCHECK on entry). So mark any other merge as conflicting here.
464       return Kind::kConflict;
465     } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
466       return Kind::kJavaLangObject;
467     } else {
468       // Use `UnresolvedMergedReference` to tell the caller to process a reference merge.
469       // This does not mean that the actual merged kind must be `UnresolvedMergedReference`.
470       return Kind::kUnresolvedMergedReference;
471     }
472   } else {
473     return Kind::kConflict;  // Unexpected types => Conflict
474   }
475 }
476 
477 }  // namespace
478 
Merge(const RegType & incoming_type,RegTypeCache * reg_types,MethodVerifier * verifier) const479 const RegType& RegType::Merge(const RegType& incoming_type,
480                               RegTypeCache* reg_types,
481                               MethodVerifier* verifier) const {
482   DCHECK(!Equals(incoming_type));  // Trivial equality handled by caller
483 
484   static constexpr size_t kNumKinds = NumberOfKinds();
485   using MergeTable = std::array<std::array<Kind, kNumKinds>, kNumKinds>;
486   static constexpr MergeTable kMergeTable = []() constexpr {
487     MergeTable result;
488     for (size_t lhs = 0u; lhs != kNumKinds; ++lhs) {
489       for (size_t rhs = 0u; rhs != kNumKinds; ++rhs) {
490         RegTypeMergeImpl lhs_impl(enum_cast<RegType::Kind>(lhs));
491         result[lhs][rhs] = lhs_impl.MergeKind(enum_cast<RegType::Kind>(rhs));
492       }
493     }
494     return result;
495   }();
496 
497   Kind merge_kind = kMergeTable[GetKind()][incoming_type.GetKind()];
498   if (merge_kind != Kind::kUnresolvedMergedReference) {
499     return reg_types->GetFromRegKind(merge_kind);
500   } else {
501     // The `UnresolvedMergedReference` tells us to do non-trivial reference merging which
502     // requires more information than the two kinds used for the lookup in `kMergeTable`.
503     DCHECK(IsReferenceTypes()) << *this;
504     DCHECK(incoming_type.IsReferenceTypes()) << incoming_type;
505     DCHECK(!IsUninitializedTypes()) << *this;
506     DCHECK(!incoming_type.IsUninitializedTypes());
507     DCHECK(!IsJavaLangObject());
508     DCHECK(!incoming_type.IsJavaLangObject());
509     if (IsZeroOrNull() || incoming_type.IsZeroOrNull()) {
510       return SelectNonConstant2(*this, incoming_type);  // 0 MERGE ref => ref
511     } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
512       // We know how to merge an unresolved type with itself, 0 or Object. In this case we
513       // have two sub-classes and don't know how to merge. Create a new string-based unresolved
514       // type that reflects our lack of knowledge and that allows the rest of the unresolved
515       // mechanics to continue.
516       return reg_types->FromUnresolvedMerge(*this, incoming_type, verifier);
517     } else {  // Two reference types, compute Join
518       // Do not cache the classes as ClassJoin() can suspend and invalidate ObjPtr<>s.
519       DCHECK(GetClass() != nullptr && !GetClass()->IsPrimitive());
520       DCHECK(incoming_type.GetClass() != nullptr && !incoming_type.GetClass()->IsPrimitive());
521       ObjPtr<mirror::Class> join_class = ClassJoin(GetClass(),
522                                                    incoming_type.GetClass(),
523                                                    reg_types->GetClassLinker());
524       if (UNLIKELY(join_class == nullptr)) {
525         // Internal error joining the classes (e.g., OOME). Report an unresolved reference type.
526         // We cannot report an unresolved merge type, as that will attempt to merge the resolved
527         // components, leaving us in an infinite loop.
528         // We do not want to report the originating exception, as that would require a fast path
529         // out all the way to VerifyClass. Instead attempt to continue on without a detailed type.
530         Thread* self = Thread::Current();
531         self->AssertPendingException();
532         self->ClearException();
533 
534         // When compiling on the host, we rather want to abort to ensure determinism for preopting.
535         // (In that case, it is likely a misconfiguration of dex2oat.)
536         if (!kIsTargetBuild && (verifier != nullptr && verifier->IsAotMode())) {
537           LOG(FATAL) << "Could not create class join of "
538                      << GetClass()->PrettyClass()
539                      << " & "
540                      << incoming_type.GetClass()->PrettyClass();
541           UNREACHABLE();
542         }
543 
544         return reg_types->MakeUnresolvedReference();
545       }
546 
547       // Record the dependency that both `GetClass()` and `incoming_type.GetClass()`
548       // are assignable to `join_class`. The `verifier` is null during unit tests.
549       if (verifier != nullptr) {
550         VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
551                                                verifier->GetDexFile(),
552                                                verifier->GetClassDef(),
553                                                join_class,
554                                                GetClass());
555         VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
556                                                verifier->GetDexFile(),
557                                                verifier->GetClassDef(),
558                                                join_class,
559                                                incoming_type.GetClass());
560       }
561       if (GetClass() == join_class) {
562         return *this;
563       } else if (incoming_type.GetClass() == join_class) {
564         return incoming_type;
565       } else {
566         return reg_types->FromClass(join_class);
567       }
568     }
569   }
570 }
571 
CheckClassDescriptor() const572 void ReferenceType::CheckClassDescriptor() const {
573   CHECK(IsReference());
574   CHECK(!klass_.IsNull());
575   CHECK(!descriptor_.empty()) << *this;
576   std::string temp;
577   CHECK_EQ(descriptor_, klass_->GetDescriptor(&temp)) << *this;
578 }
579 
UnresolvedMergedReferenceType(const RegType & resolved,const BitVector & unresolved,const RegTypeCache * reg_type_cache,uint16_t cache_id)580 UnresolvedMergedReferenceType::UnresolvedMergedReferenceType(const RegType& resolved,
581                                                              const BitVector& unresolved,
582                                                              const RegTypeCache* reg_type_cache,
583                                                              uint16_t cache_id)
584     : UnresolvedType("", cache_id, Kind::kUnresolvedMergedReference),
585       reg_type_cache_(reg_type_cache),
586       resolved_part_(resolved),
587       unresolved_types_(unresolved, false, unresolved.GetAllocator()) {
588   CheckConstructorInvariants(this);
589   if (kIsDebugBuild) {
590     CheckInvariants();
591   }
592 }
593 
CheckInvariants() const594 void UnresolvedMergedReferenceType::CheckInvariants() const {
595   CHECK(reg_type_cache_ != nullptr);
596 
597   // Unresolved merged types: merged types should be defined.
598   CHECK(descriptor_.empty()) << *this;
599   CHECK(!HasClass()) << *this;
600 
601   CHECK(!resolved_part_.IsConflict());
602   CHECK(resolved_part_.IsReferenceTypes());
603   CHECK(!resolved_part_.IsUnresolvedTypes());
604 
605   CHECK(resolved_part_.IsZero() ||
606         !(resolved_part_.IsArrayTypes() && !resolved_part_.IsObjectArrayTypes()));
607 
608   CHECK_GT(unresolved_types_.NumSetBits(), 0U);
609   bool unresolved_is_array =
610       reg_type_cache_->GetFromId(unresolved_types_.GetHighestBitSet()).IsArrayTypes();
611   for (uint32_t idx : unresolved_types_.Indexes()) {
612     const RegType& t = reg_type_cache_->GetFromId(idx);
613     CHECK_EQ(unresolved_is_array, t.IsArrayTypes());
614   }
615 
616   if (!resolved_part_.IsZero()) {
617     CHECK_EQ(resolved_part_.IsArrayTypes(), unresolved_is_array);
618   }
619 }
620 
IsArrayTypesImpl() const621 bool UnresolvedMergedReferenceType::IsArrayTypesImpl() const {
622   // For a merge to be an array, both the resolved and the unresolved part need to be object
623   // arrays.
624   // (Note: we encode a missing resolved part [which doesn't need to be an array] as zero.)
625 
626   if (!resolved_part_.IsZero() && !resolved_part_.IsArrayTypes()) {
627     return false;
628   }
629 
630   // It is enough to check just one of the merged types. Otherwise the merge should have been
631   // collapsed (checked in CheckInvariants on construction).
632   uint32_t idx = unresolved_types_.GetHighestBitSet();
633   const RegType& unresolved = reg_type_cache_->GetFromId(idx);
634   return unresolved.IsArrayTypes();
635 }
IsObjectArrayTypesImpl() const636 bool UnresolvedMergedReferenceType::IsObjectArrayTypesImpl() const {
637   // Same as IsArrayTypes, as primitive arrays are always resolved.
638   return IsArrayTypes();
639 }
640 
operator <<(std::ostream & os,const RegType & rhs)641 std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
642   os << rhs.Dump();
643   return os;
644 }
645 
646 }  // namespace verifier
647 }  // namespace art
648