blob: e738e805144bd50f44867b1623ecaddb2752a5c4 [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 Rogers4f6ad8a2013-03-18 15:27:28 -070021#include "dex_file-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080022#include "mirror/class.h"
23#include "mirror/class-inl.h"
24#include "mirror/object-inl.h"
Ian Rogers693ff612013-02-01 10:56:12 -080025#include "mirror/object_array-inl.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070026#include "object_utils.h"
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080027#include "reg_type_cache-inl.h"
Ian Rogers637c65b2013-05-31 11:46:00 -070028#include "scoped_thread_state_change.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070029
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080030#include <limits>
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080031#include <sstream>
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080032
Ian Rogers776ac1f2012-04-13 23:36:36 -070033namespace art {
34namespace verifier {
35
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080036UndefinedType* 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;
Ian Rogers776ac1f2012-04-13 23:36:36 -070048
Ian Rogers637c65b2013-05-31 11:46:00 -070049int32_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
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080084std::string PreciseConstType::Dump() const {
85 std::stringstream result;
86 uint32_t val = ConstantValue();
87 if (val == 0) {
88 CHECK(IsPreciseConstant());
89 result << "Zero/null";
Ian Rogers776ac1f2012-04-13 23:36:36 -070090 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080091 result << "Precise ";
92 if (IsConstantShort()) {
93 result << StringPrintf("Constant: %d", val);
94 } else {
95 result << StringPrintf("Constant: 0x%x", val);
Ian Rogers776ac1f2012-04-13 23:36:36 -070096 }
97 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080098 return result.str();
99}
100
101std::string BooleanType::Dump() const {
102 return "boolean";
103}
104
105std::string ConflictType::Dump() const {
106 return "Conflict";
107}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700108
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800109std::string ByteType::Dump() const {
110 return "Byte";
111}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700112
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800113std::string ShortType::Dump() const {
114 return "short";
115}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700116
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800117std::string CharType::Dump() const {
118 return "Char";
119}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700120
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800121std::string FloatType::Dump() const {
122 return "float";
123}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700124
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800125std::string LongLoType::Dump() const {
126 return "long (Low Half)";
127}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700128
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800129std::string LongHiType::Dump() const {
130 return "long (High Half)";
131}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700132
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800133std::string DoubleLoType::Dump() const {
134 return "Double (Low Half)";
135}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700136
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800137std::string DoubleHiType::Dump() const {
138 return "Double (High Half)";
139}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700140
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800141std::string IntegerType::Dump() const {
142 return "Integer";
143}
144
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700145DoubleHiType* DoubleHiType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800146 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
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700165DoubleLoType* DoubleLoType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800166 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
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700185LongLoType* LongLoType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800186 uint16_t cache_id) {
187 if (instance_ == NULL) {
188 instance_ = new LongLoType(klass, descriptor, cache_id);
189 }
190 return instance_;
191}
192
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700193LongHiType* LongHiType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800194 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
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700225FloatType* FloatType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
226 uint16_t cache_id) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800227 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
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700244CharType* CharType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800245 uint16_t cache_id) {
246 if (instance_ == NULL) {
247 instance_ = new CharType(klass, descriptor, cache_id);
248 }
249 return instance_;
250}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700251
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800252CharType* CharType::GetInstance() {
253 CHECK(instance_ != NULL);
254 return instance_;
255}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700256
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800257void CharType::Destroy() {
258 if (instance_ != NULL) {
259 delete instance_;
260 instance_ = NULL;
261 }
262}
263
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700264ShortType* ShortType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800265 uint16_t cache_id) {
266 if (instance_ == NULL) {
267 instance_ = new ShortType(klass, descriptor, cache_id);
268 }
269 return instance_;
270}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700271
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800272ShortType* ShortType::GetInstance() {
273 CHECK(instance_ != NULL);
274 return instance_;
275}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700276
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800277void ShortType::Destroy() {
278 if (instance_ != NULL) {
279 delete instance_;
280 instance_ = NULL;
281 }
282}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700283
284ByteType* ByteType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
285 uint16_t cache_id) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800286 if (instance_ == NULL) {
287 instance_ = new ByteType(klass, descriptor, cache_id);
288 }
289 return instance_;
290}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700291
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800292ByteType* ByteType::GetInstance() {
293 CHECK(instance_ != NULL);
294 return instance_;
295}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700296
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800297void ByteType::Destroy() {
298 if (instance_ != NULL) {
299 delete instance_;
300 instance_ = NULL;
301 }
302}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700303
304IntegerType* IntegerType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800305 uint16_t cache_id) {
306 if (instance_ == NULL) {
307 instance_ = new IntegerType(klass, descriptor, cache_id);
308 }
309 return instance_;
310}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700311
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800312IntegerType* IntegerType::GetInstance() {
313 CHECK(instance_ != NULL);
314 return instance_;
315}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700316
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800317void IntegerType::Destroy() {
318 if (instance_ != NULL) {
319 delete instance_;
320 instance_ = NULL;
321 }
322}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700323
324ConflictType* ConflictType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800325 uint16_t cache_id) {
326 if (instance_ == NULL) {
327 instance_ = new ConflictType(klass, descriptor, cache_id);
328 }
329 return instance_;
330}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700331
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800332ConflictType* ConflictType::GetInstance() {
333 CHECK(instance_ != NULL);
334 return instance_;
335}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700336
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800337void ConflictType::Destroy() {
338 if (instance_ != NULL) {
339 delete instance_;
340 instance_ = NULL;
341 }
342}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700343
344BooleanType* BooleanType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800345 uint16_t cache_id) {
346 if (BooleanType::instance == NULL) {
347 instance = new BooleanType(klass, descriptor, cache_id);
348 }
349 return BooleanType::instance;
350}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700351
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800352BooleanType* 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() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
365 return "Undefined";
366}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700367
368UndefinedType* UndefinedType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800369 uint16_t cache_id) {
370 if (instance_ == NULL) {
371 instance_ = new UndefinedType(klass, descriptor, cache_id);
372 }
373 return instance_;
374}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700375
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800376UndefinedType* UndefinedType::GetInstance() {
377 CHECK(instance_ != NULL);
378 return instance_;
379}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700380
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800381void UndefinedType::Destroy() {
382 if (instance_ != NULL) {
383 delete instance_;
384 instance_ = NULL;
385 }
386}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700387
Ian Rogers637c65b2013-05-31 11:46:00 -0700388PreciseReferenceType::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
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800394std::string UnresolvedMergedType::Dump() const {
395 std::stringstream result;
396 std::set<uint16_t> types = GetMergedTypes();
397 result << "UnresolvedMergedReferences(";
398 typedef std::set<uint16_t>::const_iterator It; // TODO: C++0x auto
399 It it = types.begin();
400 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) {
465 CHECK(IsPreciseConstant());
466 result << "Zero/null";
467 } else {
468 result << "Imprecise ";
469 if (IsConstantShort()) {
470 result << StringPrintf("Constant: %d", val);
471 } else {
472 result << StringPrintf("Constant: 0x%x", val);
473 }
474 }
475 return result.str();
476}
477std::string PreciseConstLoType::Dump() const {
478 std::stringstream result;
479
480 int32_t val = ConstantValueLo();
481 result << "Precise ";
482 if (val >= std::numeric_limits<jshort>::min() &&
483 val <= std::numeric_limits<jshort>::max()) {
484 result << StringPrintf("Low-half Constant: %d", val);
485 } else {
486 result << StringPrintf("Low-half Constant: 0x%x", val);
487 }
488 return result.str();
489}
490
491std::string ImpreciseConstLoType::Dump() const {
492 std::stringstream result;
493
494 int32_t val = ConstantValueLo();
495 result << "Imprecise ";
496 if (val >= std::numeric_limits<jshort>::min() &&
497 val <= std::numeric_limits<jshort>::max()) {
498 result << StringPrintf("Low-half Constant: %d", val);
499 } else {
500 result << StringPrintf("Low-half Constant: 0x%x", val);
501 }
502 return result.str();
503}
504
505std::string PreciseConstHiType::Dump() const {
506 std::stringstream result;
507 int32_t val = ConstantValueHi();
508 result << "Precise ";
509 if (val >= std::numeric_limits<jshort>::min() &&
510 val <= std::numeric_limits<jshort>::max()) {
511 result << StringPrintf("High-half Constant: %d", val);
512 } else {
513 result << StringPrintf("High-half Constant: 0x%x", val);
514 }
515 return result.str();
516}
517
518std::string ImpreciseConstHiType::Dump() const {
519 std::stringstream result;
520 int32_t val = ConstantValueHi();
521 result << "Imprecise ";
522 if (val >= std::numeric_limits<jshort>::min() &&
523 val <= std::numeric_limits<jshort>::max()) {
524 result << StringPrintf("High-half Constant: %d", val);
525 } else {
526 result << StringPrintf("High-half Constant: 0x%x", val);
527 }
528 return result.str();
529}
530
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700531ConstantType::ConstantType(uint32_t constant, uint16_t cache_id)
532 : RegType(NULL, "", cache_id), constant_(constant) {
533}
534
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800535const RegType& UndefinedType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
536 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
537 if (incoming_type.IsUndefined()) {
538 return *this; // Undefined MERGE Undefined => Undefined
539 }
540 return reg_types->Conflict();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700541}
542
543const RegType& RegType::HighHalf(RegTypeCache* cache) const {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800544 DCHECK(IsLowHalf());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800545 if (IsLongLo()) {
546 return cache->LongHi();
547 } else if (IsDoubleLo()) {
548 return cache->DoubleHi();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700549 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800550 DCHECK(IsImpreciseConstantLo());
551 return cache->FromCat2ConstHi(ConstantValue(), false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700552 }
553}
554
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800555Primitive::Type RegType::GetPrimitiveType() const {
556 if (IsNonZeroReferenceTypes()) {
557 return Primitive::kPrimNot;
558 } else if (IsBooleanTypes()) {
559 return Primitive::kPrimBoolean;
560 } else if (IsByteTypes()) {
561 return Primitive::kPrimByte;
562 } else if (IsShortTypes()) {
563 return Primitive::kPrimShort;
564 } else if (IsCharTypes()) {
565 return Primitive::kPrimChar;
566 } else if (IsFloat()) {
567 return Primitive::kPrimFloat;
568 } else if (IsIntegralTypes()) {
569 return Primitive::kPrimInt;
570 } else if (IsDoubleLo()) {
571 return Primitive::kPrimDouble;
572 } else {
573 DCHECK(IsLongTypes());
574 return Primitive::kPrimLong;
575 }
576}
577
Ian Rogers637c65b2013-05-31 11:46:00 -0700578bool UninitializedType::IsUninitializedTypes() const {
579 return true;
580}
581
582bool UninitializedType::IsNonZeroReferenceTypes() const {
583 return true;
584}
585
586bool UnresolvedType::IsNonZeroReferenceTypes() const {
587 return true;
588}
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800589std::set<uint16_t> UnresolvedMergedType::GetMergedTypes() const {
Ian Rogers529781d2012-07-23 17:24:29 -0700590 std::pair<uint16_t, uint16_t> refs = GetTopMergedTypes();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800591 const RegType& _left(reg_type_cache_->GetFromId(refs.first));
592 RegType& __left(const_cast<RegType&>(_left));
593 UnresolvedMergedType* left = down_cast<UnresolvedMergedType*>(&__left);
594
595 RegType& _right(
596 const_cast<RegType&>(reg_type_cache_->GetFromId(refs.second)));
597 UnresolvedMergedType* right = down_cast<UnresolvedMergedType*>(&_right);
598
Ian Rogers529781d2012-07-23 17:24:29 -0700599 std::set<uint16_t> types;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800600 if (left->IsUnresolvedMergedReference()) {
601 types = left->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700602 } else {
603 types.insert(refs.first);
604 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800605 if (right->IsUnresolvedMergedReference()) {
606 std::set<uint16_t> right_types = right->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700607 types.insert(right_types.begin(), right_types.end());
608 } else {
609 types.insert(refs.second);
610 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800611 if (kIsDebugBuild) {
612 typedef std::set<uint16_t>::const_iterator It; // TODO: C++0x auto
613 for (It it = types.begin(); it != types.end(); ++it) {
614 CHECK(!reg_type_cache_->GetFromId(*it).IsUnresolvedMergedReference());
615 }
Ian Rogers529781d2012-07-23 17:24:29 -0700616 }
Ian Rogers529781d2012-07-23 17:24:29 -0700617 return types;
618}
619
Ian Rogersad0b3a32012-04-16 14:50:24 -0700620const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
621 if (!IsUnresolvedTypes()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800622 mirror::Class* super_klass = GetClass()->GetSuperClass();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700623 if (super_klass != NULL) {
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700624 // A super class of a precise type isn't precise as a precise type indicates the register
625 // holds exactly that type.
Ian Rogers637c65b2013-05-31 11:46:00 -0700626 return cache->FromClass(ClassHelper(super_klass).GetDescriptor(), super_klass, false);
Ian Rogers0d604842012-04-16 14:50:24 -0700627 } else {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700628 return cache->Zero();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700629 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700630 } else {
Ian Rogers529781d2012-07-23 17:24:29 -0700631 if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
Elliott Hughes80537bb2013-01-04 16:37:26 -0800632 GetDescriptor()[0] == '[') {
Ian Rogers529781d2012-07-23 17:24:29 -0700633 // Super class of all arrays is Object.
Ian Rogersb4903572012-10-11 11:52:56 -0700634 return cache->JavaLangObject(true);
Ian Rogers529781d2012-07-23 17:24:29 -0700635 } else {
636 return cache->FromUnresolvedSuperClass(*this);
637 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700638 }
639}
640
641bool RegType::CanAccess(const RegType& other) const {
642 if (Equals(other)) {
643 return true; // Trivial accessibility.
644 } else {
645 bool this_unresolved = IsUnresolvedTypes();
646 bool other_unresolved = other.IsUnresolvedTypes();
647 if (!this_unresolved && !other_unresolved) {
648 return GetClass()->CanAccess(other.GetClass());
649 } else if (!other_unresolved) {
650 return other.GetClass()->IsPublic(); // Be conservative, only allow if other is public.
651 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800652 return false; // More complicated test not possible on unresolved types, be conservative.
Ian Rogerse1758fe2012-04-19 11:31:15 -0700653 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700654 }
655}
656
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800657bool RegType::CanAccessMember(mirror::Class* klass, uint32_t access_flags) const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800658 if ((access_flags & kAccPublic) != 0) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700659 return true;
660 }
661 if (!IsUnresolvedTypes()) {
662 return GetClass()->CanAccessMember(klass, access_flags);
663 } else {
664 return false; // More complicated test not possible on unresolved types, be conservative.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700665 }
666}
667
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800668bool RegType::IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
669 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
670 // Primitive arrays will always resolve
671 DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
672 return descriptor_[0] == '[';
673 } else if (HasClass()) {
674 mirror::Class* type = GetClass();
675 return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
676 } else {
677 return false;
678 }
679}
680
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800681bool RegType::IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
682 return IsReference() && GetClass()->IsObjectClass();
683}
684
685bool RegType::IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
686 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
687 return descriptor_[0] == '[';
688 } else if (HasClass()) {
689 return GetClass()->IsArrayClass();
690 } else {
691 return false;
692 }
693}
694
695bool RegType::IsJavaLangObjectArray() const {
696 if (HasClass()) {
697 mirror::Class* type = GetClass();
698 return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
699 }
700 return false;
701}
702
703bool RegType::IsInstantiableTypes() const {
704 return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
705}
706
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800707ImpreciseConstType::ImpreciseConstType(uint32_t constat, uint16_t cache_id)
708 : ConstantType(constat, cache_id) {
709}
710
Ian Rogers776ac1f2012-04-13 23:36:36 -0700711bool RegType::IsAssignableFrom(const RegType& src) const {
712 if (Equals(src)) {
713 return true;
714 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800715 if (IsBoolean()) {
716 return src.IsBooleanTypes();
717 } else if (IsByte()) {
718 return src.IsByteTypes();
719 } else if (IsShort()) {
720 return src.IsShortTypes();
721 } else if (IsChar()) {
722 return src.IsCharTypes();
723 } else if (IsInteger()) {
724 return src.IsIntegralTypes();
725 } else if (IsFloat()) {
726 return src.IsFloatTypes();
727 } else if (IsLongLo()) {
728 return src.IsLongTypes();
729 } else if (IsDoubleLo()) {
730 return src.IsDoubleTypes();
731 } else {
732 if (!IsReferenceTypes()) {
733 LOG(FATAL) << "Unexpected register type in 4bleFrom: '" << src << "'";
734 }
735 if (src.IsZero()) {
736 return true; // all reference types can be assigned null
737 } else if (!src.IsReferenceTypes()) {
738 return false; // expect src to be a reference type
739 } else if (IsJavaLangObject()) {
740 return true; // all reference types can be assigned to Object
741 } else if (!IsUnresolvedTypes() && GetClass()->IsInterface()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700742 return true; // We allow assignment to any interface, see comment in ClassJoin
743 } else if (IsJavaLangObjectArray()) {
744 return src.IsObjectArrayTypes(); // All reference arrays may be assigned to Object[]
745 } else if (!IsUnresolvedTypes() && !src.IsUnresolvedTypes() &&
746 GetClass()->IsAssignableFrom(src.GetClass())) {
747 // We're assignable from the Class point-of-view
748 return true;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800749 } else if (IsUnresolvedTypes()) {
750 // Unresolved types are only assignable for null, Object and equality.
751 return (src.IsZero() || src.IsJavaLangObject());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700752 } else {
753 return false;
754 }
755 }
756 }
757}
758
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800759int32_t ConstantType::ConstantValue() const {
760 DCHECK(IsConstantTypes());
761 return constant_;
762}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700763
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800764int32_t ConstantType::ConstantValueLo() const {
765 DCHECK(IsConstantLo());
766 return constant_;
767}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700768
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800769int32_t ConstantType::ConstantValueHi() const {
770 if (IsConstantHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()) {
771 return constant_;
772 } else {
773 DCHECK(false);
774 return 0;
775 }
776}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700777
Ian Rogers776ac1f2012-04-13 23:36:36 -0700778static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
779 return a.IsConstant() ? b : a;
780}
781
782const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
783 DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800784 if (IsConflict()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700785 return *this; // Conflict MERGE * => Conflict
786 } else if (incoming_type.IsConflict()) {
787 return incoming_type; // * MERGE Conflict => Conflict
Ian Rogersad0b3a32012-04-16 14:50:24 -0700788 } else if (IsUndefined() || incoming_type.IsUndefined()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700789 return reg_types->Conflict(); // Unknown MERGE * => Conflict
790 } else if (IsConstant() && incoming_type.IsConstant()) {
791 int32_t val1 = ConstantValue();
792 int32_t val2 = incoming_type.ConstantValue();
793 if (val1 >= 0 && val2 >= 0) {
794 // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
795 if (val1 >= val2) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800796 if (!IsPreciseConstant()) {
797 return *this;
798 } else {
799 return reg_types->FromCat1Const(val1, false);
800 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700801 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800802 if (!incoming_type.IsPreciseConstant()) {
803 return incoming_type;
804 } else {
805 return reg_types->FromCat1Const(val2, false);
806 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700807 }
808 } else if (val1 < 0 && val2 < 0) {
809 // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
810 if (val1 <= val2) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800811 if (!IsPreciseConstant()) {
812 return *this;
813 } else {
814 return reg_types->FromCat1Const(val1, false);
815 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700816 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800817 if (!incoming_type.IsPreciseConstant()) {
818 return incoming_type;
819 } else {
820 return reg_types->FromCat1Const(val2, false);
821 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700822 }
823 } else {
824 // Values are +ve and -ve, choose smallest signed type in which they both fit
825 if (IsConstantByte()) {
826 if (incoming_type.IsConstantByte()) {
827 return reg_types->ByteConstant();
828 } else if (incoming_type.IsConstantShort()) {
829 return reg_types->ShortConstant();
830 } else {
831 return reg_types->IntConstant();
832 }
833 } else if (IsConstantShort()) {
834 if (incoming_type.IsConstantShort()) {
835 return reg_types->ShortConstant();
836 } else {
837 return reg_types->IntConstant();
838 }
839 } else {
840 return reg_types->IntConstant();
841 }
842 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800843 } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
844 int32_t val1 = ConstantValueLo();
845 int32_t val2 = incoming_type.ConstantValueLo();
846 return reg_types->FromCat2ConstLo(val1 | val2, false);
847 } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
848 int32_t val1 = ConstantValueHi();
849 int32_t val2 = incoming_type.ConstantValueHi();
850 return reg_types->FromCat2ConstHi(val1 | val2, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700851 } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
852 if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
853 return reg_types->Boolean(); // boolean MERGE boolean => boolean
854 }
855 if (IsByteTypes() && incoming_type.IsByteTypes()) {
856 return reg_types->Byte(); // byte MERGE byte => byte
857 }
858 if (IsShortTypes() && incoming_type.IsShortTypes()) {
859 return reg_types->Short(); // short MERGE short => short
860 }
861 if (IsCharTypes() && incoming_type.IsCharTypes()) {
862 return reg_types->Char(); // char MERGE char => char
863 }
864 return reg_types->Integer(); // int MERGE * => int
865 } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
866 (IsLongTypes() && incoming_type.IsLongTypes()) ||
867 (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
868 (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
869 (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
870 // check constant case was handled prior to entry
871 DCHECK(!IsConstant() || !incoming_type.IsConstant());
872 // float/long/double MERGE float/long/double_constant => float/long/double
873 return SelectNonConstant(*this, incoming_type);
874 } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
875 if (IsZero() || incoming_type.IsZero()) {
876 return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref
877 } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
Ian Rogersb4903572012-10-11 11:52:56 -0700878 return reg_types->JavaLangObject(false); // Object MERGE ref => Object
Ian Rogers529781d2012-07-23 17:24:29 -0700879 } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
880 // We know how to merge an unresolved type with itself, 0 or Object. In this case we
881 // have two sub-classes and don't know how to merge. Create a new string-based unresolved
882 // type that reflects our lack of knowledge and that allows the rest of the unresolved
883 // mechanics to continue.
884 return reg_types->FromUnresolvedMerge(*this, incoming_type);
885 } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
886 // Something that is uninitialized hasn't had its constructor called. Mark any merge
887 // of this type with something that is initialized as conflicting. The cases of a merge
888 // with itself, 0 or Object are handled above.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700889 return reg_types->Conflict();
890 } else { // Two reference types, compute Join
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800891 mirror::Class* c1 = GetClass();
892 mirror::Class* c2 = incoming_type.GetClass();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700893 DCHECK(c1 != NULL && !c1->IsPrimitive());
894 DCHECK(c2 != NULL && !c2->IsPrimitive());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800895 mirror::Class* join_class = ClassJoin(c1, c2);
Ian Rogersb4903572012-10-11 11:52:56 -0700896 if (c1 == join_class && !IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700897 return *this;
Ian Rogersb4903572012-10-11 11:52:56 -0700898 } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700899 return incoming_type;
900 } else {
Ian Rogers637c65b2013-05-31 11:46:00 -0700901 return reg_types->FromClass(ClassHelper(join_class).GetDescriptor(), join_class, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700902 }
903 }
904 } else {
905 return reg_types->Conflict(); // Unexpected types => Conflict
906 }
907}
908
Ian Rogersad0b3a32012-04-16 14:50:24 -0700909// See comment in reg_type.h
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800910mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700911 DCHECK(!s->IsPrimitive()) << PrettyClass(s);
912 DCHECK(!t->IsPrimitive()) << PrettyClass(t);
913 if (s == t) {
914 return s;
915 } else if (s->IsAssignableFrom(t)) {
916 return s;
917 } else if (t->IsAssignableFrom(s)) {
918 return t;
919 } else if (s->IsArrayClass() && t->IsArrayClass()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800920 mirror::Class* s_ct = s->GetComponentType();
921 mirror::Class* t_ct = t->GetComponentType();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700922 if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
923 // Given the types aren't the same, if either array is of primitive types then the only
924 // common parent is java.lang.Object
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800925 mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object
Ian Rogersad0b3a32012-04-16 14:50:24 -0700926 DCHECK(result->IsObjectClass());
927 return result;
928 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800929 mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700930 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800931 mirror::ClassLoader* class_loader = s->GetClassLoader();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700932 std::string descriptor("[");
933 descriptor += ClassHelper(common_elem).GetDescriptor();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800934 mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700935 DCHECK(array_class != NULL);
936 return array_class;
937 } else {
938 size_t s_depth = s->Depth();
939 size_t t_depth = t->Depth();
940 // Get s and t to the same depth in the hierarchy
941 if (s_depth > t_depth) {
942 while (s_depth > t_depth) {
943 s = s->GetSuperClass();
944 s_depth--;
945 }
946 } else {
947 while (t_depth > s_depth) {
948 t = t->GetSuperClass();
949 t_depth--;
950 }
951 }
952 // Go up the hierarchy until we get to the common parent
953 while (s != t) {
954 s = s->GetSuperClass();
955 t = t->GetSuperClass();
956 }
957 return s;
958 }
959}
960
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800961void RegType::CheckInvariants() const {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800962 if (IsConstant() || IsConstantLo() || IsConstantHi()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800963 CHECK(descriptor_.empty()) << *this;
964 CHECK(klass_ == NULL) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800965 }
Ian Rogers637c65b2013-05-31 11:46:00 -0700966 if (klass_ != NULL) {
967 CHECK(!descriptor_.empty()) << *this;
968 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800969}
970
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700971void UninitializedThisReferenceType::CheckInvariants() const {
Ian Rogers637c65b2013-05-31 11:46:00 -0700972 CHECK_EQ(GetAllocationPc(), 0U) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800973}
974
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700975void UnresolvedUninitializedThisRefType::CheckInvariants() const {
Ian Rogers637c65b2013-05-31 11:46:00 -0700976 CHECK_EQ(GetAllocationPc(), 0U) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800977 CHECK(!descriptor_.empty()) << *this;
978 CHECK(klass_ == NULL) << *this;
979}
980
981void UnresolvedUninitializedRefType::CheckInvariants() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800982 CHECK(!descriptor_.empty()) << *this;
983 CHECK(klass_ == NULL) << *this;
984}
985
986void UnresolvedMergedType::CheckInvariants() const {
987 // Unresolved merged types: merged types should be defined.
988 CHECK(descriptor_.empty()) << *this;
989 CHECK(klass_ == NULL) << *this;
990 CHECK_NE(merged_types_.first, 0U) << *this;
991 CHECK_NE(merged_types_.second, 0U) << *this;
992}
993
994void UnresolvedReferenceType::CheckInvariants() const {
995 CHECK(!descriptor_.empty()) << *this;
996 CHECK(klass_ == NULL) << *this;
997}
998
999void UnresolvedSuperClass::CheckInvariants() const {
1000 // Unresolved merged types: merged types should be defined.
1001 CHECK(descriptor_.empty()) << *this;
1002 CHECK(klass_ == NULL) << *this;
1003 CHECK_NE(unresolved_child_id_, 0U) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001004}
1005
1006std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
Ian Rogers776ac1f2012-04-13 23:36:36 -07001007 os << rhs.Dump();
1008 return os;
1009}
1010
Elliott Hughesa21039c2012-06-21 12:09:25 -07001011} // namespace verifier
1012} // namespace art