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.h"
18
19
20 #include "base/casts.h"
21 #include "class_linker-inl.h"
22 #include "dex_file-inl.h"
23 #include "mirror/class.h"
24 #include "mirror/class-inl.h"
25 #include "mirror/object-inl.h"
26 #include "mirror/object_array-inl.h"
27 #include "reg_type_cache-inl.h"
28 #include "scoped_thread_state_change.h"
29
30 #include <limits>
31 #include <sstream>
32
33 namespace art {
34 namespace verifier {
35
36 UndefinedType* UndefinedType::instance_ = NULL;
37 ConflictType* ConflictType::instance_ = NULL;
38 BooleanType* BooleanType::instance = NULL;
39 ByteType* ByteType::instance_ = NULL;
40 ShortType* ShortType::instance_ = NULL;
41 CharType* CharType::instance_ = NULL;
42 FloatType* FloatType::instance_ = NULL;
43 LongLoType* LongLoType::instance_ = NULL;
44 LongHiType* LongHiType::instance_ = NULL;
45 DoubleLoType* DoubleLoType::instance_ = NULL;
46 DoubleHiType* DoubleHiType::instance_ = NULL;
47 IntegerType* IntegerType::instance_ = NULL;
48
ConstantValue() const49 int32_t RegType::ConstantValue() const {
50 ScopedObjectAccess soa(Thread::Current());
51 LOG(FATAL) << "Unexpected call to ConstantValue: " << *this;
52 return 0;
53 }
54
ConstantValueLo() const55 int32_t RegType::ConstantValueLo() const {
56 ScopedObjectAccess soa(Thread::Current());
57 LOG(FATAL) << "Unexpected call to ConstantValueLo: " << *this;
58 return 0;
59 }
60
ConstantValueHi() const61 int32_t RegType::ConstantValueHi() const {
62 ScopedObjectAccess soa(Thread::Current());
63 LOG(FATAL) << "Unexpected call to ConstantValueHi: " << *this;
64 return 0;
65 }
66
PrimitiveType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)67 PrimitiveType::PrimitiveType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
68 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
69 : RegType(klass, descriptor, cache_id) {
70 CHECK(klass != NULL);
71 CHECK(!descriptor.empty());
72 }
73
Cat1Type(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)74 Cat1Type::Cat1Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
75 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
76 : PrimitiveType(klass, descriptor, cache_id) {
77 }
78
Cat2Type(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)79 Cat2Type::Cat2Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
80 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
81 : PrimitiveType(klass, descriptor, cache_id) {
82 }
83
Dump()84 std::string PreciseConstType::Dump() {
85 std::stringstream result;
86 uint32_t val = ConstantValue();
87 if (val == 0) {
88 CHECK(IsPreciseConstant());
89 result << "Zero/null";
90 } else {
91 result << "Precise ";
92 if (IsConstantShort()) {
93 result << StringPrintf("Constant: %d", val);
94 } else {
95 result << StringPrintf("Constant: 0x%x", val);
96 }
97 }
98 return result.str();
99 }
100
Dump()101 std::string BooleanType::Dump() {
102 return "Boolean";
103 }
104
Dump()105 std::string ConflictType::Dump() {
106 return "Conflict";
107 }
108
Dump()109 std::string ByteType::Dump() {
110 return "Byte";
111 }
112
Dump()113 std::string ShortType::Dump() {
114 return "Short";
115 }
116
Dump()117 std::string CharType::Dump() {
118 return "Char";
119 }
120
Dump()121 std::string FloatType::Dump() {
122 return "Float";
123 }
124
Dump()125 std::string LongLoType::Dump() {
126 return "Long (Low Half)";
127 }
128
Dump()129 std::string LongHiType::Dump() {
130 return "Long (High Half)";
131 }
132
Dump()133 std::string DoubleLoType::Dump() {
134 return "Double (Low Half)";
135 }
136
Dump()137 std::string DoubleHiType::Dump() {
138 return "Double (High Half)";
139 }
140
Dump()141 std::string IntegerType::Dump() {
142 return "Integer";
143 }
144
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)145 DoubleHiType* DoubleHiType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
146 uint16_t cache_id) {
147 if (instance_ == NULL) {
148 instance_ = new DoubleHiType(klass, descriptor, cache_id);
149 }
150 return instance_;
151 }
152
GetInstance()153 DoubleHiType* DoubleHiType::GetInstance() {
154 CHECK(instance_ != NULL);
155 return instance_;
156 }
157
Destroy()158 void DoubleHiType::Destroy() {
159 if (instance_ != NULL) {
160 delete instance_;
161 instance_ = NULL;
162 }
163 }
164
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)165 DoubleLoType* DoubleLoType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
166 uint16_t cache_id) {
167 if (instance_ == NULL) {
168 instance_ = new DoubleLoType(klass, descriptor, cache_id);
169 }
170 return instance_;
171 }
172
GetInstance()173 DoubleLoType* DoubleLoType::GetInstance() {
174 CHECK(instance_ != NULL);
175 return instance_;
176 }
177
Destroy()178 void DoubleLoType::Destroy() {
179 if (instance_ != NULL) {
180 delete instance_;
181 instance_ = NULL;
182 }
183 }
184
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)185 LongLoType* LongLoType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
186 uint16_t cache_id) {
187 if (instance_ == NULL) {
188 instance_ = new LongLoType(klass, descriptor, cache_id);
189 }
190 return instance_;
191 }
192
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)193 LongHiType* LongHiType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
194 uint16_t cache_id) {
195 if (instance_ == NULL) {
196 instance_ = new LongHiType(klass, descriptor, cache_id);
197 }
198 return instance_;
199 }
200
GetInstance()201 LongHiType* LongHiType::GetInstance() {
202 CHECK(instance_ != NULL);
203 return instance_;
204 }
205
Destroy()206 void LongHiType::Destroy() {
207 if (instance_ != NULL) {
208 delete instance_;
209 instance_ = NULL;
210 }
211 }
212
GetInstance()213 LongLoType* LongLoType::GetInstance() {
214 CHECK(instance_ != NULL);
215 return instance_;
216 }
217
Destroy()218 void LongLoType::Destroy() {
219 if (instance_ != NULL) {
220 delete instance_;
221 instance_ = NULL;
222 }
223 }
224
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)225 FloatType* FloatType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
226 uint16_t cache_id) {
227 if (instance_ == NULL) {
228 instance_ = new FloatType(klass, descriptor, cache_id);
229 }
230 return instance_;
231 }
GetInstance()232 FloatType* FloatType::GetInstance() {
233 CHECK(instance_ != NULL);
234 return instance_;
235 }
236
Destroy()237 void FloatType::Destroy() {
238 if (instance_ != NULL) {
239 delete instance_;
240 instance_ = NULL;
241 }
242 }
243
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)244 CharType* CharType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
245 uint16_t cache_id) {
246 if (instance_ == NULL) {
247 instance_ = new CharType(klass, descriptor, cache_id);
248 }
249 return instance_;
250 }
251
GetInstance()252 CharType* CharType::GetInstance() {
253 CHECK(instance_ != NULL);
254 return instance_;
255 }
256
Destroy()257 void CharType::Destroy() {
258 if (instance_ != NULL) {
259 delete instance_;
260 instance_ = NULL;
261 }
262 }
263
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)264 ShortType* ShortType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
265 uint16_t cache_id) {
266 if (instance_ == NULL) {
267 instance_ = new ShortType(klass, descriptor, cache_id);
268 }
269 return instance_;
270 }
271
GetInstance()272 ShortType* ShortType::GetInstance() {
273 CHECK(instance_ != NULL);
274 return instance_;
275 }
276
Destroy()277 void ShortType::Destroy() {
278 if (instance_ != NULL) {
279 delete instance_;
280 instance_ = NULL;
281 }
282 }
283
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)284 ByteType* ByteType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
285 uint16_t cache_id) {
286 if (instance_ == NULL) {
287 instance_ = new ByteType(klass, descriptor, cache_id);
288 }
289 return instance_;
290 }
291
GetInstance()292 ByteType* ByteType::GetInstance() {
293 CHECK(instance_ != NULL);
294 return instance_;
295 }
296
Destroy()297 void ByteType::Destroy() {
298 if (instance_ != NULL) {
299 delete instance_;
300 instance_ = NULL;
301 }
302 }
303
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)304 IntegerType* IntegerType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
305 uint16_t cache_id) {
306 if (instance_ == NULL) {
307 instance_ = new IntegerType(klass, descriptor, cache_id);
308 }
309 return instance_;
310 }
311
GetInstance()312 IntegerType* IntegerType::GetInstance() {
313 CHECK(instance_ != NULL);
314 return instance_;
315 }
316
Destroy()317 void IntegerType::Destroy() {
318 if (instance_ != NULL) {
319 delete instance_;
320 instance_ = NULL;
321 }
322 }
323
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)324 ConflictType* ConflictType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
325 uint16_t cache_id) {
326 if (instance_ == NULL) {
327 instance_ = new ConflictType(klass, descriptor, cache_id);
328 }
329 return instance_;
330 }
331
GetInstance()332 ConflictType* ConflictType::GetInstance() {
333 CHECK(instance_ != NULL);
334 return instance_;
335 }
336
Destroy()337 void ConflictType::Destroy() {
338 if (instance_ != NULL) {
339 delete instance_;
340 instance_ = NULL;
341 }
342 }
343
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)344 BooleanType* BooleanType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
345 uint16_t cache_id) {
346 if (BooleanType::instance == NULL) {
347 instance = new BooleanType(klass, descriptor, cache_id);
348 }
349 return BooleanType::instance;
350 }
351
GetInstance()352 BooleanType* BooleanType::GetInstance() {
353 CHECK(BooleanType::instance != NULL);
354 return BooleanType::instance;
355 }
356
Destroy()357 void BooleanType::Destroy() {
358 if (BooleanType::instance != NULL) {
359 delete instance;
360 instance = NULL;
361 }
362 }
363
Dump()364 std::string UndefinedType::Dump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
365 return "Undefined";
366 }
367
CreateInstance(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)368 UndefinedType* UndefinedType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
369 uint16_t cache_id) {
370 if (instance_ == NULL) {
371 instance_ = new UndefinedType(klass, descriptor, cache_id);
372 }
373 return instance_;
374 }
375
GetInstance()376 UndefinedType* UndefinedType::GetInstance() {
377 CHECK(instance_ != NULL);
378 return instance_;
379 }
380
Destroy()381 void UndefinedType::Destroy() {
382 if (instance_ != NULL) {
383 delete instance_;
384 instance_ = NULL;
385 }
386 }
387
PreciseReferenceType(mirror::Class * klass,const std::string & descriptor,uint16_t cache_id)388 PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, const std::string& descriptor,
389 uint16_t cache_id)
390 : RegType(klass, descriptor, cache_id) {
391 DCHECK(klass->IsInstantiable());
392 }
393
Dump()394 std::string UnresolvedMergedType::Dump() {
395 std::stringstream result;
396 std::set<uint16_t> types = GetMergedTypes();
397 result << "UnresolvedMergedReferences(";
398 auto it = types.begin();
399 result << reg_type_cache_->GetFromId(*it).Dump();
400 for (++it; it != types.end(); ++it) {
401 result << ", ";
402 result << reg_type_cache_->GetFromId(*it).Dump();
403 }
404 result << ")";
405 return result.str();
406 }
407
Dump()408 std::string UnresolvedSuperClass::Dump() {
409 std::stringstream result;
410 uint16_t super_type_id = GetUnresolvedSuperClassChildId();
411 result << "UnresolvedSuperClass(" << reg_type_cache_->GetFromId(super_type_id).Dump() << ")";
412 return result.str();
413 }
414
Dump()415 std::string UnresolvedReferenceType::Dump() {
416 std::stringstream result;
417 result << "Unresolved Reference" << ": " << PrettyDescriptor(GetDescriptor().c_str());
418 return result.str();
419 }
420
Dump()421 std::string UnresolvedUninitializedRefType::Dump() {
422 std::stringstream result;
423 result << "Unresolved And Uninitialized Reference" << ": "
424 << PrettyDescriptor(GetDescriptor().c_str())
425 << " Allocation PC: " << GetAllocationPc();
426 return result.str();
427 }
428
Dump()429 std::string UnresolvedUninitializedThisRefType::Dump() {
430 std::stringstream result;
431 result << "Unresolved And Uninitialized This Reference"
432 << PrettyDescriptor(GetDescriptor().c_str());
433 return result.str();
434 }
435
Dump()436 std::string ReferenceType::Dump() {
437 std::stringstream result;
438 result << "Reference" << ": " << PrettyDescriptor(GetClass());
439 return result.str();
440 }
441
Dump()442 std::string PreciseReferenceType::Dump() {
443 std::stringstream result;
444 result << "Precise Reference" << ": "<< PrettyDescriptor(GetClass());
445 return result.str();
446 }
447
Dump()448 std::string UninitializedReferenceType::Dump() {
449 std::stringstream result;
450 result << "Uninitialized Reference" << ": " << PrettyDescriptor(GetClass());
451 result << " Allocation PC: " << GetAllocationPc();
452 return result.str();
453 }
454
Dump()455 std::string UninitializedThisReferenceType::Dump() {
456 std::stringstream result;
457 result << "Uninitialized This Reference" << ": " << PrettyDescriptor(GetClass());
458 result << "Allocation PC: " << GetAllocationPc();
459 return result.str();
460 }
461
Dump()462 std::string ImpreciseConstType::Dump() {
463 std::stringstream result;
464 uint32_t val = ConstantValue();
465 if (val == 0) {
466 result << "Zero/null";
467 } else {
468 result << "Imprecise ";
469 if (IsConstantShort()) {
470 result << StringPrintf("Constant: %d", val);
471 } else {
472 result << StringPrintf("Constant: 0x%x", val);
473 }
474 }
475 return result.str();
476 }
Dump()477 std::string PreciseConstLoType::Dump() {
478 std::stringstream result;
479
480 int32_t val = ConstantValueLo();
481 result << "Precise ";
482 if (val >= std::numeric_limits<jshort>::min() &&
483 val <= std::numeric_limits<jshort>::max()) {
484 result << StringPrintf("Low-half Constant: %d", val);
485 } else {
486 result << StringPrintf("Low-half Constant: 0x%x", val);
487 }
488 return result.str();
489 }
490
Dump()491 std::string ImpreciseConstLoType::Dump() {
492 std::stringstream result;
493
494 int32_t val = ConstantValueLo();
495 result << "Imprecise ";
496 if (val >= std::numeric_limits<jshort>::min() &&
497 val <= std::numeric_limits<jshort>::max()) {
498 result << StringPrintf("Low-half Constant: %d", val);
499 } else {
500 result << StringPrintf("Low-half Constant: 0x%x", val);
501 }
502 return result.str();
503 }
504
Dump()505 std::string PreciseConstHiType::Dump() {
506 std::stringstream result;
507 int32_t val = ConstantValueHi();
508 result << "Precise ";
509 if (val >= std::numeric_limits<jshort>::min() &&
510 val <= std::numeric_limits<jshort>::max()) {
511 result << StringPrintf("High-half Constant: %d", val);
512 } else {
513 result << StringPrintf("High-half Constant: 0x%x", val);
514 }
515 return result.str();
516 }
517
Dump()518 std::string ImpreciseConstHiType::Dump() {
519 std::stringstream result;
520 int32_t val = ConstantValueHi();
521 result << "Imprecise ";
522 if (val >= std::numeric_limits<jshort>::min() &&
523 val <= std::numeric_limits<jshort>::max()) {
524 result << StringPrintf("High-half Constant: %d", val);
525 } else {
526 result << StringPrintf("High-half Constant: 0x%x", val);
527 }
528 return result.str();
529 }
530
ConstantType(uint32_t constant,uint16_t cache_id)531 ConstantType::ConstantType(uint32_t constant, uint16_t cache_id)
532 : RegType(NULL, "", cache_id), constant_(constant) {
533 }
534
Merge(RegType & incoming_type,RegTypeCache * reg_types)535 RegType& UndefinedType::Merge(RegType& incoming_type, RegTypeCache* reg_types)
536 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
537 if (incoming_type.IsUndefined()) {
538 return *this; // Undefined MERGE Undefined => Undefined
539 }
540 return reg_types->Conflict();
541 }
542
HighHalf(RegTypeCache * cache) const543 RegType& RegType::HighHalf(RegTypeCache* cache) const {
544 DCHECK(IsLowHalf());
545 if (IsLongLo()) {
546 return cache->LongHi();
547 } else if (IsDoubleLo()) {
548 return cache->DoubleHi();
549 } else {
550 DCHECK(IsImpreciseConstantLo());
551 return cache->FromCat2ConstHi(ConstantValue(), false);
552 }
553 }
554
GetPrimitiveType() const555 Primitive::Type RegType::GetPrimitiveType() const {
556 if (IsNonZeroReferenceTypes()) {
557 return Primitive::kPrimNot;
558 } else if (IsBooleanTypes()) {
559 return Primitive::kPrimBoolean;
560 } else if (IsByteTypes()) {
561 return Primitive::kPrimByte;
562 } else if (IsShortTypes()) {
563 return Primitive::kPrimShort;
564 } else if (IsCharTypes()) {
565 return Primitive::kPrimChar;
566 } else if (IsFloat()) {
567 return Primitive::kPrimFloat;
568 } else if (IsIntegralTypes()) {
569 return Primitive::kPrimInt;
570 } else if (IsDoubleLo()) {
571 return Primitive::kPrimDouble;
572 } else {
573 DCHECK(IsLongTypes());
574 return Primitive::kPrimLong;
575 }
576 }
577
IsUninitializedTypes() const578 bool UninitializedType::IsUninitializedTypes() const {
579 return true;
580 }
581
IsNonZeroReferenceTypes() const582 bool UninitializedType::IsNonZeroReferenceTypes() const {
583 return true;
584 }
585
IsNonZeroReferenceTypes() const586 bool UnresolvedType::IsNonZeroReferenceTypes() const {
587 return true;
588 }
GetMergedTypes() const589 std::set<uint16_t> UnresolvedMergedType::GetMergedTypes() const {
590 std::pair<uint16_t, uint16_t> refs = GetTopMergedTypes();
591 RegType& _left(reg_type_cache_->GetFromId(refs.first));
592 UnresolvedMergedType* left = down_cast<UnresolvedMergedType*>(&_left);
593
594 RegType& _right(reg_type_cache_->GetFromId(refs.second));
595 UnresolvedMergedType* right = down_cast<UnresolvedMergedType*>(&_right);
596
597 std::set<uint16_t> types;
598 if (left->IsUnresolvedMergedReference()) {
599 types = left->GetMergedTypes();
600 } else {
601 types.insert(refs.first);
602 }
603 if (right->IsUnresolvedMergedReference()) {
604 std::set<uint16_t> right_types = right->GetMergedTypes();
605 types.insert(right_types.begin(), right_types.end());
606 } else {
607 types.insert(refs.second);
608 }
609 if (kIsDebugBuild) {
610 for (const auto& type : types) {
611 CHECK(!reg_type_cache_->GetFromId(type).IsUnresolvedMergedReference());
612 }
613 }
614 return types;
615 }
616
GetSuperClass(RegTypeCache * cache)617 RegType& RegType::GetSuperClass(RegTypeCache* cache) {
618 if (!IsUnresolvedTypes()) {
619 mirror::Class* super_klass = GetClass()->GetSuperClass();
620 if (super_klass != NULL) {
621 // A super class of a precise type isn't precise as a precise type indicates the register
622 // holds exactly that type.
623 std::string temp;
624 return cache->FromClass(super_klass->GetDescriptor(&temp), super_klass, false);
625 } else {
626 return cache->Zero();
627 }
628 } else {
629 if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
630 GetDescriptor()[0] == '[') {
631 // Super class of all arrays is Object.
632 return cache->JavaLangObject(true);
633 } else {
634 return cache->FromUnresolvedSuperClass(*this);
635 }
636 }
637 }
638
CanAccess(RegType & other)639 bool RegType::CanAccess(RegType& other) {
640 if (Equals(other)) {
641 return true; // Trivial accessibility.
642 } else {
643 bool this_unresolved = IsUnresolvedTypes();
644 bool other_unresolved = other.IsUnresolvedTypes();
645 if (!this_unresolved && !other_unresolved) {
646 return GetClass()->CanAccess(other.GetClass());
647 } else if (!other_unresolved) {
648 return other.GetClass()->IsPublic(); // Be conservative, only allow if other is public.
649 } else {
650 return false; // More complicated test not possible on unresolved types, be conservative.
651 }
652 }
653 }
654
CanAccessMember(mirror::Class * klass,uint32_t access_flags)655 bool RegType::CanAccessMember(mirror::Class* klass, uint32_t access_flags) {
656 if ((access_flags & kAccPublic) != 0) {
657 return true;
658 }
659 if (!IsUnresolvedTypes()) {
660 return GetClass()->CanAccessMember(klass, access_flags);
661 } else {
662 return false; // More complicated test not possible on unresolved types, be conservative.
663 }
664 }
665
IsObjectArrayTypes()666 bool RegType::IsObjectArrayTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
667 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
668 // Primitive arrays will always resolve
669 DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
670 return descriptor_[0] == '[';
671 } else if (HasClass()) {
672 mirror::Class* type = GetClass();
673 return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
674 } else {
675 return false;
676 }
677 }
678
IsJavaLangObject()679 bool RegType::IsJavaLangObject() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
680 return IsReference() && GetClass()->IsObjectClass();
681 }
682
IsArrayTypes()683 bool RegType::IsArrayTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
684 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
685 return descriptor_[0] == '[';
686 } else if (HasClass()) {
687 return GetClass()->IsArrayClass();
688 } else {
689 return false;
690 }
691 }
692
IsJavaLangObjectArray()693 bool RegType::IsJavaLangObjectArray() {
694 if (HasClass()) {
695 mirror::Class* type = GetClass();
696 return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
697 }
698 return false;
699 }
700
IsInstantiableTypes()701 bool RegType::IsInstantiableTypes() {
702 return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
703 }
704
ImpreciseConstType(uint32_t constat,uint16_t cache_id)705 ImpreciseConstType::ImpreciseConstType(uint32_t constat, uint16_t cache_id)
706 : ConstantType(constat, cache_id) {
707 }
708
AssignableFrom(RegType & lhs,RegType & rhs,bool strict)709 static bool AssignableFrom(RegType& lhs, RegType& rhs, bool strict)
710 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
711 if (lhs.Equals(rhs)) {
712 return true;
713 } else {
714 if (lhs.IsBoolean()) {
715 return rhs.IsBooleanTypes();
716 } else if (lhs.IsByte()) {
717 return rhs.IsByteTypes();
718 } else if (lhs.IsShort()) {
719 return rhs.IsShortTypes();
720 } else if (lhs.IsChar()) {
721 return rhs.IsCharTypes();
722 } else if (lhs.IsInteger()) {
723 return rhs.IsIntegralTypes();
724 } else if (lhs.IsFloat()) {
725 return rhs.IsFloatTypes();
726 } else if (lhs.IsLongLo()) {
727 return rhs.IsLongTypes();
728 } else if (lhs.IsDoubleLo()) {
729 return rhs.IsDoubleTypes();
730 } else {
731 CHECK(lhs.IsReferenceTypes())
732 << "Unexpected register type in IsAssignableFrom: '"
733 << lhs << "' := '" << rhs << "'";
734 if (rhs.IsZero()) {
735 return true; // All reference types can be assigned null.
736 } else if (!rhs.IsReferenceTypes()) {
737 return false; // Expect rhs to be a reference type.
738 } else if (lhs.IsJavaLangObject()) {
739 return true; // All reference types can be assigned to Object.
740 } else if (!strict && !lhs.IsUnresolvedTypes() && lhs.GetClass()->IsInterface()) {
741 // If we're not strict allow assignment to any interface, see comment in ClassJoin.
742 return true;
743 } else if (lhs.IsJavaLangObjectArray()) {
744 return rhs.IsObjectArrayTypes(); // All reference arrays may be assigned to Object[]
745 } else if (lhs.HasClass() && rhs.HasClass() &&
746 lhs.GetClass()->IsAssignableFrom(rhs.GetClass())) {
747 // We're assignable from the Class point-of-view.
748 return true;
749 } else {
750 // Unresolved types are only assignable for null and equality.
751 return false;
752 }
753 }
754 }
755 }
756
IsAssignableFrom(RegType & src)757 bool RegType::IsAssignableFrom(RegType& src) {
758 return AssignableFrom(*this, src, false);
759 }
760
IsStrictlyAssignableFrom(RegType & src)761 bool RegType::IsStrictlyAssignableFrom(RegType& src) {
762 return AssignableFrom(*this, src, true);
763 }
764
ConstantValueLo() const765 int32_t ConstantType::ConstantValueLo() const {
766 DCHECK(IsConstantLo());
767 return constant_;
768 }
769
ConstantValueHi() const770 int32_t ConstantType::ConstantValueHi() const {
771 if (IsConstantHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()) {
772 return constant_;
773 } else {
774 DCHECK(false);
775 return 0;
776 }
777 }
778
SelectNonConstant(RegType & a,RegType & b)779 static RegType& SelectNonConstant(RegType& a, RegType& b) {
780 return a.IsConstantTypes() ? b : a;
781 }
782
Merge(RegType & incoming_type,RegTypeCache * reg_types)783 RegType& RegType::Merge(RegType& incoming_type, RegTypeCache* reg_types) {
784 DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller
785 if (IsConflict()) {
786 return *this; // Conflict MERGE * => Conflict
787 } else if (incoming_type.IsConflict()) {
788 return incoming_type; // * MERGE Conflict => Conflict
789 } else if (IsUndefined() || incoming_type.IsUndefined()) {
790 return reg_types->Conflict(); // Unknown MERGE * => Conflict
791 } else if (IsConstant() && incoming_type.IsConstant()) {
792 int32_t val1 = ConstantValue();
793 int32_t val2 = incoming_type.ConstantValue();
794 if (val1 >= 0 && val2 >= 0) {
795 // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
796 if (val1 >= val2) {
797 if (!IsPreciseConstant()) {
798 return *this;
799 } else {
800 return reg_types->FromCat1Const(val1, false);
801 }
802 } else {
803 if (!incoming_type.IsPreciseConstant()) {
804 return incoming_type;
805 } else {
806 return reg_types->FromCat1Const(val2, false);
807 }
808 }
809 } else if (val1 < 0 && val2 < 0) {
810 // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
811 if (val1 <= val2) {
812 if (!IsPreciseConstant()) {
813 return *this;
814 } else {
815 return reg_types->FromCat1Const(val1, false);
816 }
817 } else {
818 if (!incoming_type.IsPreciseConstant()) {
819 return incoming_type;
820 } else {
821 return reg_types->FromCat1Const(val2, false);
822 }
823 }
824 } else {
825 // Values are +ve and -ve, choose smallest signed type in which they both fit
826 if (IsConstantByte()) {
827 if (incoming_type.IsConstantByte()) {
828 return reg_types->ByteConstant();
829 } else if (incoming_type.IsConstantShort()) {
830 return reg_types->ShortConstant();
831 } else {
832 return reg_types->IntConstant();
833 }
834 } else if (IsConstantShort()) {
835 if (incoming_type.IsConstantShort()) {
836 return reg_types->ShortConstant();
837 } else {
838 return reg_types->IntConstant();
839 }
840 } else {
841 return reg_types->IntConstant();
842 }
843 }
844 } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
845 int32_t val1 = ConstantValueLo();
846 int32_t val2 = incoming_type.ConstantValueLo();
847 return reg_types->FromCat2ConstLo(val1 | val2, false);
848 } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
849 int32_t val1 = ConstantValueHi();
850 int32_t val2 = incoming_type.ConstantValueHi();
851 return reg_types->FromCat2ConstHi(val1 | val2, false);
852 } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
853 if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
854 return reg_types->Boolean(); // boolean MERGE boolean => boolean
855 }
856 if (IsByteTypes() && incoming_type.IsByteTypes()) {
857 return reg_types->Byte(); // byte MERGE byte => byte
858 }
859 if (IsShortTypes() && incoming_type.IsShortTypes()) {
860 return reg_types->Short(); // short MERGE short => short
861 }
862 if (IsCharTypes() && incoming_type.IsCharTypes()) {
863 return reg_types->Char(); // char MERGE char => char
864 }
865 return reg_types->Integer(); // int MERGE * => int
866 } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
867 (IsLongTypes() && incoming_type.IsLongTypes()) ||
868 (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
869 (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
870 (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
871 // check constant case was handled prior to entry
872 DCHECK(!IsConstant() || !incoming_type.IsConstant());
873 // float/long/double MERGE float/long/double_constant => float/long/double
874 return SelectNonConstant(*this, incoming_type);
875 } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
876 if (IsZero() || incoming_type.IsZero()) {
877 return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref
878 } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
879 return reg_types->JavaLangObject(false); // Object MERGE ref => Object
880 } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
881 // We know how to merge an unresolved type with itself, 0 or Object. In this case we
882 // have two sub-classes and don't know how to merge. Create a new string-based unresolved
883 // type that reflects our lack of knowledge and that allows the rest of the unresolved
884 // mechanics to continue.
885 return reg_types->FromUnresolvedMerge(*this, incoming_type);
886 } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
887 // Something that is uninitialized hasn't had its constructor called. Mark any merge
888 // of this type with something that is initialized as conflicting. The cases of a merge
889 // with itself, 0 or Object are handled above.
890 return reg_types->Conflict();
891 } else { // Two reference types, compute Join
892 mirror::Class* c1 = GetClass();
893 mirror::Class* c2 = incoming_type.GetClass();
894 DCHECK(c1 != NULL && !c1->IsPrimitive());
895 DCHECK(c2 != NULL && !c2->IsPrimitive());
896 mirror::Class* join_class = ClassJoin(c1, c2);
897 if (c1 == join_class && !IsPreciseReference()) {
898 return *this;
899 } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
900 return incoming_type;
901 } else {
902 std::string temp;
903 return reg_types->FromClass(join_class->GetDescriptor(&temp), join_class, false);
904 }
905 }
906 } else {
907 return reg_types->Conflict(); // Unexpected types => Conflict
908 }
909 }
910
911 // See comment in reg_type.h
ClassJoin(mirror::Class * s,mirror::Class * t)912 mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
913 DCHECK(!s->IsPrimitive()) << PrettyClass(s);
914 DCHECK(!t->IsPrimitive()) << PrettyClass(t);
915 if (s == t) {
916 return s;
917 } else if (s->IsAssignableFrom(t)) {
918 return s;
919 } else if (t->IsAssignableFrom(s)) {
920 return t;
921 } else if (s->IsArrayClass() && t->IsArrayClass()) {
922 mirror::Class* s_ct = s->GetComponentType();
923 mirror::Class* t_ct = t->GetComponentType();
924 if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
925 // Given the types aren't the same, if either array is of primitive types then the only
926 // common parent is java.lang.Object
927 mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object
928 DCHECK(result->IsObjectClass());
929 return result;
930 }
931 mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
932 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
933 mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), &common_elem);
934 DCHECK(array_class != NULL);
935 return array_class;
936 } else {
937 size_t s_depth = s->Depth();
938 size_t t_depth = t->Depth();
939 // Get s and t to the same depth in the hierarchy
940 if (s_depth > t_depth) {
941 while (s_depth > t_depth) {
942 s = s->GetSuperClass();
943 s_depth--;
944 }
945 } else {
946 while (t_depth > s_depth) {
947 t = t->GetSuperClass();
948 t_depth--;
949 }
950 }
951 // Go up the hierarchy until we get to the common parent
952 while (s != t) {
953 s = s->GetSuperClass();
954 t = t->GetSuperClass();
955 }
956 return s;
957 }
958 }
959
CheckInvariants() const960 void RegType::CheckInvariants() const {
961 if (IsConstant() || IsConstantLo() || IsConstantHi()) {
962 CHECK(descriptor_.empty()) << *this;
963 CHECK(klass_.IsNull()) << *this;
964 }
965 if (!klass_.IsNull()) {
966 CHECK(!descriptor_.empty()) << *this;
967 }
968 }
969
VisitRoots(RootCallback * callback,void * arg)970 void RegType::VisitRoots(RootCallback* callback, void* arg) {
971 klass_.VisitRootIfNonNull(callback, arg, RootInfo(kRootUnknown));
972 }
973
CheckInvariants() const974 void UninitializedThisReferenceType::CheckInvariants() const {
975 CHECK_EQ(GetAllocationPc(), 0U) << *this;
976 }
977
CheckInvariants() const978 void UnresolvedUninitializedThisRefType::CheckInvariants() const {
979 CHECK_EQ(GetAllocationPc(), 0U) << *this;
980 CHECK(!descriptor_.empty()) << *this;
981 CHECK(klass_.IsNull()) << *this;
982 }
983
CheckInvariants() const984 void UnresolvedUninitializedRefType::CheckInvariants() const {
985 CHECK(!descriptor_.empty()) << *this;
986 CHECK(klass_.IsNull()) << *this;
987 }
988
CheckInvariants() const989 void UnresolvedMergedType::CheckInvariants() const {
990 // Unresolved merged types: merged types should be defined.
991 CHECK(descriptor_.empty()) << *this;
992 CHECK(klass_.IsNull()) << *this;
993 CHECK_NE(merged_types_.first, 0U) << *this;
994 CHECK_NE(merged_types_.second, 0U) << *this;
995 }
996
CheckInvariants() const997 void UnresolvedReferenceType::CheckInvariants() const {
998 CHECK(!descriptor_.empty()) << *this;
999 CHECK(klass_.IsNull()) << *this;
1000 }
1001
CheckInvariants() const1002 void UnresolvedSuperClass::CheckInvariants() const {
1003 // Unresolved merged types: merged types should be defined.
1004 CHECK(descriptor_.empty()) << *this;
1005 CHECK(klass_.IsNull()) << *this;
1006 CHECK_NE(unresolved_child_id_, 0U) << *this;
1007 }
1008
operator <<(std::ostream & os,const RegType & rhs)1009 std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
1010 RegType& rhs_non_const = const_cast<RegType&>(rhs);
1011 os << rhs_non_const.Dump();
1012 return os;
1013 }
1014
1015 } // namespace verifier
1016 } // namespace art
1017