1 /*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "reg_type-inl.h"
18
19 #include "base/arena_bit_vector.h"
20 #include "base/bit_vector-inl.h"
21 #include "base/casts.h"
22 #include "class_linker-inl.h"
23 #include "dex_file-inl.h"
24 #include "mirror/class.h"
25 #include "mirror/class-inl.h"
26 #include "mirror/object-inl.h"
27 #include "mirror/object_array-inl.h"
28 #include "reg_type_cache-inl.h"
29 #include "scoped_thread_state_change.h"
30
31 #include <limits>
32 #include <sstream>
33
34 namespace art {
35 namespace verifier {
36
37 const UndefinedType* UndefinedType::instance_ = nullptr;
38 const ConflictType* ConflictType::instance_ = nullptr;
39 const BooleanType* BooleanType::instance_ = nullptr;
40 const ByteType* ByteType::instance_ = nullptr;
41 const ShortType* ShortType::instance_ = nullptr;
42 const CharType* CharType::instance_ = nullptr;
43 const FloatType* FloatType::instance_ = nullptr;
44 const LongLoType* LongLoType::instance_ = nullptr;
45 const LongHiType* LongHiType::instance_ = nullptr;
46 const DoubleLoType* DoubleLoType::instance_ = nullptr;
47 const DoubleHiType* DoubleHiType::instance_ = nullptr;
48 const IntegerType* IntegerType::instance_ = nullptr;
49
PrimitiveType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)50 PrimitiveType::PrimitiveType(mirror::Class* klass, const StringPiece& descriptor, uint16_t cache_id)
51 : RegType(klass, descriptor, cache_id) {
52 CHECK(klass != nullptr);
53 CHECK(!descriptor.empty());
54 }
55
Cat1Type(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)56 Cat1Type::Cat1Type(mirror::Class* klass, const StringPiece& descriptor, uint16_t cache_id)
57 : PrimitiveType(klass, descriptor, cache_id) {
58 }
59
Cat2Type(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)60 Cat2Type::Cat2Type(mirror::Class* klass, const StringPiece& descriptor, uint16_t cache_id)
61 : PrimitiveType(klass, descriptor, cache_id) {
62 }
63
Dump() const64 std::string PreciseConstType::Dump() const {
65 std::stringstream result;
66 uint32_t val = ConstantValue();
67 if (val == 0) {
68 CHECK(IsPreciseConstant());
69 result << "Zero/null";
70 } else {
71 result << "Precise ";
72 if (IsConstantShort()) {
73 result << StringPrintf("Constant: %d", val);
74 } else {
75 result << StringPrintf("Constant: 0x%x", val);
76 }
77 }
78 return result.str();
79 }
80
Dump() const81 std::string BooleanType::Dump() const {
82 return "Boolean";
83 }
84
Dump() const85 std::string ConflictType::Dump() const {
86 return "Conflict";
87 }
88
Dump() const89 std::string ByteType::Dump() const {
90 return "Byte";
91 }
92
Dump() const93 std::string ShortType::Dump() const {
94 return "Short";
95 }
96
Dump() const97 std::string CharType::Dump() const {
98 return "Char";
99 }
100
Dump() const101 std::string FloatType::Dump() const {
102 return "Float";
103 }
104
Dump() const105 std::string LongLoType::Dump() const {
106 return "Long (Low Half)";
107 }
108
Dump() const109 std::string LongHiType::Dump() const {
110 return "Long (High Half)";
111 }
112
Dump() const113 std::string DoubleLoType::Dump() const {
114 return "Double (Low Half)";
115 }
116
Dump() const117 std::string DoubleHiType::Dump() const {
118 return "Double (High Half)";
119 }
120
Dump() const121 std::string IntegerType::Dump() const {
122 return "Integer";
123 }
124
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)125 const DoubleHiType* DoubleHiType::CreateInstance(mirror::Class* klass,
126 const StringPiece& descriptor,
127 uint16_t cache_id) {
128 CHECK(instance_ == nullptr);
129 instance_ = new DoubleHiType(klass, descriptor, cache_id);
130 return instance_;
131 }
132
Destroy()133 void DoubleHiType::Destroy() {
134 if (instance_ != nullptr) {
135 delete instance_;
136 instance_ = nullptr;
137 }
138 }
139
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)140 const DoubleLoType* DoubleLoType::CreateInstance(mirror::Class* klass,
141 const StringPiece& descriptor,
142 uint16_t cache_id) {
143 CHECK(instance_ == nullptr);
144 instance_ = new DoubleLoType(klass, descriptor, cache_id);
145 return instance_;
146 }
147
Destroy()148 void DoubleLoType::Destroy() {
149 if (instance_ != nullptr) {
150 delete instance_;
151 instance_ = nullptr;
152 }
153 }
154
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)155 const LongLoType* LongLoType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
156 uint16_t cache_id) {
157 CHECK(instance_ == nullptr);
158 instance_ = new LongLoType(klass, descriptor, cache_id);
159 return instance_;
160 }
161
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)162 const LongHiType* LongHiType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
163 uint16_t cache_id) {
164 CHECK(instance_ == nullptr);
165 instance_ = new LongHiType(klass, descriptor, cache_id);
166 return instance_;
167 }
168
Destroy()169 void LongHiType::Destroy() {
170 if (instance_ != nullptr) {
171 delete instance_;
172 instance_ = nullptr;
173 }
174 }
175
Destroy()176 void LongLoType::Destroy() {
177 if (instance_ != nullptr) {
178 delete instance_;
179 instance_ = nullptr;
180 }
181 }
182
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)183 const FloatType* FloatType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
184 uint16_t cache_id) {
185 CHECK(instance_ == nullptr);
186 instance_ = new FloatType(klass, descriptor, cache_id);
187 return instance_;
188 }
189
Destroy()190 void FloatType::Destroy() {
191 if (instance_ != nullptr) {
192 delete instance_;
193 instance_ = nullptr;
194 }
195 }
196
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)197 const CharType* CharType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
198 uint16_t cache_id) {
199 CHECK(instance_ == nullptr);
200 instance_ = new CharType(klass, descriptor, cache_id);
201 return instance_;
202 }
203
Destroy()204 void CharType::Destroy() {
205 if (instance_ != nullptr) {
206 delete instance_;
207 instance_ = nullptr;
208 }
209 }
210
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)211 const ShortType* ShortType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
212 uint16_t cache_id) {
213 CHECK(instance_ == nullptr);
214 instance_ = new ShortType(klass, descriptor, cache_id);
215 return instance_;
216 }
217
Destroy()218 void ShortType::Destroy() {
219 if (instance_ != nullptr) {
220 delete instance_;
221 instance_ = nullptr;
222 }
223 }
224
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)225 const ByteType* ByteType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
226 uint16_t cache_id) {
227 CHECK(instance_ == nullptr);
228 instance_ = new ByteType(klass, descriptor, cache_id);
229 return instance_;
230 }
231
Destroy()232 void ByteType::Destroy() {
233 if (instance_ != nullptr) {
234 delete instance_;
235 instance_ = nullptr;
236 }
237 }
238
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)239 const IntegerType* IntegerType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
240 uint16_t cache_id) {
241 CHECK(instance_ == nullptr);
242 instance_ = new IntegerType(klass, descriptor, cache_id);
243 return instance_;
244 }
245
Destroy()246 void IntegerType::Destroy() {
247 if (instance_ != nullptr) {
248 delete instance_;
249 instance_ = nullptr;
250 }
251 }
252
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)253 const ConflictType* ConflictType::CreateInstance(mirror::Class* klass,
254 const StringPiece& descriptor,
255 uint16_t cache_id) {
256 CHECK(instance_ == nullptr);
257 instance_ = new ConflictType(klass, descriptor, cache_id);
258 return instance_;
259 }
260
Destroy()261 void ConflictType::Destroy() {
262 if (instance_ != nullptr) {
263 delete instance_;
264 instance_ = nullptr;
265 }
266 }
267
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)268 const BooleanType* BooleanType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
269 uint16_t cache_id) {
270 CHECK(BooleanType::instance_ == nullptr);
271 instance_ = new BooleanType(klass, descriptor, cache_id);
272 return BooleanType::instance_;
273 }
274
Destroy()275 void BooleanType::Destroy() {
276 if (BooleanType::instance_ != nullptr) {
277 delete instance_;
278 instance_ = nullptr;
279 }
280 }
281
Dump() const282 std::string UndefinedType::Dump() const SHARED_REQUIRES(Locks::mutator_lock_) {
283 return "Undefined";
284 }
285
CreateInstance(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)286 const UndefinedType* UndefinedType::CreateInstance(mirror::Class* klass,
287 const StringPiece& descriptor,
288 uint16_t cache_id) {
289 CHECK(instance_ == nullptr);
290 instance_ = new UndefinedType(klass, descriptor, cache_id);
291 return instance_;
292 }
293
Destroy()294 void UndefinedType::Destroy() {
295 if (instance_ != nullptr) {
296 delete instance_;
297 instance_ = nullptr;
298 }
299 }
300
PreciseReferenceType(mirror::Class * klass,const StringPiece & descriptor,uint16_t cache_id)301 PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, const StringPiece& descriptor,
302 uint16_t cache_id)
303 : RegType(klass, descriptor, cache_id) {
304 // Note: no check for IsInstantiable() here. We may produce this in case an InstantiationError
305 // would be thrown at runtime, but we need to continue verification and *not* create a
306 // hard failure or abort.
307 }
308
Dump() const309 std::string UnresolvedMergedType::Dump() const {
310 std::stringstream result;
311 result << "UnresolvedMergedReferences(" << GetResolvedPart().Dump() << " | ";
312 const BitVector& types = GetUnresolvedTypes();
313
314 bool first = true;
315 for (uint32_t idx : types.Indexes()) {
316 if (!first) {
317 result << ", ";
318 } else {
319 first = false;
320 }
321 result << reg_type_cache_->GetFromId(idx).Dump();
322 }
323 result << ")";
324 return result.str();
325 }
326
Dump() const327 std::string UnresolvedSuperClass::Dump() const {
328 std::stringstream result;
329 uint16_t super_type_id = GetUnresolvedSuperClassChildId();
330 result << "UnresolvedSuperClass(" << reg_type_cache_->GetFromId(super_type_id).Dump() << ")";
331 return result.str();
332 }
333
Dump() const334 std::string UnresolvedReferenceType::Dump() const {
335 std::stringstream result;
336 result << "Unresolved Reference" << ": " << PrettyDescriptor(GetDescriptor().as_string().c_str());
337 return result.str();
338 }
339
Dump() const340 std::string UnresolvedUninitializedRefType::Dump() const {
341 std::stringstream result;
342 result << "Unresolved And Uninitialized Reference" << ": "
343 << PrettyDescriptor(GetDescriptor().as_string().c_str())
344 << " Allocation PC: " << GetAllocationPc();
345 return result.str();
346 }
347
Dump() const348 std::string UnresolvedUninitializedThisRefType::Dump() const {
349 std::stringstream result;
350 result << "Unresolved And Uninitialized This Reference"
351 << PrettyDescriptor(GetDescriptor().as_string().c_str());
352 return result.str();
353 }
354
Dump() const355 std::string ReferenceType::Dump() const {
356 std::stringstream result;
357 result << "Reference" << ": " << PrettyDescriptor(GetClass());
358 return result.str();
359 }
360
Dump() const361 std::string PreciseReferenceType::Dump() const {
362 std::stringstream result;
363 result << "Precise Reference" << ": "<< PrettyDescriptor(GetClass());
364 return result.str();
365 }
366
Dump() const367 std::string UninitializedReferenceType::Dump() const {
368 std::stringstream result;
369 result << "Uninitialized Reference" << ": " << PrettyDescriptor(GetClass());
370 result << " Allocation PC: " << GetAllocationPc();
371 return result.str();
372 }
373
Dump() const374 std::string UninitializedThisReferenceType::Dump() const {
375 std::stringstream result;
376 result << "Uninitialized This Reference" << ": " << PrettyDescriptor(GetClass());
377 result << "Allocation PC: " << GetAllocationPc();
378 return result.str();
379 }
380
Dump() const381 std::string ImpreciseConstType::Dump() const {
382 std::stringstream result;
383 uint32_t val = ConstantValue();
384 if (val == 0) {
385 result << "Zero/null";
386 } else {
387 result << "Imprecise ";
388 if (IsConstantShort()) {
389 result << StringPrintf("Constant: %d", val);
390 } else {
391 result << StringPrintf("Constant: 0x%x", val);
392 }
393 }
394 return result.str();
395 }
Dump() const396 std::string PreciseConstLoType::Dump() const {
397 std::stringstream result;
398
399 int32_t val = ConstantValueLo();
400 result << "Precise ";
401 if (val >= std::numeric_limits<jshort>::min() &&
402 val <= std::numeric_limits<jshort>::max()) {
403 result << StringPrintf("Low-half Constant: %d", val);
404 } else {
405 result << StringPrintf("Low-half Constant: 0x%x", val);
406 }
407 return result.str();
408 }
409
Dump() const410 std::string ImpreciseConstLoType::Dump() const {
411 std::stringstream result;
412
413 int32_t val = ConstantValueLo();
414 result << "Imprecise ";
415 if (val >= std::numeric_limits<jshort>::min() &&
416 val <= std::numeric_limits<jshort>::max()) {
417 result << StringPrintf("Low-half Constant: %d", val);
418 } else {
419 result << StringPrintf("Low-half Constant: 0x%x", val);
420 }
421 return result.str();
422 }
423
Dump() const424 std::string PreciseConstHiType::Dump() const {
425 std::stringstream result;
426 int32_t val = ConstantValueHi();
427 result << "Precise ";
428 if (val >= std::numeric_limits<jshort>::min() &&
429 val <= std::numeric_limits<jshort>::max()) {
430 result << StringPrintf("High-half Constant: %d", val);
431 } else {
432 result << StringPrintf("High-half Constant: 0x%x", val);
433 }
434 return result.str();
435 }
436
Dump() const437 std::string ImpreciseConstHiType::Dump() const {
438 std::stringstream result;
439 int32_t val = ConstantValueHi();
440 result << "Imprecise ";
441 if (val >= std::numeric_limits<jshort>::min() &&
442 val <= std::numeric_limits<jshort>::max()) {
443 result << StringPrintf("High-half Constant: %d", val);
444 } else {
445 result << StringPrintf("High-half Constant: 0x%x", val);
446 }
447 return result.str();
448 }
449
HighHalf(RegTypeCache * cache) const450 const RegType& RegType::HighHalf(RegTypeCache* cache) const {
451 DCHECK(IsLowHalf());
452 if (IsLongLo()) {
453 return cache->LongHi();
454 } else if (IsDoubleLo()) {
455 return cache->DoubleHi();
456 } else {
457 DCHECK(IsImpreciseConstantLo());
458 const ConstantType* const_val = down_cast<const ConstantType*>(this);
459 return cache->FromCat2ConstHi(const_val->ConstantValue(), false);
460 }
461 }
462
GetPrimitiveType() const463 Primitive::Type RegType::GetPrimitiveType() const {
464 if (IsNonZeroReferenceTypes()) {
465 return Primitive::kPrimNot;
466 } else if (IsBooleanTypes()) {
467 return Primitive::kPrimBoolean;
468 } else if (IsByteTypes()) {
469 return Primitive::kPrimByte;
470 } else if (IsShortTypes()) {
471 return Primitive::kPrimShort;
472 } else if (IsCharTypes()) {
473 return Primitive::kPrimChar;
474 } else if (IsFloat()) {
475 return Primitive::kPrimFloat;
476 } else if (IsIntegralTypes()) {
477 return Primitive::kPrimInt;
478 } else if (IsDoubleLo()) {
479 return Primitive::kPrimDouble;
480 } else {
481 DCHECK(IsLongTypes());
482 return Primitive::kPrimLong;
483 }
484 }
485
IsUninitializedTypes() const486 bool UninitializedType::IsUninitializedTypes() const {
487 return true;
488 }
489
IsNonZeroReferenceTypes() const490 bool UninitializedType::IsNonZeroReferenceTypes() const {
491 return true;
492 }
493
IsNonZeroReferenceTypes() const494 bool UnresolvedType::IsNonZeroReferenceTypes() const {
495 return true;
496 }
497
GetSuperClass(RegTypeCache * cache) const498 const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
499 if (!IsUnresolvedTypes()) {
500 mirror::Class* super_klass = GetClass()->GetSuperClass();
501 if (super_klass != nullptr) {
502 // A super class of a precise type isn't precise as a precise type indicates the register
503 // holds exactly that type.
504 std::string temp;
505 return cache->FromClass(super_klass->GetDescriptor(&temp), super_klass, false);
506 } else {
507 return cache->Zero();
508 }
509 } else {
510 if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
511 GetDescriptor()[0] == '[') {
512 // Super class of all arrays is Object.
513 return cache->JavaLangObject(true);
514 } else {
515 return cache->FromUnresolvedSuperClass(*this);
516 }
517 }
518 }
519
IsJavaLangObject() const520 bool RegType::IsJavaLangObject() const SHARED_REQUIRES(Locks::mutator_lock_) {
521 return IsReference() && GetClass()->IsObjectClass();
522 }
523
IsObjectArrayTypes() const524 bool RegType::IsObjectArrayTypes() const SHARED_REQUIRES(Locks::mutator_lock_) {
525 if (IsUnresolvedTypes()) {
526 DCHECK(!IsUnresolvedMergedReference());
527
528 if (IsUnresolvedSuperClass()) {
529 // Cannot be an array, as the superclass of arrays is java.lang.Object (which cannot be
530 // unresolved).
531 return false;
532 }
533
534 // Primitive arrays will always resolve.
535 DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
536 return descriptor_[0] == '[';
537 } else if (HasClass()) {
538 mirror::Class* type = GetClass();
539 return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
540 } else {
541 return false;
542 }
543 }
544
IsArrayTypes() const545 bool RegType::IsArrayTypes() const SHARED_REQUIRES(Locks::mutator_lock_) {
546 if (IsUnresolvedTypes()) {
547 DCHECK(!IsUnresolvedMergedReference());
548
549 if (IsUnresolvedSuperClass()) {
550 // Cannot be an array, as the superclass of arrays is java.lang.Object (which cannot be
551 // unresolved).
552 return false;
553 }
554 return descriptor_[0] == '[';
555 } else if (HasClass()) {
556 return GetClass()->IsArrayClass();
557 } else {
558 return false;
559 }
560 }
561
IsJavaLangObjectArray() const562 bool RegType::IsJavaLangObjectArray() const {
563 if (HasClass()) {
564 mirror::Class* type = GetClass();
565 return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
566 }
567 return false;
568 }
569
IsInstantiableTypes() const570 bool RegType::IsInstantiableTypes() const {
571 return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
572 }
573
SelectNonConstant(const RegType & a,const RegType & b)574 static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
575 return a.IsConstantTypes() ? b : a;
576 }
577
Merge(const RegType & incoming_type,RegTypeCache * reg_types) const578 const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
579 DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller
580 // Perform pointer equality tests for undefined and conflict to avoid virtual method dispatch.
581 const UndefinedType& undefined = reg_types->Undefined();
582 const ConflictType& conflict = reg_types->Conflict();
583 DCHECK_EQ(this == &undefined, IsUndefined());
584 DCHECK_EQ(&incoming_type == &undefined, incoming_type.IsUndefined());
585 DCHECK_EQ(this == &conflict, IsConflict());
586 DCHECK_EQ(&incoming_type == &conflict, incoming_type.IsConflict());
587 if (this == &undefined || &incoming_type == &undefined) {
588 // There is a difference between undefined and conflict. Conflicts may be copied around, but
589 // not used. Undefined registers must not be copied. So any merge with undefined should return
590 // undefined.
591 return undefined;
592 } else if (this == &conflict || &incoming_type == &conflict) {
593 return conflict; // (Conflict MERGE *) or (* MERGE Conflict) => Conflict
594 } else if (IsConstant() && incoming_type.IsConstant()) {
595 const ConstantType& type1 = *down_cast<const ConstantType*>(this);
596 const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
597 int32_t val1 = type1.ConstantValue();
598 int32_t val2 = type2.ConstantValue();
599 if (val1 >= 0 && val2 >= 0) {
600 // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
601 if (val1 >= val2) {
602 if (!type1.IsPreciseConstant()) {
603 return *this;
604 } else {
605 return reg_types->FromCat1Const(val1, false);
606 }
607 } else {
608 if (!type2.IsPreciseConstant()) {
609 return type2;
610 } else {
611 return reg_types->FromCat1Const(val2, false);
612 }
613 }
614 } else if (val1 < 0 && val2 < 0) {
615 // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
616 if (val1 <= val2) {
617 if (!type1.IsPreciseConstant()) {
618 return *this;
619 } else {
620 return reg_types->FromCat1Const(val1, false);
621 }
622 } else {
623 if (!type2.IsPreciseConstant()) {
624 return type2;
625 } else {
626 return reg_types->FromCat1Const(val2, false);
627 }
628 }
629 } else {
630 // Values are +ve and -ve, choose smallest signed type in which they both fit
631 if (type1.IsConstantByte()) {
632 if (type2.IsConstantByte()) {
633 return reg_types->ByteConstant();
634 } else if (type2.IsConstantShort()) {
635 return reg_types->ShortConstant();
636 } else {
637 return reg_types->IntConstant();
638 }
639 } else if (type1.IsConstantShort()) {
640 if (type2.IsConstantShort()) {
641 return reg_types->ShortConstant();
642 } else {
643 return reg_types->IntConstant();
644 }
645 } else {
646 return reg_types->IntConstant();
647 }
648 }
649 } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
650 const ConstantType& type1 = *down_cast<const ConstantType*>(this);
651 const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
652 int32_t val1 = type1.ConstantValueLo();
653 int32_t val2 = type2.ConstantValueLo();
654 return reg_types->FromCat2ConstLo(val1 | val2, false);
655 } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
656 const ConstantType& type1 = *down_cast<const ConstantType*>(this);
657 const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
658 int32_t val1 = type1.ConstantValueHi();
659 int32_t val2 = type2.ConstantValueHi();
660 return reg_types->FromCat2ConstHi(val1 | val2, false);
661 } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
662 if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
663 return reg_types->Boolean(); // boolean MERGE boolean => boolean
664 }
665 if (IsByteTypes() && incoming_type.IsByteTypes()) {
666 return reg_types->Byte(); // byte MERGE byte => byte
667 }
668 if (IsShortTypes() && incoming_type.IsShortTypes()) {
669 return reg_types->Short(); // short MERGE short => short
670 }
671 if (IsCharTypes() && incoming_type.IsCharTypes()) {
672 return reg_types->Char(); // char MERGE char => char
673 }
674 return reg_types->Integer(); // int MERGE * => int
675 } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
676 (IsLongTypes() && incoming_type.IsLongTypes()) ||
677 (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
678 (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
679 (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
680 // check constant case was handled prior to entry
681 DCHECK(!IsConstant() || !incoming_type.IsConstant());
682 // float/long/double MERGE float/long/double_constant => float/long/double
683 return SelectNonConstant(*this, incoming_type);
684 } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
685 if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
686 // Something that is uninitialized hasn't had its constructor called. Unitialized types are
687 // special. They may only ever be merged with themselves (must be taken care of by the
688 // caller of Merge(), see the DCHECK on entry). So mark any other merge as conflicting here.
689 return conflict;
690 } else if (IsZero() || incoming_type.IsZero()) {
691 return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref
692 } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
693 return reg_types->JavaLangObject(false); // Object MERGE ref => Object
694 } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
695 // We know how to merge an unresolved type with itself, 0 or Object. In this case we
696 // have two sub-classes and don't know how to merge. Create a new string-based unresolved
697 // type that reflects our lack of knowledge and that allows the rest of the unresolved
698 // mechanics to continue.
699 return reg_types->FromUnresolvedMerge(*this, incoming_type);
700 } else { // Two reference types, compute Join
701 mirror::Class* c1 = GetClass();
702 mirror::Class* c2 = incoming_type.GetClass();
703 DCHECK(c1 != nullptr && !c1->IsPrimitive());
704 DCHECK(c2 != nullptr && !c2->IsPrimitive());
705 mirror::Class* join_class = ClassJoin(c1, c2);
706 if (c1 == join_class && !IsPreciseReference()) {
707 return *this;
708 } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
709 return incoming_type;
710 } else {
711 std::string temp;
712 return reg_types->FromClass(join_class->GetDescriptor(&temp), join_class, false);
713 }
714 }
715 } else {
716 return conflict; // Unexpected types => Conflict
717 }
718 }
719
720 // See comment in reg_type.h
ClassJoin(mirror::Class * s,mirror::Class * t)721 mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
722 DCHECK(!s->IsPrimitive()) << PrettyClass(s);
723 DCHECK(!t->IsPrimitive()) << PrettyClass(t);
724 if (s == t) {
725 return s;
726 } else if (s->IsAssignableFrom(t)) {
727 return s;
728 } else if (t->IsAssignableFrom(s)) {
729 return t;
730 } else if (s->IsArrayClass() && t->IsArrayClass()) {
731 mirror::Class* s_ct = s->GetComponentType();
732 mirror::Class* t_ct = t->GetComponentType();
733 if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
734 // Given the types aren't the same, if either array is of primitive types then the only
735 // common parent is java.lang.Object
736 mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object
737 DCHECK(result->IsObjectClass());
738 return result;
739 }
740 mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
741 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
742 mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), &common_elem);
743 DCHECK(array_class != nullptr);
744 return array_class;
745 } else {
746 size_t s_depth = s->Depth();
747 size_t t_depth = t->Depth();
748 // Get s and t to the same depth in the hierarchy
749 if (s_depth > t_depth) {
750 while (s_depth > t_depth) {
751 s = s->GetSuperClass();
752 s_depth--;
753 }
754 } else {
755 while (t_depth > s_depth) {
756 t = t->GetSuperClass();
757 t_depth--;
758 }
759 }
760 // Go up the hierarchy until we get to the common parent
761 while (s != t) {
762 s = s->GetSuperClass();
763 t = t->GetSuperClass();
764 }
765 return s;
766 }
767 }
768
CheckInvariants() const769 void RegType::CheckInvariants() const {
770 if (IsConstant() || IsConstantLo() || IsConstantHi()) {
771 CHECK(descriptor_.empty()) << *this;
772 CHECK(klass_.IsNull()) << *this;
773 }
774 if (!klass_.IsNull()) {
775 CHECK(!descriptor_.empty()) << *this;
776 }
777 }
778
VisitRoots(RootVisitor * visitor,const RootInfo & root_info) const779 void RegType::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const {
780 klass_.VisitRootIfNonNull(visitor, root_info);
781 }
782
CheckInvariants() const783 void UninitializedThisReferenceType::CheckInvariants() const {
784 CHECK_EQ(GetAllocationPc(), 0U) << *this;
785 }
786
CheckInvariants() const787 void UnresolvedUninitializedThisRefType::CheckInvariants() const {
788 CHECK_EQ(GetAllocationPc(), 0U) << *this;
789 CHECK(!descriptor_.empty()) << *this;
790 CHECK(klass_.IsNull()) << *this;
791 }
792
CheckInvariants() const793 void UnresolvedUninitializedRefType::CheckInvariants() const {
794 CHECK(!descriptor_.empty()) << *this;
795 CHECK(klass_.IsNull()) << *this;
796 }
797
UnresolvedMergedType(const RegType & resolved,const BitVector & unresolved,const RegTypeCache * reg_type_cache,uint16_t cache_id)798 UnresolvedMergedType::UnresolvedMergedType(const RegType& resolved,
799 const BitVector& unresolved,
800 const RegTypeCache* reg_type_cache,
801 uint16_t cache_id)
802 : UnresolvedType("", cache_id),
803 reg_type_cache_(reg_type_cache),
804 resolved_part_(resolved),
805 unresolved_types_(unresolved, false, unresolved.GetAllocator()) {
806 if (kIsDebugBuild) {
807 CheckInvariants();
808 }
809 }
CheckInvariants() const810 void UnresolvedMergedType::CheckInvariants() const {
811 CHECK(reg_type_cache_ != nullptr);
812
813 // Unresolved merged types: merged types should be defined.
814 CHECK(descriptor_.empty()) << *this;
815 CHECK(klass_.IsNull()) << *this;
816
817 CHECK(!resolved_part_.IsConflict());
818 CHECK(resolved_part_.IsReferenceTypes());
819 CHECK(!resolved_part_.IsUnresolvedTypes());
820
821 CHECK(resolved_part_.IsZero() ||
822 !(resolved_part_.IsArrayTypes() && !resolved_part_.IsObjectArrayTypes()));
823
824 CHECK_GT(unresolved_types_.NumSetBits(), 0U);
825 bool unresolved_is_array =
826 reg_type_cache_->GetFromId(unresolved_types_.GetHighestBitSet()).IsArrayTypes();
827 for (uint32_t idx : unresolved_types_.Indexes()) {
828 const RegType& t = reg_type_cache_->GetFromId(idx);
829 CHECK_EQ(unresolved_is_array, t.IsArrayTypes());
830 }
831
832 if (!resolved_part_.IsZero()) {
833 CHECK_EQ(resolved_part_.IsArrayTypes(), unresolved_is_array);
834 }
835 }
836
IsArrayTypes() const837 bool UnresolvedMergedType::IsArrayTypes() const {
838 // For a merge to be an array, both the resolved and the unresolved part need to be object
839 // arrays.
840 // (Note: we encode a missing resolved part [which doesn't need to be an array] as zero.)
841
842 if (!resolved_part_.IsZero() && !resolved_part_.IsArrayTypes()) {
843 return false;
844 }
845
846 // It is enough to check just one of the merged types. Otherwise the merge should have been
847 // collapsed (checked in CheckInvariants on construction).
848 uint32_t idx = unresolved_types_.GetHighestBitSet();
849 const RegType& unresolved = reg_type_cache_->GetFromId(idx);
850 return unresolved.IsArrayTypes();
851 }
IsObjectArrayTypes() const852 bool UnresolvedMergedType::IsObjectArrayTypes() const {
853 // Same as IsArrayTypes, as primitive arrays are always resolved.
854 return IsArrayTypes();
855 }
856
CheckInvariants() const857 void UnresolvedReferenceType::CheckInvariants() const {
858 CHECK(!descriptor_.empty()) << *this;
859 CHECK(klass_.IsNull()) << *this;
860 }
861
CheckInvariants() const862 void UnresolvedSuperClass::CheckInvariants() const {
863 // Unresolved merged types: merged types should be defined.
864 CHECK(descriptor_.empty()) << *this;
865 CHECK(klass_.IsNull()) << *this;
866 CHECK_NE(unresolved_child_id_, 0U) << *this;
867 }
868
operator <<(std::ostream & os,const RegType & rhs)869 std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
870 os << rhs.Dump();
871 return os;
872 }
873
CanAssignArray(const RegType & src,RegTypeCache & reg_types,Handle<mirror::ClassLoader> class_loader,bool * soft_error) const874 bool RegType::CanAssignArray(const RegType& src, RegTypeCache& reg_types,
875 Handle<mirror::ClassLoader> class_loader, bool* soft_error) const {
876 if (!IsArrayTypes() || !src.IsArrayTypes()) {
877 *soft_error = false;
878 return false;
879 }
880
881 if (IsUnresolvedMergedReference() || src.IsUnresolvedMergedReference()) {
882 // An unresolved array type means that it's an array of some reference type. Reference arrays
883 // can never be assigned to primitive-type arrays, and vice versa. So it is a soft error if
884 // both arrays are reference arrays, otherwise a hard error.
885 *soft_error = IsObjectArrayTypes() && src.IsObjectArrayTypes();
886 return false;
887 }
888
889 const RegType& cmp1 = reg_types.GetComponentType(*this, class_loader.Get());
890 const RegType& cmp2 = reg_types.GetComponentType(src, class_loader.Get());
891
892 if (cmp1.IsAssignableFrom(cmp2)) {
893 return true;
894 }
895 if (cmp1.IsUnresolvedTypes()) {
896 if (cmp2.IsIntegralTypes() || cmp2.IsFloatTypes() || cmp2.IsArrayTypes()) {
897 *soft_error = false;
898 return false;
899 }
900 *soft_error = true;
901 return false;
902 }
903 if (cmp2.IsUnresolvedTypes()) {
904 if (cmp1.IsIntegralTypes() || cmp1.IsFloatTypes() || cmp1.IsArrayTypes()) {
905 *soft_error = false;
906 return false;
907 }
908 *soft_error = true;
909 return false;
910 }
911 if (!cmp1.IsArrayTypes() || !cmp2.IsArrayTypes()) {
912 *soft_error = false;
913 return false;
914 }
915 return cmp1.CanAssignArray(cmp2, reg_types, class_loader, soft_error);
916 }
917
918
919 } // namespace verifier
920 } // namespace art
921