blob: e24c92091c010fda2af6a34cd9c4151f740ddbc5 [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
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080019
20#include "base/casts.h"
Ian Rogers98379392014-02-24 16:53:16 -080021#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070022#include "dex_file-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080023#include "mirror/class.h"
24#include "mirror/class-inl.h"
25#include "mirror/object-inl.h"
Ian Rogers693ff612013-02-01 10:56:12 -080026#include "mirror/object_array-inl.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070027#include "object_utils.h"
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080028#include "reg_type_cache-inl.h"
Ian Rogers637c65b2013-05-31 11:46:00 -070029#include "scoped_thread_state_change.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070030
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080031#include <limits>
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080032#include <sstream>
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080033
Ian Rogers776ac1f2012-04-13 23:36:36 -070034namespace art {
35namespace verifier {
36
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080037UndefinedType* UndefinedType::instance_ = NULL;
38ConflictType* ConflictType::instance_ = NULL;
39BooleanType* BooleanType::instance = NULL;
40ByteType* ByteType::instance_ = NULL;
41ShortType* ShortType::instance_ = NULL;
42CharType* CharType::instance_ = NULL;
43FloatType* FloatType::instance_ = NULL;
44LongLoType* LongLoType::instance_ = NULL;
45LongHiType* LongHiType::instance_ = NULL;
46DoubleLoType* DoubleLoType::instance_ = NULL;
47DoubleHiType* DoubleHiType::instance_ = NULL;
48IntegerType* IntegerType::instance_ = NULL;
Ian Rogers776ac1f2012-04-13 23:36:36 -070049
Ian Rogers637c65b2013-05-31 11:46:00 -070050int32_t RegType::ConstantValue() const {
51 ScopedObjectAccess soa(Thread::Current());
52 LOG(FATAL) << "Unexpected call to ConstantValue: " << *this;
53 return 0;
54}
55
56int32_t RegType::ConstantValueLo() const {
57 ScopedObjectAccess soa(Thread::Current());
58 LOG(FATAL) << "Unexpected call to ConstantValueLo: " << *this;
59 return 0;
60}
61
62int32_t RegType::ConstantValueHi() const {
63 ScopedObjectAccess soa(Thread::Current());
64 LOG(FATAL) << "Unexpected call to ConstantValueHi: " << *this;
65 return 0;
66}
67
68PrimitiveType::PrimitiveType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
69 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
70 : RegType(klass, descriptor, cache_id) {
71 CHECK(klass != NULL);
72 CHECK(!descriptor.empty());
73}
74
75Cat1Type::Cat1Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
76 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
77 : PrimitiveType(klass, descriptor, cache_id) {
78}
79
80Cat2Type::Cat2Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
81 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
82 : PrimitiveType(klass, descriptor, cache_id) {
83}
84
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080085std::string PreciseConstType::Dump() const {
86 std::stringstream result;
87 uint32_t val = ConstantValue();
88 if (val == 0) {
89 CHECK(IsPreciseConstant());
90 result << "Zero/null";
Ian Rogers776ac1f2012-04-13 23:36:36 -070091 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080092 result << "Precise ";
93 if (IsConstantShort()) {
94 result << StringPrintf("Constant: %d", val);
95 } else {
96 result << StringPrintf("Constant: 0x%x", val);
Ian Rogers776ac1f2012-04-13 23:36:36 -070097 }
98 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080099 return result.str();
100}
101
102std::string BooleanType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700103 return "Boolean";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800104}
105
106std::string ConflictType::Dump() const {
107 return "Conflict";
108}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700109
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800110std::string ByteType::Dump() const {
111 return "Byte";
112}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700113
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800114std::string ShortType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700115 return "Short";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800116}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700117
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800118std::string CharType::Dump() const {
119 return "Char";
120}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700121
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800122std::string FloatType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700123 return "Float";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800124}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700125
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800126std::string LongLoType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700127 return "Long (Low Half)";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800128}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700129
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800130std::string LongHiType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700131 return "Long (High Half)";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800132}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700133
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800134std::string DoubleLoType::Dump() const {
135 return "Double (Low Half)";
136}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700137
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800138std::string DoubleHiType::Dump() const {
139 return "Double (High Half)";
140}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700141
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800142std::string IntegerType::Dump() const {
143 return "Integer";
144}
145
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700146DoubleHiType* DoubleHiType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800147 uint16_t cache_id) {
148 if (instance_ == NULL) {
149 instance_ = new DoubleHiType(klass, descriptor, cache_id);
150 }
151 return instance_;
152}
153
154DoubleHiType* DoubleHiType::GetInstance() {
155 CHECK(instance_ != NULL);
156 return instance_;
157}
158
159void DoubleHiType::Destroy() {
160 if (instance_ != NULL) {
161 delete instance_;
162 instance_ = NULL;
163 }
164}
165
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700166DoubleLoType* DoubleLoType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800167 uint16_t cache_id) {
168 if (instance_ == NULL) {
169 instance_ = new DoubleLoType(klass, descriptor, cache_id);
170 }
171 return instance_;
172}
173
174DoubleLoType* DoubleLoType::GetInstance() {
175 CHECK(instance_ != NULL);
176 return instance_;
177}
178
179void DoubleLoType::Destroy() {
180 if (instance_ != NULL) {
181 delete instance_;
182 instance_ = NULL;
183 }
184}
185
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700186LongLoType* LongLoType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800187 uint16_t cache_id) {
188 if (instance_ == NULL) {
189 instance_ = new LongLoType(klass, descriptor, cache_id);
190 }
191 return instance_;
192}
193
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700194LongHiType* LongHiType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800195 uint16_t cache_id) {
196 if (instance_ == NULL) {
197 instance_ = new LongHiType(klass, descriptor, cache_id);
198 }
199 return instance_;
200}
201
202LongHiType* LongHiType::GetInstance() {
203 CHECK(instance_ != NULL);
204 return instance_;
205}
206
207void LongHiType::Destroy() {
208 if (instance_ != NULL) {
209 delete instance_;
210 instance_ = NULL;
211 }
212}
213
214LongLoType* LongLoType::GetInstance() {
Brian Carlstromdf629502013-07-17 22:39:56 -0700215 CHECK(instance_ != NULL);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800216 return instance_;
217}
218
219void LongLoType::Destroy() {
220 if (instance_ != NULL) {
221 delete instance_;
222 instance_ = NULL;
223 }
224}
225
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700226FloatType* FloatType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
227 uint16_t cache_id) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800228 if (instance_ == NULL) {
229 instance_ = new FloatType(klass, descriptor, cache_id);
230 }
231 return instance_;
232}
233FloatType* FloatType::GetInstance() {
234 CHECK(instance_ != NULL);
235 return instance_;
236}
237
238void FloatType::Destroy() {
239 if (instance_ != NULL) {
240 delete instance_;
241 instance_ = NULL;
242 }
243}
244
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700245CharType* CharType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800246 uint16_t cache_id) {
247 if (instance_ == NULL) {
248 instance_ = new CharType(klass, descriptor, cache_id);
249 }
250 return instance_;
251}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700252
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800253CharType* CharType::GetInstance() {
254 CHECK(instance_ != NULL);
255 return instance_;
256}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700257
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800258void CharType::Destroy() {
259 if (instance_ != NULL) {
260 delete instance_;
261 instance_ = NULL;
262 }
263}
264
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700265ShortType* ShortType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800266 uint16_t cache_id) {
267 if (instance_ == NULL) {
268 instance_ = new ShortType(klass, descriptor, cache_id);
269 }
270 return instance_;
271}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700272
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800273ShortType* ShortType::GetInstance() {
274 CHECK(instance_ != NULL);
275 return instance_;
276}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700277
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800278void ShortType::Destroy() {
279 if (instance_ != NULL) {
280 delete instance_;
281 instance_ = NULL;
282 }
283}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700284
285ByteType* ByteType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
286 uint16_t cache_id) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800287 if (instance_ == NULL) {
288 instance_ = new ByteType(klass, descriptor, cache_id);
289 }
290 return instance_;
291}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700292
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800293ByteType* ByteType::GetInstance() {
294 CHECK(instance_ != NULL);
295 return instance_;
296}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700297
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800298void ByteType::Destroy() {
299 if (instance_ != NULL) {
300 delete instance_;
301 instance_ = NULL;
302 }
303}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700304
305IntegerType* IntegerType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800306 uint16_t cache_id) {
307 if (instance_ == NULL) {
308 instance_ = new IntegerType(klass, descriptor, cache_id);
309 }
310 return instance_;
311}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700312
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800313IntegerType* IntegerType::GetInstance() {
314 CHECK(instance_ != NULL);
315 return instance_;
316}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700317
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800318void IntegerType::Destroy() {
319 if (instance_ != NULL) {
320 delete instance_;
321 instance_ = NULL;
322 }
323}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700324
325ConflictType* ConflictType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800326 uint16_t cache_id) {
327 if (instance_ == NULL) {
328 instance_ = new ConflictType(klass, descriptor, cache_id);
329 }
330 return instance_;
331}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700332
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800333ConflictType* ConflictType::GetInstance() {
334 CHECK(instance_ != NULL);
335 return instance_;
336}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700337
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800338void ConflictType::Destroy() {
339 if (instance_ != NULL) {
340 delete instance_;
341 instance_ = NULL;
342 }
343}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700344
345BooleanType* BooleanType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800346 uint16_t cache_id) {
347 if (BooleanType::instance == NULL) {
348 instance = new BooleanType(klass, descriptor, cache_id);
349 }
350 return BooleanType::instance;
351}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700352
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800353BooleanType* BooleanType::GetInstance() {
354 CHECK(BooleanType::instance != NULL);
355 return BooleanType::instance;
356}
357
358void BooleanType::Destroy() {
Brian Carlstromdf629502013-07-17 22:39:56 -0700359 if (BooleanType::instance != NULL) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800360 delete instance;
361 instance = NULL;
362 }
363}
364
365std::string UndefinedType::Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
366 return "Undefined";
367}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700368
369UndefinedType* UndefinedType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800370 uint16_t cache_id) {
371 if (instance_ == NULL) {
372 instance_ = new UndefinedType(klass, descriptor, cache_id);
373 }
374 return instance_;
375}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700376
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800377UndefinedType* UndefinedType::GetInstance() {
378 CHECK(instance_ != NULL);
379 return instance_;
380}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700381
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800382void UndefinedType::Destroy() {
383 if (instance_ != NULL) {
384 delete instance_;
385 instance_ = NULL;
386 }
387}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700388
Ian Rogers637c65b2013-05-31 11:46:00 -0700389PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, const std::string& descriptor,
390 uint16_t cache_id)
391 : RegType(klass, descriptor, cache_id) {
392 DCHECK(klass->IsInstantiable());
393}
394
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800395std::string UnresolvedMergedType::Dump() const {
396 std::stringstream result;
397 std::set<uint16_t> types = GetMergedTypes();
398 result << "UnresolvedMergedReferences(";
Mathieu Chartier02e25112013-08-14 16:14:24 -0700399 auto it = types.begin();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800400 result << reg_type_cache_->GetFromId(*it).Dump();
401 for (++it; it != types.end(); ++it) {
402 result << ", ";
403 result << reg_type_cache_->GetFromId(*it).Dump();
404 }
405 result << ")";
406 return result.str();
407}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700408
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800409std::string UnresolvedSuperClass::Dump() const {
410 std::stringstream result;
411 uint16_t super_type_id = GetUnresolvedSuperClassChildId();
412 result << "UnresolvedSuperClass(" << reg_type_cache_->GetFromId(super_type_id).Dump() << ")";
413 return result.str();
414}
415
416std::string UnresolvedReferenceType::Dump() const {
417 std::stringstream result;
418 result << "Unresolved Reference" << ": " << PrettyDescriptor(GetDescriptor());
419 return result.str();
420}
421
422std::string UnresolvedUninitializedRefType::Dump() const {
423 std::stringstream result;
424 result << "Unresolved And Uninitialized Reference" << ": " << PrettyDescriptor(GetDescriptor());
425 result << " Allocation PC: " << GetAllocationPc();
426 return result.str();
427}
428
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700429std::string UnresolvedUninitializedThisRefType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800430 std::stringstream result;
431 result << "Unresolved And Uninitialized This Reference" << PrettyDescriptor(GetDescriptor());
432 return result.str();
433}
434
435std::string ReferenceType::Dump() const {
436 std::stringstream result;
437 result << "Reference" << ": " << PrettyDescriptor(GetClass());
438 return result.str();
439}
440
441std::string PreciseReferenceType::Dump() const {
442 std::stringstream result;
443 result << "Precise Reference" << ": "<< PrettyDescriptor(GetClass());
444 return result.str();
445}
446
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700447std::string UninitializedReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800448 std::stringstream result;
449 result << "Uninitialized Reference" << ": " << PrettyDescriptor(GetClass());
450 result << " Allocation PC: " << GetAllocationPc();
451 return result.str();
452}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700453
454std::string UninitializedThisReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800455 std::stringstream result;
456 result << "Uninitialized This Reference" << ": " << PrettyDescriptor(GetClass());
457 result << "Allocation PC: " << GetAllocationPc();
458 return result.str();
459}
460
461std::string ImpreciseConstType::Dump() const {
462 std::stringstream result;
463 uint32_t val = ConstantValue();
464 if (val == 0) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800465 result << "Zero/null";
466 } else {
467 result << "Imprecise ";
468 if (IsConstantShort()) {
469 result << StringPrintf("Constant: %d", val);
470 } else {
471 result << StringPrintf("Constant: 0x%x", val);
472 }
473 }
474 return result.str();
475}
476std::string PreciseConstLoType::Dump() const {
477 std::stringstream result;
478
479 int32_t val = ConstantValueLo();
480 result << "Precise ";
481 if (val >= std::numeric_limits<jshort>::min() &&
482 val <= std::numeric_limits<jshort>::max()) {
483 result << StringPrintf("Low-half Constant: %d", val);
484 } else {
485 result << StringPrintf("Low-half Constant: 0x%x", val);
486 }
487 return result.str();
488}
489
490std::string ImpreciseConstLoType::Dump() const {
491 std::stringstream result;
492
493 int32_t val = ConstantValueLo();
494 result << "Imprecise ";
495 if (val >= std::numeric_limits<jshort>::min() &&
496 val <= std::numeric_limits<jshort>::max()) {
497 result << StringPrintf("Low-half Constant: %d", val);
498 } else {
499 result << StringPrintf("Low-half Constant: 0x%x", val);
500 }
501 return result.str();
502}
503
504std::string PreciseConstHiType::Dump() const {
505 std::stringstream result;
506 int32_t val = ConstantValueHi();
507 result << "Precise ";
508 if (val >= std::numeric_limits<jshort>::min() &&
509 val <= std::numeric_limits<jshort>::max()) {
510 result << StringPrintf("High-half Constant: %d", val);
511 } else {
512 result << StringPrintf("High-half Constant: 0x%x", val);
513 }
514 return result.str();
515}
516
517std::string ImpreciseConstHiType::Dump() const {
518 std::stringstream result;
519 int32_t val = ConstantValueHi();
520 result << "Imprecise ";
521 if (val >= std::numeric_limits<jshort>::min() &&
522 val <= std::numeric_limits<jshort>::max()) {
523 result << StringPrintf("High-half Constant: %d", val);
524 } else {
525 result << StringPrintf("High-half Constant: 0x%x", val);
526 }
527 return result.str();
528}
529
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700530ConstantType::ConstantType(uint32_t constant, uint16_t cache_id)
531 : RegType(NULL, "", cache_id), constant_(constant) {
532}
533
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800534const RegType& UndefinedType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
535 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
536 if (incoming_type.IsUndefined()) {
537 return *this; // Undefined MERGE Undefined => Undefined
538 }
539 return reg_types->Conflict();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700540}
541
542const RegType& RegType::HighHalf(RegTypeCache* cache) const {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800543 DCHECK(IsLowHalf());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800544 if (IsLongLo()) {
545 return cache->LongHi();
546 } else if (IsDoubleLo()) {
547 return cache->DoubleHi();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700548 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800549 DCHECK(IsImpreciseConstantLo());
550 return cache->FromCat2ConstHi(ConstantValue(), false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700551 }
552}
553
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800554Primitive::Type RegType::GetPrimitiveType() const {
555 if (IsNonZeroReferenceTypes()) {
556 return Primitive::kPrimNot;
557 } else if (IsBooleanTypes()) {
558 return Primitive::kPrimBoolean;
559 } else if (IsByteTypes()) {
560 return Primitive::kPrimByte;
561 } else if (IsShortTypes()) {
562 return Primitive::kPrimShort;
563 } else if (IsCharTypes()) {
564 return Primitive::kPrimChar;
565 } else if (IsFloat()) {
566 return Primitive::kPrimFloat;
567 } else if (IsIntegralTypes()) {
568 return Primitive::kPrimInt;
569 } else if (IsDoubleLo()) {
570 return Primitive::kPrimDouble;
571 } else {
572 DCHECK(IsLongTypes());
573 return Primitive::kPrimLong;
574 }
575}
576
Ian Rogers637c65b2013-05-31 11:46:00 -0700577bool UninitializedType::IsUninitializedTypes() const {
578 return true;
579}
580
581bool UninitializedType::IsNonZeroReferenceTypes() const {
582 return true;
583}
584
585bool UnresolvedType::IsNonZeroReferenceTypes() const {
586 return true;
587}
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800588std::set<uint16_t> UnresolvedMergedType::GetMergedTypes() const {
Ian Rogers529781d2012-07-23 17:24:29 -0700589 std::pair<uint16_t, uint16_t> refs = GetTopMergedTypes();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800590 const RegType& _left(reg_type_cache_->GetFromId(refs.first));
591 RegType& __left(const_cast<RegType&>(_left));
592 UnresolvedMergedType* left = down_cast<UnresolvedMergedType*>(&__left);
593
594 RegType& _right(
595 const_cast<RegType&>(reg_type_cache_->GetFromId(refs.second)));
596 UnresolvedMergedType* right = down_cast<UnresolvedMergedType*>(&_right);
597
Ian Rogers529781d2012-07-23 17:24:29 -0700598 std::set<uint16_t> types;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800599 if (left->IsUnresolvedMergedReference()) {
600 types = left->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700601 } else {
602 types.insert(refs.first);
603 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800604 if (right->IsUnresolvedMergedReference()) {
605 std::set<uint16_t> right_types = right->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700606 types.insert(right_types.begin(), right_types.end());
607 } else {
608 types.insert(refs.second);
609 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800610 if (kIsDebugBuild) {
Mathieu Chartier02e25112013-08-14 16:14:24 -0700611 for (const auto& type : types) {
612 CHECK(!reg_type_cache_->GetFromId(type).IsUnresolvedMergedReference());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800613 }
Ian Rogers529781d2012-07-23 17:24:29 -0700614 }
Ian Rogers529781d2012-07-23 17:24:29 -0700615 return types;
616}
617
Ian Rogersad0b3a32012-04-16 14:50:24 -0700618const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
619 if (!IsUnresolvedTypes()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800620 mirror::Class* super_klass = GetClass()->GetSuperClass();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700621 if (super_klass != NULL) {
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700622 // A super class of a precise type isn't precise as a precise type indicates the register
623 // holds exactly that type.
Mathieu Chartierf8322842014-05-16 10:59:25 -0700624 return cache->FromClass(super_klass->GetDescriptor().c_str(), super_klass, false);
Ian Rogers0d604842012-04-16 14:50:24 -0700625 } else {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700626 return cache->Zero();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700627 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700628 } else {
Ian Rogers529781d2012-07-23 17:24:29 -0700629 if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
Elliott Hughes80537bb2013-01-04 16:37:26 -0800630 GetDescriptor()[0] == '[') {
Ian Rogers529781d2012-07-23 17:24:29 -0700631 // Super class of all arrays is Object.
Ian Rogersb4903572012-10-11 11:52:56 -0700632 return cache->JavaLangObject(true);
Ian Rogers529781d2012-07-23 17:24:29 -0700633 } else {
634 return cache->FromUnresolvedSuperClass(*this);
635 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700636 }
637}
638
639bool RegType::CanAccess(const RegType& other) const {
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 {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800650 return false; // More complicated test not possible on unresolved types, be conservative.
Ian Rogerse1758fe2012-04-19 11:31:15 -0700651 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700652 }
653}
654
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800655bool RegType::CanAccessMember(mirror::Class* klass, uint32_t access_flags) const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800656 if ((access_flags & kAccPublic) != 0) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700657 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.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700663 }
664}
665
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800666bool RegType::IsObjectArrayTypes() const 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
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800679bool RegType::IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
680 return IsReference() && GetClass()->IsObjectClass();
681}
682
683bool RegType::IsArrayTypes() const 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
693bool RegType::IsJavaLangObjectArray() const {
694 if (HasClass()) {
695 mirror::Class* type = GetClass();
696 return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
697 }
698 return false;
699}
700
701bool RegType::IsInstantiableTypes() const {
702 return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
703}
704
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800705ImpreciseConstType::ImpreciseConstType(uint32_t constat, uint16_t cache_id)
706 : ConstantType(constat, cache_id) {
707}
708
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700709static bool AssignableFrom(const RegType& lhs, const RegType& rhs, bool strict)
710 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
711 if (lhs.Equals(rhs)) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700712 return true;
713 } else {
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700714 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();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800730 } else {
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700731 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.
Ian Rogersfae370a2013-06-05 08:33:27 -0700742 return true;
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700743 } 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;
Ian Rogersfae370a2013-06-05 08:33:27 -0700749 } else {
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700750 // Unresolved types are only assignable for null and equality.
Ian Rogersfae370a2013-06-05 08:33:27 -0700751 return false;
752 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700753 }
754 }
755}
756
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700757bool RegType::IsAssignableFrom(const RegType& src) const {
758 return AssignableFrom(*this, src, false);
759}
760
761bool RegType::IsStrictlyAssignableFrom(const RegType& src) const {
762 return AssignableFrom(*this, src, true);
763}
764
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800765int32_t ConstantType::ConstantValueLo() const {
766 DCHECK(IsConstantLo());
767 return constant_;
768}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700769
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800770int32_t ConstantType::ConstantValueHi() const {
771 if (IsConstantHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()) {
772 return constant_;
773 } else {
774 DCHECK(false);
775 return 0;
776 }
777}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700778
Ian Rogers776ac1f2012-04-13 23:36:36 -0700779static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
Sebastien Hertzaa0c00c2014-03-14 17:58:54 +0100780 return a.IsConstantTypes() ? b : a;
Ian Rogers776ac1f2012-04-13 23:36:36 -0700781}
782
783const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
784 DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800785 if (IsConflict()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700786 return *this; // Conflict MERGE * => Conflict
787 } else if (incoming_type.IsConflict()) {
788 return incoming_type; // * MERGE Conflict => Conflict
Ian Rogersad0b3a32012-04-16 14:50:24 -0700789 } else if (IsUndefined() || incoming_type.IsUndefined()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700790 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) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800797 if (!IsPreciseConstant()) {
798 return *this;
799 } else {
800 return reg_types->FromCat1Const(val1, false);
801 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700802 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800803 if (!incoming_type.IsPreciseConstant()) {
804 return incoming_type;
805 } else {
806 return reg_types->FromCat1Const(val2, false);
807 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700808 }
809 } else if (val1 < 0 && val2 < 0) {
810 // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
811 if (val1 <= val2) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800812 if (!IsPreciseConstant()) {
813 return *this;
814 } else {
815 return reg_types->FromCat1Const(val1, false);
816 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700817 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800818 if (!incoming_type.IsPreciseConstant()) {
819 return incoming_type;
820 } else {
821 return reg_types->FromCat1Const(val2, false);
822 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700823 }
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 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800844 } 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);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700852 } 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()) {
Ian Rogersb4903572012-10-11 11:52:56 -0700879 return reg_types->JavaLangObject(false); // Object MERGE ref => Object
Ian Rogers529781d2012-07-23 17:24:29 -0700880 } 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.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700890 return reg_types->Conflict();
891 } else { // Two reference types, compute Join
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800892 mirror::Class* c1 = GetClass();
893 mirror::Class* c2 = incoming_type.GetClass();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700894 DCHECK(c1 != NULL && !c1->IsPrimitive());
895 DCHECK(c2 != NULL && !c2->IsPrimitive());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800896 mirror::Class* join_class = ClassJoin(c1, c2);
Ian Rogersb4903572012-10-11 11:52:56 -0700897 if (c1 == join_class && !IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700898 return *this;
Ian Rogersb4903572012-10-11 11:52:56 -0700899 } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700900 return incoming_type;
901 } else {
Mathieu Chartierf8322842014-05-16 10:59:25 -0700902 return reg_types->FromClass(join_class->GetDescriptor().c_str(), join_class, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700903 }
904 }
905 } else {
906 return reg_types->Conflict(); // Unexpected types => Conflict
907 }
908}
909
Ian Rogersad0b3a32012-04-16 14:50:24 -0700910// See comment in reg_type.h
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800911mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700912 DCHECK(!s->IsPrimitive()) << PrettyClass(s);
913 DCHECK(!t->IsPrimitive()) << PrettyClass(t);
914 if (s == t) {
915 return s;
916 } else if (s->IsAssignableFrom(t)) {
917 return s;
918 } else if (t->IsAssignableFrom(s)) {
919 return t;
920 } else if (s->IsArrayClass() && t->IsArrayClass()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800921 mirror::Class* s_ct = s->GetComponentType();
922 mirror::Class* t_ct = t->GetComponentType();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700923 if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
924 // Given the types aren't the same, if either array is of primitive types then the only
925 // common parent is java.lang.Object
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800926 mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object
Ian Rogersad0b3a32012-04-16 14:50:24 -0700927 DCHECK(result->IsObjectClass());
928 return result;
929 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800930 mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700931 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Mathieu Chartierb74cd292014-05-29 14:31:33 -0700932 mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), &common_elem);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700933 DCHECK(array_class != NULL);
934 return array_class;
935 } else {
936 size_t s_depth = s->Depth();
937 size_t t_depth = t->Depth();
938 // Get s and t to the same depth in the hierarchy
939 if (s_depth > t_depth) {
940 while (s_depth > t_depth) {
941 s = s->GetSuperClass();
942 s_depth--;
943 }
944 } else {
945 while (t_depth > s_depth) {
946 t = t->GetSuperClass();
947 t_depth--;
948 }
949 }
950 // Go up the hierarchy until we get to the common parent
951 while (s != t) {
952 s = s->GetSuperClass();
953 t = t->GetSuperClass();
954 }
955 return s;
956 }
957}
958
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800959void RegType::CheckInvariants() const {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800960 if (IsConstant() || IsConstantLo() || IsConstantHi()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800961 CHECK(descriptor_.empty()) << *this;
962 CHECK(klass_ == NULL) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800963 }
Ian Rogers637c65b2013-05-31 11:46:00 -0700964 if (klass_ != NULL) {
965 CHECK(!descriptor_.empty()) << *this;
966 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800967}
968
Mathieu Chartier83c8ee02014-01-28 14:50:23 -0800969void RegType::VisitRoots(RootCallback* callback, void* arg) {
Mathieu Chartierc528dba2013-11-26 12:00:11 -0800970 if (klass_ != nullptr) {
Mathieu Chartier815873e2014-02-13 18:02:13 -0800971 callback(reinterpret_cast<mirror::Object**>(&klass_), arg, 0, kRootUnknown);
Mathieu Chartierc528dba2013-11-26 12:00:11 -0800972 }
973}
974
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700975void UninitializedThisReferenceType::CheckInvariants() const {
Ian Rogers637c65b2013-05-31 11:46:00 -0700976 CHECK_EQ(GetAllocationPc(), 0U) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800977}
978
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700979void UnresolvedUninitializedThisRefType::CheckInvariants() const {
Ian Rogers637c65b2013-05-31 11:46:00 -0700980 CHECK_EQ(GetAllocationPc(), 0U) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800981 CHECK(!descriptor_.empty()) << *this;
982 CHECK(klass_ == NULL) << *this;
983}
984
985void UnresolvedUninitializedRefType::CheckInvariants() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800986 CHECK(!descriptor_.empty()) << *this;
987 CHECK(klass_ == NULL) << *this;
988}
989
990void UnresolvedMergedType::CheckInvariants() const {
991 // Unresolved merged types: merged types should be defined.
992 CHECK(descriptor_.empty()) << *this;
993 CHECK(klass_ == NULL) << *this;
994 CHECK_NE(merged_types_.first, 0U) << *this;
995 CHECK_NE(merged_types_.second, 0U) << *this;
996}
997
998void UnresolvedReferenceType::CheckInvariants() const {
999 CHECK(!descriptor_.empty()) << *this;
1000 CHECK(klass_ == NULL) << *this;
1001}
1002
1003void UnresolvedSuperClass::CheckInvariants() const {
1004 // Unresolved merged types: merged types should be defined.
1005 CHECK(descriptor_.empty()) << *this;
1006 CHECK(klass_ == NULL) << *this;
1007 CHECK_NE(unresolved_child_id_, 0U) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001008}
1009
1010std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
Ian Rogers776ac1f2012-04-13 23:36:36 -07001011 os << rhs.Dump();
1012 return os;
1013}
1014
Elliott Hughesa21039c2012-06-21 12:09:25 -07001015} // namespace verifier
1016} // namespace art