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