blob: 0cca343612204c39785d23e58faf2d0653776324 [file] [log] [blame]
Ian Rogers776ac1f2012-04-13 23:36:36 -07001/*
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
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070019#include "dex_file-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "mirror/class.h"
21#include "mirror/class-inl.h"
22#include "mirror/object-inl.h"
Ian Rogers693ff612013-02-01 10:56:12 -080023#include "mirror/object_array-inl.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070024#include "object_utils.h"
25#include "reg_type_cache.h"
26
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080027#include <limits>
28
Ian Rogers776ac1f2012-04-13 23:36:36 -070029namespace art {
30namespace verifier {
31
32static const char* type_strings[] = {
Ian Rogersad0b3a32012-04-16 14:50:24 -070033 "Undefined",
Ian Rogers776ac1f2012-04-13 23:36:36 -070034 "Conflict",
Ian Rogers2bcb4a42012-11-08 10:39:18 -080035 "boolean",
36 "byte",
37 "short",
38 "char",
39 "int",
40 "float",
41 "long (Low Half)",
42 "long (High Half)",
43 "double (Low Half)",
44 "double (High Half)",
45 "Precise 32-bit Constant",
46 "Imprecise 32-bit Constant",
47 "Precise 64-bit Constant (Low Half)",
48 "Precise 64-bit Constant (High Half)",
49 "Imprecise 64-bit Constant (Low Half)",
50 "Imprecise 64-bit Constant (High Half)",
Ian Rogers776ac1f2012-04-13 23:36:36 -070051 "Unresolved Reference",
52 "Uninitialized Reference",
53 "Uninitialized This Reference",
54 "Unresolved And Uninitialized Reference",
Ian Rogersad0b3a32012-04-16 14:50:24 -070055 "Unresolved And Uninitialized This Reference",
Ian Rogers529781d2012-07-23 17:24:29 -070056 "Unresolved Merged References",
57 "Unresolved Super Class",
Ian Rogers776ac1f2012-04-13 23:36:36 -070058 "Reference",
Ian Rogersb4903572012-10-11 11:52:56 -070059 "Precise Reference",
Ian Rogers776ac1f2012-04-13 23:36:36 -070060};
61
Ian Rogers529781d2012-07-23 17:24:29 -070062std::string RegType::Dump(const RegTypeCache* reg_types) const {
Ian Rogersb4903572012-10-11 11:52:56 -070063 DCHECK(type_ >= kRegTypeUndefined && type_ <= kRegTypePreciseReference);
64 DCHECK(arraysize(type_strings) == (kRegTypePreciseReference + 1));
Ian Rogers776ac1f2012-04-13 23:36:36 -070065 std::string result;
Ian Rogers529781d2012-07-23 17:24:29 -070066 if (IsUnresolvedMergedReference()) {
67 if (reg_types == NULL) {
68 std::pair<uint16_t, uint16_t> refs = GetTopMergedTypes();
69 result += StringPrintf("UnresolvedMergedReferences(%d, %d)", refs.first, refs.second);
70 } else {
71 std::set<uint16_t> types = GetMergedTypes(reg_types);
72 result += "UnresolvedMergedReferences(";
73 typedef std::set<uint16_t>::const_iterator It; // TODO: C++0x auto
74 It it = types.begin();
75 result += reg_types->GetFromId(*it).Dump(reg_types);
76 for(++it; it != types.end(); ++it) {
77 result += ", ";
78 result += reg_types->GetFromId(*it).Dump(reg_types);
79 }
80 result += ")";
81 }
82 } else if (IsUnresolvedSuperClass()) {
83 uint16_t super_type_id = GetUnresolvedSuperClassChildId();
84 if (reg_types == NULL) {
85 result += StringPrintf("UnresolvedSuperClass(%d)", super_type_id);
86 } else {
87 result += "UnresolvedSuperClass(";
88 result += reg_types->GetFromId(super_type_id).Dump(reg_types);
89 result += ")";
90 }
91 } else if (IsConstant()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070092 uint32_t val = ConstantValue();
93 if (val == 0) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -080094 CHECK(IsPreciseConstant());
95 result = "Zero/null";
Ian Rogers776ac1f2012-04-13 23:36:36 -070096 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -080097 result = IsPreciseConstant() ? "Precise " : "Imprecise ";
Ian Rogers776ac1f2012-04-13 23:36:36 -070098 if (IsConstantShort()) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -080099 result += StringPrintf("Constant: %d", val);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700100 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800101 result += StringPrintf("Constant: 0x%x", val);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700102 }
103 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800104 } else if (IsConstantLo()) {
105 int32_t val = ConstantValueLo();
106 result = IsPreciseConstantLo() ? "Precise " : "Imprecise ";
107 if (val >= std::numeric_limits<jshort>::min() &&
108 val <= std::numeric_limits<jshort>::max()) {
109 result += StringPrintf("Low-half Constant: %d", val);
110 } else {
111 result += StringPrintf("Low-half Constant: 0x%x", val);
112 }
113 } else if (IsConstantHi()) {
114 int32_t val = ConstantValueHi();
115 result = IsPreciseConstantHi() ? "Precise " : "Imprecise ";
116 if (val >= std::numeric_limits<jshort>::min() &&
117 val <= std::numeric_limits<jshort>::max()) {
118 result += StringPrintf("High-half Constant: %d", val);
119 } else {
120 result += StringPrintf("High-half Constant: 0x%x", val);
121 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700122 } else {
123 result = type_strings[type_];
124 if (IsReferenceTypes()) {
125 result += ": ";
126 if (IsUnresolvedTypes()) {
127 result += PrettyDescriptor(GetDescriptor());
128 } else {
129 result += PrettyDescriptor(GetClass());
130 }
131 }
132 }
133 return result;
134}
135
136const RegType& RegType::HighHalf(RegTypeCache* cache) const {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800137 DCHECK(IsLowHalf());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700138 if (type_ == kRegTypeLongLo) {
139 return cache->FromType(kRegTypeLongHi);
140 } else if (type_ == kRegTypeDoubleLo) {
141 return cache->FromType(kRegTypeDoubleHi);
142 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800143 DCHECK_EQ(type_, kRegTypeImpreciseConstLo);
144 return cache->FromType(kRegTypeImpreciseConstHi);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700145 }
146}
147
Ian Rogers529781d2012-07-23 17:24:29 -0700148std::set<uint16_t> RegType::GetMergedTypes(const RegTypeCache* cache) const {
149 std::pair<uint16_t, uint16_t> refs = GetTopMergedTypes();
150 const RegType& left = cache->GetFromId(refs.first);
151 const RegType& right = cache->GetFromId(refs.second);
152 std::set<uint16_t> types;
153 if (left.IsUnresolvedMergedReference()) {
154 types = left.GetMergedTypes(cache);
155 } else {
156 types.insert(refs.first);
157 }
158 if (right.IsUnresolvedMergedReference()) {
159 std::set<uint16_t> right_types = right.GetMergedTypes(cache);
160 types.insert(right_types.begin(), right_types.end());
161 } else {
162 types.insert(refs.second);
163 }
164#ifndef NDEBUG
165 typedef std::set<uint16_t>::const_iterator It; // TODO: C++0x auto
166 for(It it = types.begin(); it != types.end(); ++it) {
167 CHECK(!cache->GetFromId(*it).IsUnresolvedMergedReference());
168 }
169#endif
170 return types;
171}
172
Ian Rogersad0b3a32012-04-16 14:50:24 -0700173const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
174 if (!IsUnresolvedTypes()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800175 mirror::Class* super_klass = GetClass()->GetSuperClass();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700176 if (super_klass != NULL) {
Ian Rogersb4903572012-10-11 11:52:56 -0700177 return cache->FromClass(super_klass, IsPreciseReference());
Ian Rogers0d604842012-04-16 14:50:24 -0700178 } else {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700179 return cache->Zero();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700180 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700181 } else {
Ian Rogers529781d2012-07-23 17:24:29 -0700182 if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
Elliott Hughes80537bb2013-01-04 16:37:26 -0800183 GetDescriptor()[0] == '[') {
Ian Rogers529781d2012-07-23 17:24:29 -0700184 // Super class of all arrays is Object.
Ian Rogersb4903572012-10-11 11:52:56 -0700185 return cache->JavaLangObject(true);
Ian Rogers529781d2012-07-23 17:24:29 -0700186 } else {
187 return cache->FromUnresolvedSuperClass(*this);
188 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700189 }
190}
191
192bool RegType::CanAccess(const RegType& other) const {
193 if (Equals(other)) {
194 return true; // Trivial accessibility.
195 } else {
196 bool this_unresolved = IsUnresolvedTypes();
197 bool other_unresolved = other.IsUnresolvedTypes();
198 if (!this_unresolved && !other_unresolved) {
199 return GetClass()->CanAccess(other.GetClass());
200 } else if (!other_unresolved) {
201 return other.GetClass()->IsPublic(); // Be conservative, only allow if other is public.
202 } else {
203 return false; // More complicated test not possible on unresolved types, be conservative.
Ian Rogerse1758fe2012-04-19 11:31:15 -0700204 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700205 }
206}
207
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800208bool RegType::CanAccessMember(mirror::Class* klass, uint32_t access_flags) const {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700209 if (access_flags & kAccPublic) {
210 return true;
211 }
212 if (!IsUnresolvedTypes()) {
213 return GetClass()->CanAccessMember(klass, access_flags);
214 } else {
215 return false; // More complicated test not possible on unresolved types, be conservative.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700216 }
217}
218
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800219bool RegType::IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
220 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
221 // Primitive arrays will always resolve
222 DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
223 return descriptor_[0] == '[';
224 } else if (HasClass()) {
225 mirror::Class* type = GetClass();
226 return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
227 } else {
228 return false;
229 }
230}
231
232bool RegType::IsConstantByte() const {
233 return IsConstant() &&
234 ConstantValue() >= std::numeric_limits<jbyte>::min() &&
235 ConstantValue() <= std::numeric_limits<jbyte>::max();
236}
237
238bool RegType::IsConstantShort() const {
239 return IsConstant() &&
240 ConstantValue() >= std::numeric_limits<jshort>::min() &&
241 ConstantValue() <= std::numeric_limits<jshort>::max();
242}
243
244bool RegType::IsConstantChar() const {
245 return IsConstant() && ConstantValue() >= 0 &&
246 ConstantValue() <= std::numeric_limits<jchar>::max();
247}
248
249bool RegType::IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
250 return IsReference() && GetClass()->IsObjectClass();
251}
252
253bool RegType::IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
254 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
255 return descriptor_[0] == '[';
256 } else if (HasClass()) {
257 return GetClass()->IsArrayClass();
258 } else {
259 return false;
260 }
261}
262
263bool RegType::IsJavaLangObjectArray() const {
264 if (HasClass()) {
265 mirror::Class* type = GetClass();
266 return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
267 }
268 return false;
269}
270
271bool RegType::IsInstantiableTypes() const {
272 return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
273}
274
Ian Rogers776ac1f2012-04-13 23:36:36 -0700275bool RegType::IsAssignableFrom(const RegType& src) const {
276 if (Equals(src)) {
277 return true;
278 } else {
279 switch (GetType()) {
280 case RegType::kRegTypeBoolean: return src.IsBooleanTypes();
281 case RegType::kRegTypeByte: return src.IsByteTypes();
282 case RegType::kRegTypeShort: return src.IsShortTypes();
283 case RegType::kRegTypeChar: return src.IsCharTypes();
284 case RegType::kRegTypeInteger: return src.IsIntegralTypes();
285 case RegType::kRegTypeFloat: return src.IsFloatTypes();
286 case RegType::kRegTypeLongLo: return src.IsLongTypes();
287 case RegType::kRegTypeDoubleLo: return src.IsDoubleTypes();
288 default:
289 if (!IsReferenceTypes()) {
290 LOG(FATAL) << "Unexpected register type in IsAssignableFrom: '" << src << "'";
291 }
292 if (src.IsZero()) {
293 return true; // all reference types can be assigned null
294 } else if (!src.IsReferenceTypes()) {
295 return false; // expect src to be a reference type
296 } else if (IsJavaLangObject()) {
297 return true; // all reference types can be assigned to Object
298 } else if (!IsUnresolvedTypes() && GetClass()->IsInterface()) {
299 return true; // We allow assignment to any interface, see comment in ClassJoin
300 } else if (IsJavaLangObjectArray()) {
301 return src.IsObjectArrayTypes(); // All reference arrays may be assigned to Object[]
302 } else if (!IsUnresolvedTypes() && !src.IsUnresolvedTypes() &&
303 GetClass()->IsAssignableFrom(src.GetClass())) {
304 // We're assignable from the Class point-of-view
305 return true;
306 } else {
Ian Rogers529781d2012-07-23 17:24:29 -0700307 // TODO: unresolved types are only assignable for null, Object and equality currently.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700308 return false;
309 }
310 }
311 }
312}
313
314static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
315 return a.IsConstant() ? b : a;
316}
317
318const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
319 DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller
Ian Rogersad0b3a32012-04-16 14:50:24 -0700320 if (IsUndefined() && incoming_type.IsUndefined()) {
321 return *this; // Undefined MERGE Undefined => Undefined
Ian Rogers776ac1f2012-04-13 23:36:36 -0700322 } else if (IsConflict()) {
323 return *this; // Conflict MERGE * => Conflict
324 } else if (incoming_type.IsConflict()) {
325 return incoming_type; // * MERGE Conflict => Conflict
Ian Rogersad0b3a32012-04-16 14:50:24 -0700326 } else if (IsUndefined() || incoming_type.IsUndefined()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700327 return reg_types->Conflict(); // Unknown MERGE * => Conflict
328 } else if (IsConstant() && incoming_type.IsConstant()) {
329 int32_t val1 = ConstantValue();
330 int32_t val2 = incoming_type.ConstantValue();
331 if (val1 >= 0 && val2 >= 0) {
332 // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
333 if (val1 >= val2) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800334 if (!IsPreciseConstant()) {
335 return *this;
336 } else {
337 return reg_types->FromCat1Const(val1, false);
338 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700339 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800340 if (!incoming_type.IsPreciseConstant()) {
341 return incoming_type;
342 } else {
343 return reg_types->FromCat1Const(val2, false);
344 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700345 }
346 } else if (val1 < 0 && val2 < 0) {
347 // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
348 if (val1 <= val2) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800349 if (!IsPreciseConstant()) {
350 return *this;
351 } else {
352 return reg_types->FromCat1Const(val1, false);
353 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700354 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800355 if (!incoming_type.IsPreciseConstant()) {
356 return incoming_type;
357 } else {
358 return reg_types->FromCat1Const(val2, false);
359 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700360 }
361 } else {
362 // Values are +ve and -ve, choose smallest signed type in which they both fit
363 if (IsConstantByte()) {
364 if (incoming_type.IsConstantByte()) {
365 return reg_types->ByteConstant();
366 } else if (incoming_type.IsConstantShort()) {
367 return reg_types->ShortConstant();
368 } else {
369 return reg_types->IntConstant();
370 }
371 } else if (IsConstantShort()) {
372 if (incoming_type.IsConstantShort()) {
373 return reg_types->ShortConstant();
374 } else {
375 return reg_types->IntConstant();
376 }
377 } else {
378 return reg_types->IntConstant();
379 }
380 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800381 } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
382 int32_t val1 = ConstantValueLo();
383 int32_t val2 = incoming_type.ConstantValueLo();
384 return reg_types->FromCat2ConstLo(val1 | val2, false);
385 } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
386 int32_t val1 = ConstantValueHi();
387 int32_t val2 = incoming_type.ConstantValueHi();
388 return reg_types->FromCat2ConstHi(val1 | val2, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700389 } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
390 if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
391 return reg_types->Boolean(); // boolean MERGE boolean => boolean
392 }
393 if (IsByteTypes() && incoming_type.IsByteTypes()) {
394 return reg_types->Byte(); // byte MERGE byte => byte
395 }
396 if (IsShortTypes() && incoming_type.IsShortTypes()) {
397 return reg_types->Short(); // short MERGE short => short
398 }
399 if (IsCharTypes() && incoming_type.IsCharTypes()) {
400 return reg_types->Char(); // char MERGE char => char
401 }
402 return reg_types->Integer(); // int MERGE * => int
403 } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
404 (IsLongTypes() && incoming_type.IsLongTypes()) ||
405 (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
406 (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
407 (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
408 // check constant case was handled prior to entry
409 DCHECK(!IsConstant() || !incoming_type.IsConstant());
410 // float/long/double MERGE float/long/double_constant => float/long/double
411 return SelectNonConstant(*this, incoming_type);
412 } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
413 if (IsZero() || incoming_type.IsZero()) {
414 return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref
415 } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
Ian Rogersb4903572012-10-11 11:52:56 -0700416 return reg_types->JavaLangObject(false); // Object MERGE ref => Object
Ian Rogers529781d2012-07-23 17:24:29 -0700417 } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
418 // We know how to merge an unresolved type with itself, 0 or Object. In this case we
419 // have two sub-classes and don't know how to merge. Create a new string-based unresolved
420 // type that reflects our lack of knowledge and that allows the rest of the unresolved
421 // mechanics to continue.
422 return reg_types->FromUnresolvedMerge(*this, incoming_type);
423 } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
424 // Something that is uninitialized hasn't had its constructor called. Mark any merge
425 // of this type with something that is initialized as conflicting. The cases of a merge
426 // with itself, 0 or Object are handled above.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700427 return reg_types->Conflict();
428 } else { // Two reference types, compute Join
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800429 mirror::Class* c1 = GetClass();
430 mirror::Class* c2 = incoming_type.GetClass();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700431 DCHECK(c1 != NULL && !c1->IsPrimitive());
432 DCHECK(c2 != NULL && !c2->IsPrimitive());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800433 mirror::Class* join_class = ClassJoin(c1, c2);
Ian Rogersb4903572012-10-11 11:52:56 -0700434 if (c1 == join_class && !IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700435 return *this;
Ian Rogersb4903572012-10-11 11:52:56 -0700436 } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700437 return incoming_type;
438 } else {
Ian Rogersb4903572012-10-11 11:52:56 -0700439 return reg_types->FromClass(join_class, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700440 }
441 }
442 } else {
443 return reg_types->Conflict(); // Unexpected types => Conflict
444 }
445}
446
Ian Rogersad0b3a32012-04-16 14:50:24 -0700447// See comment in reg_type.h
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800448mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700449 DCHECK(!s->IsPrimitive()) << PrettyClass(s);
450 DCHECK(!t->IsPrimitive()) << PrettyClass(t);
451 if (s == t) {
452 return s;
453 } else if (s->IsAssignableFrom(t)) {
454 return s;
455 } else if (t->IsAssignableFrom(s)) {
456 return t;
457 } else if (s->IsArrayClass() && t->IsArrayClass()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800458 mirror::Class* s_ct = s->GetComponentType();
459 mirror::Class* t_ct = t->GetComponentType();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700460 if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
461 // Given the types aren't the same, if either array is of primitive types then the only
462 // common parent is java.lang.Object
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800463 mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object
Ian Rogersad0b3a32012-04-16 14:50:24 -0700464 DCHECK(result->IsObjectClass());
465 return result;
466 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800467 mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700468 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800469 mirror::ClassLoader* class_loader = s->GetClassLoader();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700470 std::string descriptor("[");
471 descriptor += ClassHelper(common_elem).GetDescriptor();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800472 mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700473 DCHECK(array_class != NULL);
474 return array_class;
475 } else {
476 size_t s_depth = s->Depth();
477 size_t t_depth = t->Depth();
478 // Get s and t to the same depth in the hierarchy
479 if (s_depth > t_depth) {
480 while (s_depth > t_depth) {
481 s = s->GetSuperClass();
482 s_depth--;
483 }
484 } else {
485 while (t_depth > s_depth) {
486 t = t->GetSuperClass();
487 t_depth--;
488 }
489 }
490 // Go up the hierarchy until we get to the common parent
491 while (s != t) {
492 s = s->GetSuperClass();
493 t = t->GetSuperClass();
494 }
495 return s;
496 }
497}
498
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800499void RegType::CheckInvariants() const {
500 bool checked = false;
501 if (IsConstant() || IsConstantLo() || IsConstantHi()) {
502 // Constants: allocation_pc_or_constant_or_merged_types_ will hold the constant value, nothing
503 // else should be defined.
504 CHECK(descriptor_.empty()) << *this;
505 CHECK(klass_ == NULL) << *this;
506 checked = true;
507 }
508 if (IsUnresolvedTypes()) {
Ian Rogers55c9c4b2013-01-30 17:45:13 -0800509 if (IsUnresolvedMergedReference() || IsUnresolvedSuperClass()) {
510 // Unresolved super/merged types: allocation pc/merged types should be defined.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800511 CHECK(descriptor_.empty()) << *this;
512 CHECK(klass_ == NULL) << *this;
513 CHECK_NE(allocation_pc_or_constant_or_merged_types_, 0U) << *this;
514 } else {
515 // Unresolved types: have a descriptor and no allocation pc/merged types.
516 CHECK(!descriptor_.empty()) << *this;
517 CHECK(klass_ == NULL) << *this;
518 if (!IsUnresolvedAndUninitializedReference()) {
519 CHECK_EQ(allocation_pc_or_constant_or_merged_types_, 0U) << *this;
520 }
521 }
522 checked = true;
523 }
524 if (IsReferenceTypes() && !checked) {
525 // A resolved reference type.
526 CHECK(descriptor_.empty()) << *this;
527 CHECK(klass_ != NULL) << *this;
528 CHECK(klass_->IsClass()) << *this;
529 if (!IsUninitializedReference()) {
530 CHECK_EQ(allocation_pc_or_constant_or_merged_types_, 0U) << *this;
531 }
532 }
533 CHECK(checked = true);
534}
535
536std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700537 os << rhs.Dump();
538 return os;
539}
540
Elliott Hughesa21039c2012-06-21 12:09:25 -0700541} // namespace verifier
542} // namespace art