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
PrimitiveType(Handle<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)43 PrimitiveType::PrimitiveType(Handle<mirror::Class> klass,
44 const std::string_view& descriptor,
45 uint16_t cache_id)
46 : RegType(klass, descriptor, cache_id) {
47 CHECK(klass != nullptr);
48 CHECK(!descriptor.empty());
49 }
50
Cat1Type(Handle<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)51 Cat1Type::Cat1Type(Handle<mirror::Class> klass,
52 const std::string_view& descriptor,
53 uint16_t cache_id)
54 : PrimitiveType(klass, descriptor, cache_id) {
55 }
56
Cat2Type(Handle<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)57 Cat2Type::Cat2Type(Handle<mirror::Class> klass,
58 const std::string_view& descriptor,
59 uint16_t cache_id)
60 : PrimitiveType(klass, descriptor, cache_id) {
61 }
62
Dump() const63 std::string PreciseConstType::Dump() const {
64 std::stringstream result;
65 uint32_t val = ConstantValue();
66 if (val == 0) {
67 CHECK(IsPreciseConstant());
68 result << "Zero/null";
69 } else {
70 result << "Precise ";
71 if (IsConstantShort()) {
72 result << StringPrintf("Constant: %d", val);
73 } else {
74 result << StringPrintf("Constant: 0x%x", val);
75 }
76 }
77 return result.str();
78 }
79
Dump() const80 std::string BooleanType::Dump() const {
81 return "Boolean";
82 }
83
Dump() const84 std::string ConflictType::Dump() const {
85 return "Conflict";
86 }
87
Dump() const88 std::string ByteType::Dump() const {
89 return "Byte";
90 }
91
Dump() const92 std::string ShortType::Dump() const {
93 return "Short";
94 }
95
Dump() const96 std::string CharType::Dump() const {
97 return "Char";
98 }
99
Dump() const100 std::string FloatType::Dump() const {
101 return "Float";
102 }
103
Dump() const104 std::string LongLoType::Dump() const {
105 return "Long (Low Half)";
106 }
107
Dump() const108 std::string LongHiType::Dump() const {
109 return "Long (High Half)";
110 }
111
Dump() const112 std::string DoubleLoType::Dump() const {
113 return "Double (Low Half)";
114 }
115
Dump() const116 std::string DoubleHiType::Dump() const {
117 return "Double (High Half)";
118 }
119
Dump() const120 std::string IntegerType::Dump() const {
121 return "Integer";
122 }
123
Dump() const124 std::string UndefinedType::Dump() const REQUIRES_SHARED(Locks::mutator_lock_) {
125 return "Undefined";
126 }
127
PreciseReferenceType(Handle<mirror::Class> klass,const std::string_view & descriptor,uint16_t cache_id)128 PreciseReferenceType::PreciseReferenceType(Handle<mirror::Class> klass,
129 const std::string_view& descriptor,
130 uint16_t cache_id)
131 : RegType(klass, descriptor, cache_id) {
132 // Note: no check for IsInstantiable() here. We may produce this in case an InstantiationError
133 // would be thrown at runtime, but we need to continue verification and *not* create a
134 // hard failure or abort.
135 CheckConstructorInvariants(this);
136 }
137
Dump() const138 std::string UnresolvedMergedType::Dump() 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
Dump() const156 std::string UnresolvedSuperClass::Dump() const {
157 std::stringstream result;
158 uint16_t super_type_id = GetUnresolvedSuperClassChildId();
159 result << "UnresolvedSuperClass(" << reg_type_cache_->GetFromId(super_type_id).Dump() << ")";
160 return result.str();
161 }
162
Dump() const163 std::string UnresolvedReferenceType::Dump() const {
164 std::stringstream result;
165 result << "Unresolved Reference: " << PrettyDescriptor(std::string(GetDescriptor()).c_str());
166 return result.str();
167 }
168
Dump() const169 std::string UnresolvedUninitializedRefType::Dump() const {
170 std::stringstream result;
171 result << "Unresolved And Uninitialized Reference: "
172 << PrettyDescriptor(std::string(GetDescriptor()).c_str())
173 << " Allocation PC: " << GetAllocationPc();
174 return result.str();
175 }
176
Dump() const177 std::string UnresolvedUninitializedThisRefType::Dump() const {
178 std::stringstream result;
179 result << "Unresolved And Uninitialized This Reference: "
180 << PrettyDescriptor(std::string(GetDescriptor()).c_str());
181 return result.str();
182 }
183
Dump() const184 std::string ReferenceType::Dump() const {
185 std::stringstream result;
186 result << "Reference: " << mirror::Class::PrettyDescriptor(GetClass());
187 return result.str();
188 }
189
Dump() const190 std::string PreciseReferenceType::Dump() const {
191 std::stringstream result;
192 result << "Precise Reference: " << mirror::Class::PrettyDescriptor(GetClass());
193 return result.str();
194 }
195
Dump() const196 std::string UninitializedReferenceType::Dump() const {
197 std::stringstream result;
198 result << "Uninitialized Reference: " << mirror::Class::PrettyDescriptor(GetClass());
199 result << " Allocation PC: " << GetAllocationPc();
200 return result.str();
201 }
202
Dump() const203 std::string UninitializedThisReferenceType::Dump() const {
204 std::stringstream result;
205 result << "Uninitialized This Reference: " << mirror::Class::PrettyDescriptor(GetClass());
206 result << "Allocation PC: " << GetAllocationPc();
207 return result.str();
208 }
209
Dump() const210 std::string ImpreciseConstType::Dump() const {
211 std::stringstream result;
212 uint32_t val = ConstantValue();
213 if (val == 0) {
214 result << "Zero/null";
215 } else {
216 result << "Imprecise ";
217 if (IsConstantShort()) {
218 result << StringPrintf("Constant: %d", val);
219 } else {
220 result << StringPrintf("Constant: 0x%x", val);
221 }
222 }
223 return result.str();
224 }
Dump() const225 std::string PreciseConstLoType::Dump() const {
226 std::stringstream result;
227
228 int32_t val = ConstantValueLo();
229 result << "Precise ";
230 if (val >= std::numeric_limits<jshort>::min() &&
231 val <= std::numeric_limits<jshort>::max()) {
232 result << StringPrintf("Low-half Constant: %d", val);
233 } else {
234 result << StringPrintf("Low-half Constant: 0x%x", val);
235 }
236 return result.str();
237 }
238
Dump() const239 std::string ImpreciseConstLoType::Dump() const {
240 std::stringstream result;
241
242 int32_t val = ConstantValueLo();
243 result << "Imprecise ";
244 if (val >= std::numeric_limits<jshort>::min() &&
245 val <= std::numeric_limits<jshort>::max()) {
246 result << StringPrintf("Low-half Constant: %d", val);
247 } else {
248 result << StringPrintf("Low-half Constant: 0x%x", val);
249 }
250 return result.str();
251 }
252
Dump() const253 std::string PreciseConstHiType::Dump() const {
254 std::stringstream result;
255 int32_t val = ConstantValueHi();
256 result << "Precise ";
257 if (val >= std::numeric_limits<jshort>::min() &&
258 val <= std::numeric_limits<jshort>::max()) {
259 result << StringPrintf("High-half Constant: %d", val);
260 } else {
261 result << StringPrintf("High-half Constant: 0x%x", val);
262 }
263 return result.str();
264 }
265
Dump() const266 std::string ImpreciseConstHiType::Dump() const {
267 std::stringstream result;
268 int32_t val = ConstantValueHi();
269 result << "Imprecise ";
270 if (val >= std::numeric_limits<jshort>::min() &&
271 val <= std::numeric_limits<jshort>::max()) {
272 result << StringPrintf("High-half Constant: %d", val);
273 } else {
274 result << StringPrintf("High-half Constant: 0x%x", val);
275 }
276 return result.str();
277 }
278
HighHalf(RegTypeCache * cache) const279 const RegType& RegType::HighHalf(RegTypeCache* cache) const {
280 DCHECK(IsLowHalf());
281 if (IsLongLo()) {
282 return cache->LongHi();
283 } else if (IsDoubleLo()) {
284 return cache->DoubleHi();
285 } else {
286 DCHECK(IsImpreciseConstantLo());
287 const ConstantType* const_val = down_cast<const ConstantType*>(this);
288 return cache->FromCat2ConstHi(const_val->ConstantValue(), false);
289 }
290 }
291
GetPrimitiveType() const292 Primitive::Type RegType::GetPrimitiveType() const {
293 if (IsNonZeroReferenceTypes()) {
294 return Primitive::kPrimNot;
295 } else if (IsBooleanTypes()) {
296 return Primitive::kPrimBoolean;
297 } else if (IsByteTypes()) {
298 return Primitive::kPrimByte;
299 } else if (IsShortTypes()) {
300 return Primitive::kPrimShort;
301 } else if (IsCharTypes()) {
302 return Primitive::kPrimChar;
303 } else if (IsFloat()) {
304 return Primitive::kPrimFloat;
305 } else if (IsIntegralTypes()) {
306 return Primitive::kPrimInt;
307 } else if (IsDoubleLo()) {
308 return Primitive::kPrimDouble;
309 } else {
310 DCHECK(IsLongTypes());
311 return Primitive::kPrimLong;
312 }
313 }
314
IsUninitializedTypes() const315 bool UninitializedType::IsUninitializedTypes() const {
316 return true;
317 }
318
IsNonZeroReferenceTypes() const319 bool UninitializedType::IsNonZeroReferenceTypes() const {
320 return true;
321 }
322
IsNonZeroReferenceTypes() const323 bool UnresolvedType::IsNonZeroReferenceTypes() const {
324 return true;
325 }
326
GetSuperClass(RegTypeCache * cache) const327 const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
328 if (!IsUnresolvedTypes()) {
329 ObjPtr<mirror::Class> super_klass = GetClass()->GetSuperClass();
330 if (super_klass != nullptr) {
331 // A super class of a precise type isn't precise as a precise type indicates the register
332 // holds exactly that type.
333 std::string temp;
334 return cache->FromClass(super_klass->GetDescriptor(&temp), super_klass, false);
335 } else {
336 return cache->Zero();
337 }
338 } else {
339 if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
340 GetDescriptor()[0] == '[') {
341 // Super class of all arrays is Object.
342 return cache->JavaLangObject(true);
343 } else {
344 return cache->FromUnresolvedSuperClass(*this);
345 }
346 }
347 }
348
IsJavaLangObject() const349 bool RegType::IsJavaLangObject() const REQUIRES_SHARED(Locks::mutator_lock_) {
350 return IsReference() && GetClass()->IsObjectClass();
351 }
352
IsObjectArrayTypes() const353 bool RegType::IsObjectArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_) {
354 if (IsUnresolvedTypes()) {
355 DCHECK(!IsUnresolvedMergedReference());
356
357 if (IsUnresolvedSuperClass()) {
358 // Cannot be an array, as the superclass of arrays is java.lang.Object (which cannot be
359 // unresolved).
360 return false;
361 }
362
363 // Primitive arrays will always resolve.
364 DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
365 return descriptor_[0] == '[';
366 } else if (HasClass()) {
367 ObjPtr<mirror::Class> type = GetClass();
368 return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
369 } else {
370 return false;
371 }
372 }
373
IsArrayTypes() const374 bool RegType::IsArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_) {
375 if (IsUnresolvedTypes()) {
376 DCHECK(!IsUnresolvedMergedReference());
377
378 if (IsUnresolvedSuperClass()) {
379 // Cannot be an array, as the superclass of arrays is java.lang.Object (which cannot be
380 // unresolved).
381 return false;
382 }
383 return descriptor_[0] == '[';
384 } else if (HasClass()) {
385 return GetClass()->IsArrayClass();
386 } else {
387 return false;
388 }
389 }
390
IsJavaLangObjectArray() const391 bool RegType::IsJavaLangObjectArray() const {
392 if (HasClass()) {
393 ObjPtr<mirror::Class> type = GetClass();
394 return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
395 }
396 return false;
397 }
398
IsInstantiableTypes() const399 bool RegType::IsInstantiableTypes() const {
400 return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
401 }
402
SelectNonConstant(const RegType & a,const RegType & b)403 static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
404 return a.IsConstantTypes() ? b : a;
405 }
406
SelectNonConstant2(const RegType & a,const RegType & b)407 static const RegType& SelectNonConstant2(const RegType& a, const RegType& b) {
408 return a.IsConstantTypes() ? (b.IsZero() ? a : b) : a;
409 }
410
411
412 namespace {
413
414 ObjPtr<mirror::Class> ArrayClassJoin(ObjPtr<mirror::Class> s,
415 ObjPtr<mirror::Class> t,
416 ClassLinker* class_linker)
417 REQUIRES_SHARED(Locks::mutator_lock_);
418
419 ObjPtr<mirror::Class> InterfaceClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t)
420 REQUIRES_SHARED(Locks::mutator_lock_);
421
422 /*
423 * A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is
424 * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of
425 * 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
426 * is the deepest (lowest upper bound) parent of S and T).
427 *
428 * This operation applies for regular classes and arrays, however, for interface types there
429 * needn't be a partial ordering on the types. We could solve the problem of a lack of a partial
430 * order by introducing sets of types, however, the only operation permissible on an interface is
431 * invoke-interface. In the tradition of Java verifiers [1] we defer the verification of interface
432 * types until an invoke-interface call on the interface typed reference at runtime and allow
433 * the perversion of Object being assignable to an interface type (note, however, that we don't
434 * allow assignment of Object or Interface to any concrete class and are therefore type safe).
435 *
436 * Note: This may return null in case of internal errors, e.g., OOME when a new class would have
437 * to be created but there is no heap space. The exception will stay pending, and it is
438 * the job of the caller to handle it.
439 *
440 * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
441 */
ClassJoin(ObjPtr<mirror::Class> s,ObjPtr<mirror::Class> t,ClassLinker * class_linker)442 ObjPtr<mirror::Class> ClassJoin(ObjPtr<mirror::Class> s,
443 ObjPtr<mirror::Class> t,
444 ClassLinker* class_linker)
445 REQUIRES_SHARED(Locks::mutator_lock_) {
446 DCHECK(!s->IsPrimitive()) << s->PrettyClass();
447 DCHECK(!t->IsPrimitive()) << t->PrettyClass();
448 if (s == t) {
449 return s;
450 } else if (s->IsAssignableFrom(t)) {
451 return s;
452 } else if (t->IsAssignableFrom(s)) {
453 return t;
454 } else if (s->IsArrayClass() && t->IsArrayClass()) {
455 return ArrayClassJoin(s, t, class_linker);
456 } else if (s->IsInterface() || t->IsInterface()) {
457 return InterfaceClassJoin(s, t);
458 } else {
459 size_t s_depth = s->Depth();
460 size_t t_depth = t->Depth();
461 // Get s and t to the same depth in the hierarchy
462 if (s_depth > t_depth) {
463 while (s_depth > t_depth) {
464 s = s->GetSuperClass();
465 s_depth--;
466 }
467 } else {
468 while (t_depth > s_depth) {
469 t = t->GetSuperClass();
470 t_depth--;
471 }
472 }
473 // Go up the hierarchy until we get to the common parent
474 while (s != t) {
475 s = s->GetSuperClass();
476 t = t->GetSuperClass();
477 }
478 return s;
479 }
480 }
481
ArrayClassJoin(ObjPtr<mirror::Class> s,ObjPtr<mirror::Class> t,ClassLinker * class_linker)482 ObjPtr<mirror::Class> ArrayClassJoin(ObjPtr<mirror::Class> s,
483 ObjPtr<mirror::Class> t,
484 ClassLinker* class_linker) {
485 ObjPtr<mirror::Class> s_ct = s->GetComponentType();
486 ObjPtr<mirror::Class> t_ct = t->GetComponentType();
487 if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
488 // Given the types aren't the same, if either array is of primitive types then the only
489 // common parent is java.lang.Object
490 ObjPtr<mirror::Class> result = s->GetSuperClass(); // short-cut to java.lang.Object
491 DCHECK(result->IsObjectClass());
492 return result;
493 }
494 Thread* self = Thread::Current();
495 ObjPtr<mirror::Class> common_elem = ClassJoin(s_ct, t_ct, class_linker);
496 if (UNLIKELY(common_elem == nullptr)) {
497 self->AssertPendingException();
498 return nullptr;
499 }
500 // Note: The following lookup invalidates existing ObjPtr<>s.
501 ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(self, common_elem);
502 if (UNLIKELY(array_class == nullptr)) {
503 self->AssertPendingException();
504 return nullptr;
505 }
506 return array_class;
507 }
508
InterfaceClassJoin(ObjPtr<mirror::Class> s,ObjPtr<mirror::Class> t)509 ObjPtr<mirror::Class> InterfaceClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t) {
510 // This is expensive, as we do not have good data structures to do this even halfway
511 // efficiently.
512 //
513 // We're not following JVMS for interface verification (not everything is assignable to an
514 // interface, we trade this for IMT dispatch). We also don't have set types to make up for
515 // it. So we choose one arbitrary common ancestor interface by walking the interface tables
516 // backwards.
517 //
518 // For comparison, runtimes following the JVMS will punt all interface type checking to
519 // runtime.
520 ObjPtr<mirror::IfTable> s_if = s->GetIfTable();
521 int32_t s_if_count = s->GetIfTableCount();
522 ObjPtr<mirror::IfTable> t_if = t->GetIfTable();
523 int32_t t_if_count = t->GetIfTableCount();
524
525 // Note: we'll be using index == count to stand for the argument itself.
526 for (int32_t s_it = s_if_count; s_it >= 0; --s_it) {
527 ObjPtr<mirror::Class> s_cl = s_it == s_if_count ? s : s_if->GetInterface(s_it);
528 if (!s_cl->IsInterface()) {
529 continue;
530 }
531
532 for (int32_t t_it = t_if_count; t_it >= 0; --t_it) {
533 ObjPtr<mirror::Class> t_cl = t_it == t_if_count ? t : t_if->GetInterface(t_it);
534 if (!t_cl->IsInterface()) {
535 continue;
536 }
537
538 if (s_cl == t_cl) {
539 // Found something arbitrary in common.
540 return s_cl;
541 }
542 }
543 }
544
545 // Return java.lang.Object.
546 ObjPtr<mirror::Class> obj_class = s->IsInterface() ? s->GetSuperClass() : t->GetSuperClass();
547 DCHECK(obj_class->IsObjectClass());
548 return obj_class;
549 }
550
551 } // namespace
552
Merge(const RegType & incoming_type,RegTypeCache * reg_types,MethodVerifier * verifier) const553 const RegType& RegType::Merge(const RegType& incoming_type,
554 RegTypeCache* reg_types,
555 MethodVerifier* verifier) const {
556 DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller
557 // Perform pointer equality tests for undefined and conflict to avoid virtual method dispatch.
558 const UndefinedType& undefined = reg_types->Undefined();
559 const ConflictType& conflict = reg_types->Conflict();
560 DCHECK_EQ(this == &undefined, IsUndefined());
561 DCHECK_EQ(&incoming_type == &undefined, incoming_type.IsUndefined());
562 DCHECK_EQ(this == &conflict, IsConflict());
563 DCHECK_EQ(&incoming_type == &conflict, incoming_type.IsConflict());
564 if (this == &undefined || &incoming_type == &undefined) {
565 // There is a difference between undefined and conflict. Conflicts may be copied around, but
566 // not used. Undefined registers must not be copied. So any merge with undefined should return
567 // undefined.
568 return undefined;
569 } else if (this == &conflict || &incoming_type == &conflict) {
570 return conflict; // (Conflict MERGE *) or (* MERGE Conflict) => Conflict
571 } else if (IsConstant() && incoming_type.IsConstant()) {
572 const ConstantType& type1 = *down_cast<const ConstantType*>(this);
573 const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
574 int32_t val1 = type1.ConstantValue();
575 int32_t val2 = type2.ConstantValue();
576 if (val1 >= 0 && val2 >= 0) {
577 // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
578 if (val1 >= val2) {
579 if (!type1.IsPreciseConstant()) {
580 return *this;
581 } else {
582 return reg_types->FromCat1Const(val1, false);
583 }
584 } else {
585 if (!type2.IsPreciseConstant()) {
586 return type2;
587 } else {
588 return reg_types->FromCat1Const(val2, false);
589 }
590 }
591 } else if (val1 < 0 && val2 < 0) {
592 // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
593 if (val1 <= val2) {
594 if (!type1.IsPreciseConstant()) {
595 return *this;
596 } else {
597 return reg_types->FromCat1Const(val1, false);
598 }
599 } else {
600 if (!type2.IsPreciseConstant()) {
601 return type2;
602 } else {
603 return reg_types->FromCat1Const(val2, false);
604 }
605 }
606 } else {
607 // Values are +ve and -ve, choose smallest signed type in which they both fit
608 if (type1.IsConstantByte()) {
609 if (type2.IsConstantByte()) {
610 return reg_types->ByteConstant();
611 } else if (type2.IsConstantShort()) {
612 return reg_types->ShortConstant();
613 } else {
614 return reg_types->IntConstant();
615 }
616 } else if (type1.IsConstantShort()) {
617 if (type2.IsConstantShort()) {
618 return reg_types->ShortConstant();
619 } else {
620 return reg_types->IntConstant();
621 }
622 } else {
623 return reg_types->IntConstant();
624 }
625 }
626 } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
627 const ConstantType& type1 = *down_cast<const ConstantType*>(this);
628 const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
629 int32_t val1 = type1.ConstantValueLo();
630 int32_t val2 = type2.ConstantValueLo();
631 return reg_types->FromCat2ConstLo(val1 | val2, false);
632 } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
633 const ConstantType& type1 = *down_cast<const ConstantType*>(this);
634 const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
635 int32_t val1 = type1.ConstantValueHi();
636 int32_t val2 = type2.ConstantValueHi();
637 return reg_types->FromCat2ConstHi(val1 | val2, false);
638 } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
639 if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
640 return reg_types->Boolean(); // boolean MERGE boolean => boolean
641 }
642 if (IsByteTypes() && incoming_type.IsByteTypes()) {
643 return reg_types->Byte(); // byte MERGE byte => byte
644 }
645 if (IsShortTypes() && incoming_type.IsShortTypes()) {
646 return reg_types->Short(); // short MERGE short => short
647 }
648 if (IsCharTypes() && incoming_type.IsCharTypes()) {
649 return reg_types->Char(); // char MERGE char => char
650 }
651 return reg_types->Integer(); // int MERGE * => int
652 } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
653 (IsLongTypes() && incoming_type.IsLongTypes()) ||
654 (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
655 (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
656 (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
657 // check constant case was handled prior to entry
658 DCHECK_IMPLIES(IsConstant(), !incoming_type.IsConstant());
659 // float/long/double MERGE float/long/double_constant => float/long/double
660 return SelectNonConstant(*this, incoming_type);
661 } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
662 if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
663 // Something that is uninitialized hasn't had its constructor called. Unitialized types are
664 // special. They may only ever be merged with themselves (must be taken care of by the
665 // caller of Merge(), see the DCHECK on entry). So mark any other merge as conflicting here.
666 return conflict;
667 } else if (IsZeroOrNull() || incoming_type.IsZeroOrNull()) {
668 return SelectNonConstant2(*this, incoming_type); // 0 MERGE ref => ref
669 } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
670 return reg_types->JavaLangObject(false); // Object MERGE ref => Object
671 } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
672 // We know how to merge an unresolved type with itself, 0 or Object. In this case we
673 // have two sub-classes and don't know how to merge. Create a new string-based unresolved
674 // type that reflects our lack of knowledge and that allows the rest of the unresolved
675 // mechanics to continue.
676 return reg_types->FromUnresolvedMerge(*this, incoming_type, verifier);
677 } else { // Two reference types, compute Join
678 // Do not cache the classes as ClassJoin() can suspend and invalidate ObjPtr<>s.
679 DCHECK(GetClass() != nullptr && !GetClass()->IsPrimitive());
680 DCHECK(incoming_type.GetClass() != nullptr && !incoming_type.GetClass()->IsPrimitive());
681 ObjPtr<mirror::Class> join_class = ClassJoin(GetClass(),
682 incoming_type.GetClass(),
683 reg_types->GetClassLinker());
684 if (UNLIKELY(join_class == nullptr)) {
685 // Internal error joining the classes (e.g., OOME). Report an unresolved reference type.
686 // We cannot report an unresolved merge type, as that will attempt to merge the resolved
687 // components, leaving us in an infinite loop.
688 // We do not want to report the originating exception, as that would require a fast path
689 // out all the way to VerifyClass. Instead attempt to continue on without a detailed type.
690 Thread* self = Thread::Current();
691 self->AssertPendingException();
692 self->ClearException();
693
694 // When compiling on the host, we rather want to abort to ensure determinism for preopting.
695 // (In that case, it is likely a misconfiguration of dex2oat.)
696 if (!kIsTargetBuild && (verifier != nullptr && verifier->IsAotMode())) {
697 LOG(FATAL) << "Could not create class join of "
698 << GetClass()->PrettyClass()
699 << " & "
700 << incoming_type.GetClass()->PrettyClass();
701 UNREACHABLE();
702 }
703
704 return reg_types->MakeUnresolvedReference();
705 }
706
707 // Record the dependency that both `GetClass()` and `incoming_type.GetClass()`
708 // are assignable to `join_class`. The `verifier` is null during unit tests.
709 if (verifier != nullptr) {
710 VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
711 verifier->GetDexFile(),
712 verifier->GetClassDef(),
713 join_class,
714 GetClass());
715 VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(),
716 verifier->GetDexFile(),
717 verifier->GetClassDef(),
718 join_class,
719 incoming_type.GetClass());
720 }
721 if (GetClass() == join_class && !IsPreciseReference()) {
722 return *this;
723 } else if (incoming_type.GetClass() == join_class && !incoming_type.IsPreciseReference()) {
724 return incoming_type;
725 } else {
726 std::string temp;
727 const char* descriptor = join_class->GetDescriptor(&temp);
728 return reg_types->FromClass(descriptor, join_class, /* precise= */ false);
729 }
730 }
731 } else {
732 return conflict; // Unexpected types => Conflict
733 }
734 }
735
CheckInvariants() const736 void RegType::CheckInvariants() const {
737 if (IsConstant() || IsConstantLo() || IsConstantHi()) {
738 CHECK(descriptor_.empty()) << *this;
739 CHECK(klass_.IsNull()) << *this;
740 }
741 if (!klass_.IsNull()) {
742 CHECK(!descriptor_.empty()) << *this;
743 std::string temp;
744 CHECK_EQ(descriptor_, klass_->GetDescriptor(&temp)) << *this;
745 }
746 }
747
CheckInvariants() const748 void UninitializedThisReferenceType::CheckInvariants() const {
749 CHECK_EQ(GetAllocationPc(), 0U) << *this;
750 }
751
CheckInvariants() const752 void UnresolvedUninitializedThisRefType::CheckInvariants() const {
753 CHECK_EQ(GetAllocationPc(), 0U) << *this;
754 CHECK(!descriptor_.empty()) << *this;
755 CHECK(!HasClass()) << *this;
756 }
757
CheckInvariants() const758 void UnresolvedUninitializedRefType::CheckInvariants() const {
759 CHECK(!descriptor_.empty()) << *this;
760 CHECK(!HasClass()) << *this;
761 }
762
UnresolvedMergedType(const RegType & resolved,const BitVector & unresolved,const RegTypeCache * reg_type_cache,uint16_t cache_id)763 UnresolvedMergedType::UnresolvedMergedType(const RegType& resolved,
764 const BitVector& unresolved,
765 const RegTypeCache* reg_type_cache,
766 uint16_t cache_id)
767 : UnresolvedType(reg_type_cache->GetNullHandle(), "", cache_id),
768 reg_type_cache_(reg_type_cache),
769 resolved_part_(resolved),
770 unresolved_types_(unresolved, false, unresolved.GetAllocator()) {
771 CheckConstructorInvariants(this);
772 }
CheckInvariants() const773 void UnresolvedMergedType::CheckInvariants() const {
774 CHECK(reg_type_cache_ != nullptr);
775
776 // Unresolved merged types: merged types should be defined.
777 CHECK(descriptor_.empty()) << *this;
778 CHECK(!HasClass()) << *this;
779
780 CHECK(!resolved_part_.IsConflict());
781 CHECK(resolved_part_.IsReferenceTypes());
782 CHECK(!resolved_part_.IsUnresolvedTypes());
783
784 CHECK(resolved_part_.IsZero() ||
785 !(resolved_part_.IsArrayTypes() && !resolved_part_.IsObjectArrayTypes()));
786
787 CHECK_GT(unresolved_types_.NumSetBits(), 0U);
788 bool unresolved_is_array =
789 reg_type_cache_->GetFromId(unresolved_types_.GetHighestBitSet()).IsArrayTypes();
790 for (uint32_t idx : unresolved_types_.Indexes()) {
791 const RegType& t = reg_type_cache_->GetFromId(idx);
792 CHECK_EQ(unresolved_is_array, t.IsArrayTypes());
793 }
794
795 if (!resolved_part_.IsZero()) {
796 CHECK_EQ(resolved_part_.IsArrayTypes(), unresolved_is_array);
797 }
798 }
799
IsArrayTypes() const800 bool UnresolvedMergedType::IsArrayTypes() const {
801 // For a merge to be an array, both the resolved and the unresolved part need to be object
802 // arrays.
803 // (Note: we encode a missing resolved part [which doesn't need to be an array] as zero.)
804
805 if (!resolved_part_.IsZero() && !resolved_part_.IsArrayTypes()) {
806 return false;
807 }
808
809 // It is enough to check just one of the merged types. Otherwise the merge should have been
810 // collapsed (checked in CheckInvariants on construction).
811 uint32_t idx = unresolved_types_.GetHighestBitSet();
812 const RegType& unresolved = reg_type_cache_->GetFromId(idx);
813 return unresolved.IsArrayTypes();
814 }
IsObjectArrayTypes() const815 bool UnresolvedMergedType::IsObjectArrayTypes() const {
816 // Same as IsArrayTypes, as primitive arrays are always resolved.
817 return IsArrayTypes();
818 }
819
CheckInvariants() const820 void UnresolvedReferenceType::CheckInvariants() const {
821 CHECK(!descriptor_.empty()) << *this;
822 CHECK(!HasClass()) << *this;
823 }
824
CheckInvariants() const825 void UnresolvedSuperClass::CheckInvariants() const {
826 // Unresolved merged types: merged types should be defined.
827 CHECK(descriptor_.empty()) << *this;
828 CHECK(!HasClass()) << *this;
829 CHECK_NE(unresolved_child_id_, 0U) << *this;
830 }
831
operator <<(std::ostream & os,const RegType & rhs)832 std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
833 os << rhs.Dump();
834 return os;
835 }
836
837 } // namespace verifier
838 } // namespace art
839