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