blob: 774c2b29eb139bc863ed78b3a30082fe74e3176b [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 Rogers776ac1f2012-04-13 23:36:36 -070028
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080029#include <limits>
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080030#include <sstream>
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080031
Ian Rogers776ac1f2012-04-13 23:36:36 -070032namespace art {
33namespace verifier {
34
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080035static const bool kIsDebugBuild = false;
36UndefinedType* UndefinedType::instance_ = NULL;
37ConflictType* ConflictType::instance_ = NULL;
38BooleanType* BooleanType::instance = NULL;
39ByteType* ByteType::instance_ = NULL;
40ShortType* ShortType::instance_ = NULL;
41CharType* CharType::instance_ = NULL;
42FloatType* FloatType::instance_ = NULL;
43LongLoType* LongLoType::instance_ = NULL;
44LongHiType* LongHiType::instance_ = NULL;
45DoubleLoType* DoubleLoType::instance_ = NULL;
46DoubleHiType* DoubleHiType::instance_ = NULL;
47IntegerType* IntegerType::instance_ = NULL;
Ian Rogers776ac1f2012-04-13 23:36:36 -070048
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080049std::string PreciseConstType::Dump() const {
50 std::stringstream result;
51 uint32_t val = ConstantValue();
52 if (val == 0) {
53 CHECK(IsPreciseConstant());
54 result << "Zero/null";
Ian Rogers776ac1f2012-04-13 23:36:36 -070055 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080056 result << "Precise ";
57 if (IsConstantShort()) {
58 result << StringPrintf("Constant: %d", val);
59 } else {
60 result << StringPrintf("Constant: 0x%x", val);
Ian Rogers776ac1f2012-04-13 23:36:36 -070061 }
62 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080063 return result.str();
64}
65
66std::string BooleanType::Dump() const {
67 return "boolean";
68}
69
70std::string ConflictType::Dump() const {
71 return "Conflict";
72}
73std::string ByteType::Dump() const {
74 return "Byte";
75}
76std::string ShortType::Dump() const {
77 return "short";
78}
79std::string CharType::Dump() const {
80 return "Char";
81}
82std::string FloatType::Dump() const {
83 return "float";
84}
85std::string LongLoType::Dump() const {
86 return "long (Low Half)";
87}
88std::string LongHiType::Dump() const {
89 return "long (High Half)";
90}
91std::string DoubleLoType::Dump() const {
92 return "Double (Low Half)";
93}
94std::string DoubleHiType::Dump() const {
95 return "Double (High Half)";
96}
97std::string IntegerType::Dump() const {
98 return "Integer";
99}
100
101
102DoubleHiType* DoubleHiType::CreateInstance(mirror::Class* klass, std::string& descriptor,
103 uint16_t cache_id) {
104 if (instance_ == NULL) {
105 instance_ = new DoubleHiType(klass, descriptor, cache_id);
106 }
107 return instance_;
108}
109
110DoubleHiType* DoubleHiType::GetInstance() {
111 CHECK(instance_ != NULL);
112 return instance_;
113}
114
115void DoubleHiType::Destroy() {
116 if (instance_ != NULL) {
117 delete instance_;
118 instance_ = NULL;
119 }
120}
121
122DoubleLoType* DoubleLoType::CreateInstance(mirror::Class* klass, std::string& descriptor,
123 uint16_t cache_id) {
124 if (instance_ == NULL) {
125 instance_ = new DoubleLoType(klass, descriptor, cache_id);
126 }
127 return instance_;
128}
129
130DoubleLoType* DoubleLoType::GetInstance() {
131 CHECK(instance_ != NULL);
132 return instance_;
133}
134
135void DoubleLoType::Destroy() {
136 if (instance_ != NULL) {
137 delete instance_;
138 instance_ = NULL;
139 }
140}
141
142LongLoType* LongLoType::CreateInstance(mirror::Class* klass, std::string& descriptor,
143 uint16_t cache_id) {
144 if (instance_ == NULL) {
145 instance_ = new LongLoType(klass, descriptor, cache_id);
146 }
147 return instance_;
148}
149
150LongHiType* LongHiType::CreateInstance(mirror::Class* klass, std::string& descriptor,
151 uint16_t cache_id) {
152 if (instance_ == NULL) {
153 instance_ = new LongHiType(klass, descriptor, cache_id);
154 }
155 return instance_;
156}
157
158LongHiType* LongHiType::GetInstance() {
159 CHECK(instance_ != NULL);
160 return instance_;
161}
162
163void LongHiType::Destroy() {
164 if (instance_ != NULL) {
165 delete instance_;
166 instance_ = NULL;
167 }
168}
169
170LongLoType* LongLoType::GetInstance() {
171 CHECK (instance_ != NULL);
172 return instance_;
173}
174
175void LongLoType::Destroy() {
176 if (instance_ != NULL) {
177 delete instance_;
178 instance_ = NULL;
179 }
180}
181
182FloatType* FloatType::CreateInstance(mirror::Class* klass, std::string& descriptor,
183 uint16_t cache_id)
184 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
185 if (instance_ == NULL) {
186 instance_ = new FloatType(klass, descriptor, cache_id);
187 }
188 return instance_;
189}
190FloatType* FloatType::GetInstance() {
191 CHECK(instance_ != NULL);
192 return instance_;
193}
194
195void FloatType::Destroy() {
196 if (instance_ != NULL) {
197 delete instance_;
198 instance_ = NULL;
199 }
200}
201
202CharType* CharType::CreateInstance(mirror::Class* klass, std::string& descriptor,
203 uint16_t cache_id) {
204 if (instance_ == NULL) {
205 instance_ = new CharType(klass, descriptor, cache_id);
206 }
207 return instance_;
208}
209CharType* CharType::GetInstance() {
210 CHECK(instance_ != NULL);
211 return instance_;
212}
213void CharType::Destroy() {
214 if (instance_ != NULL) {
215 delete instance_;
216 instance_ = NULL;
217 }
218}
219
220ShortType* ShortType::CreateInstance(mirror::Class* klass, std::string& descriptor,
221 uint16_t cache_id) {
222 if (instance_ == NULL) {
223 instance_ = new ShortType(klass, descriptor, cache_id);
224 }
225 return instance_;
226}
227ShortType* ShortType::GetInstance() {
228 CHECK(instance_ != NULL);
229 return instance_;
230}
231void ShortType::Destroy() {
232 if (instance_ != NULL) {
233 delete instance_;
234 instance_ = NULL;
235 }
236}
237ByteType* ByteType::CreateInstance(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
238 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
239 if (instance_ == NULL) {
240 instance_ = new ByteType(klass, descriptor, cache_id);
241 }
242 return instance_;
243}
244ByteType* ByteType::GetInstance() {
245 CHECK(instance_ != NULL);
246 return instance_;
247}
248void ByteType::Destroy() {
249 if (instance_ != NULL) {
250 delete instance_;
251 instance_ = NULL;
252 }
253}
254IntegerType* IntegerType::CreateInstance(mirror::Class* klass, std::string& descriptor,
255 uint16_t cache_id) {
256 if (instance_ == NULL) {
257 instance_ = new IntegerType(klass, descriptor, cache_id);
258 }
259 return instance_;
260}
261IntegerType* IntegerType::GetInstance() {
262 CHECK(instance_ != NULL);
263 return instance_;
264}
265void IntegerType::Destroy() {
266 if (instance_ != NULL) {
267 delete instance_;
268 instance_ = NULL;
269 }
270}
271ConflictType* ConflictType::CreateInstance(mirror::Class* klass, std::string& descriptor,
272 uint16_t cache_id) {
273 if (instance_ == NULL) {
274 instance_ = new ConflictType(klass, descriptor, cache_id);
275 }
276 return instance_;
277}
278ConflictType* ConflictType::GetInstance() {
279 CHECK(instance_ != NULL);
280 return instance_;
281}
282void ConflictType::Destroy() {
283 if (instance_ != NULL) {
284 delete instance_;
285 instance_ = NULL;
286 }
287}
288BooleanType* BooleanType::CreateInstance(mirror::Class* klass, std::string& descriptor,
289 uint16_t cache_id) {
290 if (BooleanType::instance == NULL) {
291 instance = new BooleanType(klass, descriptor, cache_id);
292 }
293 return BooleanType::instance;
294}
295BooleanType* BooleanType::GetInstance() {
296 CHECK(BooleanType::instance != NULL);
297 return BooleanType::instance;
298}
299
300void BooleanType::Destroy() {
301 if(BooleanType::instance != NULL) {
302 delete instance;
303 instance = NULL;
304 }
305}
306
307std::string UndefinedType::Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
308 return "Undefined";
309}
310UndefinedType* UndefinedType::CreateInstance(mirror::Class* klass, std::string& descriptor,
311 uint16_t cache_id) {
312 if (instance_ == NULL) {
313 instance_ = new UndefinedType(klass, descriptor, cache_id);
314 }
315 return instance_;
316}
317UndefinedType* UndefinedType::GetInstance() {
318 CHECK(instance_ != NULL);
319 return instance_;
320}
321void UndefinedType::Destroy() {
322 if (instance_ != NULL) {
323 delete instance_;
324 instance_ = NULL;
325 }
326}
327std::string UnresolvedMergedType::Dump() const {
328 std::stringstream result;
329 std::set<uint16_t> types = GetMergedTypes();
330 result << "UnresolvedMergedReferences(";
331 typedef std::set<uint16_t>::const_iterator It; // TODO: C++0x auto
332 It it = types.begin();
333 result << reg_type_cache_->GetFromId(*it).Dump();
334 for (++it; it != types.end(); ++it) {
335 result << ", ";
336 result << reg_type_cache_->GetFromId(*it).Dump();
337 }
338 result << ")";
339 return result.str();
340}
341std::string UnresolvedSuperClass::Dump() const {
342 std::stringstream result;
343 uint16_t super_type_id = GetUnresolvedSuperClassChildId();
344 result << "UnresolvedSuperClass(" << reg_type_cache_->GetFromId(super_type_id).Dump() << ")";
345 return result.str();
346}
347
348std::string UnresolvedReferenceType::Dump() const {
349 std::stringstream result;
350 result << "Unresolved Reference" << ": " << PrettyDescriptor(GetDescriptor());
351 return result.str();
352}
353
354std::string UnresolvedUninitializedRefType::Dump() const {
355 std::stringstream result;
356 result << "Unresolved And Uninitialized Reference" << ": " << PrettyDescriptor(GetDescriptor());
357 result << " Allocation PC: " << GetAllocationPc();
358 return result.str();
359}
360
361std::string UnresolvedUninitialisedThisRefType::Dump() const {
362 std::stringstream result;
363 result << "Unresolved And Uninitialized This Reference" << PrettyDescriptor(GetDescriptor());
364 return result.str();
365}
366
367std::string ReferenceType::Dump() const {
368 std::stringstream result;
369 result << "Reference" << ": " << PrettyDescriptor(GetClass());
370 return result.str();
371}
372
373std::string PreciseReferenceType::Dump() const {
374 std::stringstream result;
375 result << "Precise Reference" << ": "<< PrettyDescriptor(GetClass());
376 return result.str();
377}
378
379std::string UninitialisedReferenceType::Dump() const {
380 std::stringstream result;
381 result << "Uninitialized Reference" << ": " << PrettyDescriptor(GetClass());
382 result << " Allocation PC: " << GetAllocationPc();
383 return result.str();
384}
385std::string UninitialisedThisReferenceType::Dump() const {
386 std::stringstream result;
387 result << "Uninitialized This Reference" << ": " << PrettyDescriptor(GetClass());
388 result << "Allocation PC: " << GetAllocationPc();
389 return result.str();
390}
391
392std::string ImpreciseConstType::Dump() const {
393 std::stringstream result;
394 uint32_t val = ConstantValue();
395 if (val == 0) {
396 CHECK(IsPreciseConstant());
397 result << "Zero/null";
398 } else {
399 result << "Imprecise ";
400 if (IsConstantShort()) {
401 result << StringPrintf("Constant: %d", val);
402 } else {
403 result << StringPrintf("Constant: 0x%x", val);
404 }
405 }
406 return result.str();
407}
408std::string PreciseConstLoType::Dump() const {
409 std::stringstream result;
410
411 int32_t val = ConstantValueLo();
412 result << "Precise ";
413 if (val >= std::numeric_limits<jshort>::min() &&
414 val <= std::numeric_limits<jshort>::max()) {
415 result << StringPrintf("Low-half Constant: %d", val);
416 } else {
417 result << StringPrintf("Low-half Constant: 0x%x", val);
418 }
419 return result.str();
420}
421
422std::string ImpreciseConstLoType::Dump() const {
423 std::stringstream result;
424
425 int32_t val = ConstantValueLo();
426 result << "Imprecise ";
427 if (val >= std::numeric_limits<jshort>::min() &&
428 val <= std::numeric_limits<jshort>::max()) {
429 result << StringPrintf("Low-half Constant: %d", val);
430 } else {
431 result << StringPrintf("Low-half Constant: 0x%x", val);
432 }
433 return result.str();
434}
435
436std::string PreciseConstHiType::Dump() const {
437 std::stringstream result;
438 int32_t val = ConstantValueHi();
439 result << "Precise ";
440 if (val >= std::numeric_limits<jshort>::min() &&
441 val <= std::numeric_limits<jshort>::max()) {
442 result << StringPrintf("High-half Constant: %d", val);
443 } else {
444 result << StringPrintf("High-half Constant: 0x%x", val);
445 }
446 return result.str();
447}
448
449std::string ImpreciseConstHiType::Dump() const {
450 std::stringstream result;
451 int32_t val = ConstantValueHi();
452 result << "Imprecise ";
453 if (val >= std::numeric_limits<jshort>::min() &&
454 val <= std::numeric_limits<jshort>::max()) {
455 result << StringPrintf("High-half Constant: %d", val);
456 } else {
457 result << StringPrintf("High-half Constant: 0x%x", val);
458 }
459 return result.str();
460}
461
462BooleanType::BooleanType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
463 : RegType(klass, descriptor, cache_id) {
464}
465
466ConflictType::ConflictType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
467 : RegType(klass, descriptor, cache_id) {
468}
469
470ByteType::ByteType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
471 : RegType(klass, descriptor, cache_id) {
472}
473
474ShortType::ShortType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
475 : RegType(klass, descriptor, cache_id) {
476}
477
478CharType::CharType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
479 : RegType(klass, descriptor, cache_id) {
480}
481
482IntegerType::IntegerType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
483 : RegType(klass, descriptor, cache_id) {
484}
485
486ConstantType::ConstantType(uint32_t constat, uint16_t cache_id)
487 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_): RegType(NULL, "", cache_id), constant_(constat) {
488}
489
490ReferenceType::ReferenceType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
491 : RegType(klass, descriptor, cache_id) {
492}
493
494PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, std::string& descriptor,
495 uint16_t cache_id)
496 : RegType(klass, descriptor, cache_id) {
497}
498
499UnresolvedUninitialisedThisRefType::UnresolvedUninitialisedThisRefType(std::string& descriptor,
500 uint16_t cache_id)
501 : UninitializedType(NULL, descriptor, 0, cache_id) {
502}
503
504UnresolvedUninitializedRefType::UnresolvedUninitializedRefType( std::string& descriptor,
505 uint32_t allocation_pc, uint16_t cache_id)
506 : UninitializedType(NULL, descriptor, allocation_pc, cache_id) {
507}
508
509UninitialisedReferenceType::UninitialisedReferenceType(mirror::Class* klass,
510 std::string& descriptor, uint32_t allocation_pc, uint16_t cache_id)
511 : UninitializedType(klass, descriptor, allocation_pc, cache_id) {
512}
513
514LongHiType::LongHiType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
515 : RegType(klass, descriptor, cache_id) {
516}
517
518FloatType::FloatType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
519 : RegType(klass, descriptor, cache_id) {
520}
521
522DoubleLoType::DoubleLoType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
523 : RegType(klass, descriptor, cache_id) {
524}
525
526DoubleHiType::DoubleHiType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
527 : RegType(klass, descriptor, cache_id) {
528}
529
530LongLoType::LongLoType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
531 : RegType(klass, descriptor, cache_id) {
532}
533
534const 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
577std::set<uint16_t> UnresolvedMergedType::GetMergedTypes() const {
Ian Rogers529781d2012-07-23 17:24:29 -0700578 std::pair<uint16_t, uint16_t> refs = GetTopMergedTypes();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800579 const RegType& _left(reg_type_cache_->GetFromId(refs.first));
580 RegType& __left(const_cast<RegType&>(_left));
581 UnresolvedMergedType* left = down_cast<UnresolvedMergedType*>(&__left);
582
583 RegType& _right(
584 const_cast<RegType&>(reg_type_cache_->GetFromId(refs.second)));
585 UnresolvedMergedType* right = down_cast<UnresolvedMergedType*>(&_right);
586
Ian Rogers529781d2012-07-23 17:24:29 -0700587 std::set<uint16_t> types;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800588 if (left->IsUnresolvedMergedReference()) {
589 types = left->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700590 } else {
591 types.insert(refs.first);
592 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800593 if (right->IsUnresolvedMergedReference()) {
594 std::set<uint16_t> right_types = right->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700595 types.insert(right_types.begin(), right_types.end());
596 } else {
597 types.insert(refs.second);
598 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800599 if (kIsDebugBuild) {
600 typedef std::set<uint16_t>::const_iterator It; // TODO: C++0x auto
601 for (It it = types.begin(); it != types.end(); ++it) {
602 CHECK(!reg_type_cache_->GetFromId(*it).IsUnresolvedMergedReference());
603 }
Ian Rogers529781d2012-07-23 17:24:29 -0700604 }
Ian Rogers529781d2012-07-23 17:24:29 -0700605 return types;
606}
607
Ian Rogersad0b3a32012-04-16 14:50:24 -0700608const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
609 if (!IsUnresolvedTypes()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800610 mirror::Class* super_klass = GetClass()->GetSuperClass();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700611 if (super_klass != NULL) {
Ian Rogersb4903572012-10-11 11:52:56 -0700612 return cache->FromClass(super_klass, IsPreciseReference());
Ian Rogers0d604842012-04-16 14:50:24 -0700613 } else {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700614 return cache->Zero();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700615 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700616 } else {
Ian Rogers529781d2012-07-23 17:24:29 -0700617 if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
Elliott Hughes80537bb2013-01-04 16:37:26 -0800618 GetDescriptor()[0] == '[') {
Ian Rogers529781d2012-07-23 17:24:29 -0700619 // Super class of all arrays is Object.
Ian Rogersb4903572012-10-11 11:52:56 -0700620 return cache->JavaLangObject(true);
Ian Rogers529781d2012-07-23 17:24:29 -0700621 } else {
622 return cache->FromUnresolvedSuperClass(*this);
623 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700624 }
625}
626
627bool RegType::CanAccess(const RegType& other) const {
628 if (Equals(other)) {
629 return true; // Trivial accessibility.
630 } else {
631 bool this_unresolved = IsUnresolvedTypes();
632 bool other_unresolved = other.IsUnresolvedTypes();
633 if (!this_unresolved && !other_unresolved) {
634 return GetClass()->CanAccess(other.GetClass());
635 } else if (!other_unresolved) {
636 return other.GetClass()->IsPublic(); // Be conservative, only allow if other is public.
637 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800638 return false; // More complicated test not possible on unresolved types, be conservative.
Ian Rogerse1758fe2012-04-19 11:31:15 -0700639 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700640 }
641}
642
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800643bool RegType::CanAccessMember(mirror::Class* klass, uint32_t access_flags) const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800644 if ((access_flags & kAccPublic) != 0) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700645 return true;
646 }
647 if (!IsUnresolvedTypes()) {
648 return GetClass()->CanAccessMember(klass, access_flags);
649 } else {
650 return false; // More complicated test not possible on unresolved types, be conservative.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700651 }
652}
653
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800654bool RegType::IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
655 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
656 // Primitive arrays will always resolve
657 DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
658 return descriptor_[0] == '[';
659 } else if (HasClass()) {
660 mirror::Class* type = GetClass();
661 return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
662 } else {
663 return false;
664 }
665}
666
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800667bool RegType::IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
668 return IsReference() && GetClass()->IsObjectClass();
669}
670
671bool RegType::IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
672 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
673 return descriptor_[0] == '[';
674 } else if (HasClass()) {
675 return GetClass()->IsArrayClass();
676 } else {
677 return false;
678 }
679}
680
681bool RegType::IsJavaLangObjectArray() const {
682 if (HasClass()) {
683 mirror::Class* type = GetClass();
684 return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
685 }
686 return false;
687}
688
689bool RegType::IsInstantiableTypes() const {
690 return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
691}
692
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800693ImpreciseConstType::ImpreciseConstType(uint32_t constat, uint16_t cache_id)
694 : ConstantType(constat, cache_id) {
695}
696
Ian Rogers776ac1f2012-04-13 23:36:36 -0700697bool RegType::IsAssignableFrom(const RegType& src) const {
698 if (Equals(src)) {
699 return true;
700 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800701 if (IsBoolean()) {
702 return src.IsBooleanTypes();
703 } else if (IsByte()) {
704 return src.IsByteTypes();
705 } else if (IsShort()) {
706 return src.IsShortTypes();
707 } else if (IsChar()) {
708 return src.IsCharTypes();
709 } else if (IsInteger()) {
710 return src.IsIntegralTypes();
711 } else if (IsFloat()) {
712 return src.IsFloatTypes();
713 } else if (IsLongLo()) {
714 return src.IsLongTypes();
715 } else if (IsDoubleLo()) {
716 return src.IsDoubleTypes();
717 } else {
718 if (!IsReferenceTypes()) {
719 LOG(FATAL) << "Unexpected register type in 4bleFrom: '" << src << "'";
720 }
721 if (src.IsZero()) {
722 return true; // all reference types can be assigned null
723 } else if (!src.IsReferenceTypes()) {
724 return false; // expect src to be a reference type
725 } else if (IsJavaLangObject()) {
726 return true; // all reference types can be assigned to Object
727 } else if (!IsUnresolvedTypes() && GetClass()->IsInterface()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700728 return true; // We allow assignment to any interface, see comment in ClassJoin
729 } else if (IsJavaLangObjectArray()) {
730 return src.IsObjectArrayTypes(); // All reference arrays may be assigned to Object[]
731 } else if (!IsUnresolvedTypes() && !src.IsUnresolvedTypes() &&
732 GetClass()->IsAssignableFrom(src.GetClass())) {
733 // We're assignable from the Class point-of-view
734 return true;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800735 } else if (IsUnresolvedTypes()) {
736 // Unresolved types are only assignable for null, Object and equality.
737 return (src.IsZero() || src.IsJavaLangObject());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700738 } else {
739 return false;
740 }
741 }
742 }
743}
744
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800745int32_t ConstantType::ConstantValue() const {
746 DCHECK(IsConstantTypes());
747 return constant_;
748}
749int32_t ConstantType::ConstantValueLo() const {
750 DCHECK(IsConstantLo());
751 return constant_;
752}
753int32_t ConstantType::ConstantValueHi() const {
754 if (IsConstantHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()) {
755 return constant_;
756 } else {
757 DCHECK(false);
758 return 0;
759 }
760}
Ian Rogers776ac1f2012-04-13 23:36:36 -0700761static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
762 return a.IsConstant() ? b : a;
763}
764
765const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
766 DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800767 if (IsConflict()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700768 return *this; // Conflict MERGE * => Conflict
769 } else if (incoming_type.IsConflict()) {
770 return incoming_type; // * MERGE Conflict => Conflict
Ian Rogersad0b3a32012-04-16 14:50:24 -0700771 } else if (IsUndefined() || incoming_type.IsUndefined()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700772 return reg_types->Conflict(); // Unknown MERGE * => Conflict
773 } else if (IsConstant() && incoming_type.IsConstant()) {
774 int32_t val1 = ConstantValue();
775 int32_t val2 = incoming_type.ConstantValue();
776 if (val1 >= 0 && val2 >= 0) {
777 // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
778 if (val1 >= val2) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800779 if (!IsPreciseConstant()) {
780 return *this;
781 } else {
782 return reg_types->FromCat1Const(val1, false);
783 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700784 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800785 if (!incoming_type.IsPreciseConstant()) {
786 return incoming_type;
787 } else {
788 return reg_types->FromCat1Const(val2, false);
789 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700790 }
791 } else if (val1 < 0 && val2 < 0) {
792 // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
793 if (val1 <= val2) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800794 if (!IsPreciseConstant()) {
795 return *this;
796 } else {
797 return reg_types->FromCat1Const(val1, false);
798 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700799 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800800 if (!incoming_type.IsPreciseConstant()) {
801 return incoming_type;
802 } else {
803 return reg_types->FromCat1Const(val2, false);
804 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700805 }
806 } else {
807 // Values are +ve and -ve, choose smallest signed type in which they both fit
808 if (IsConstantByte()) {
809 if (incoming_type.IsConstantByte()) {
810 return reg_types->ByteConstant();
811 } else if (incoming_type.IsConstantShort()) {
812 return reg_types->ShortConstant();
813 } else {
814 return reg_types->IntConstant();
815 }
816 } else if (IsConstantShort()) {
817 if (incoming_type.IsConstantShort()) {
818 return reg_types->ShortConstant();
819 } else {
820 return reg_types->IntConstant();
821 }
822 } else {
823 return reg_types->IntConstant();
824 }
825 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800826 } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
827 int32_t val1 = ConstantValueLo();
828 int32_t val2 = incoming_type.ConstantValueLo();
829 return reg_types->FromCat2ConstLo(val1 | val2, false);
830 } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
831 int32_t val1 = ConstantValueHi();
832 int32_t val2 = incoming_type.ConstantValueHi();
833 return reg_types->FromCat2ConstHi(val1 | val2, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700834 } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
835 if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
836 return reg_types->Boolean(); // boolean MERGE boolean => boolean
837 }
838 if (IsByteTypes() && incoming_type.IsByteTypes()) {
839 return reg_types->Byte(); // byte MERGE byte => byte
840 }
841 if (IsShortTypes() && incoming_type.IsShortTypes()) {
842 return reg_types->Short(); // short MERGE short => short
843 }
844 if (IsCharTypes() && incoming_type.IsCharTypes()) {
845 return reg_types->Char(); // char MERGE char => char
846 }
847 return reg_types->Integer(); // int MERGE * => int
848 } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
849 (IsLongTypes() && incoming_type.IsLongTypes()) ||
850 (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
851 (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
852 (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
853 // check constant case was handled prior to entry
854 DCHECK(!IsConstant() || !incoming_type.IsConstant());
855 // float/long/double MERGE float/long/double_constant => float/long/double
856 return SelectNonConstant(*this, incoming_type);
857 } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
858 if (IsZero() || incoming_type.IsZero()) {
859 return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref
860 } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
Ian Rogersb4903572012-10-11 11:52:56 -0700861 return reg_types->JavaLangObject(false); // Object MERGE ref => Object
Ian Rogers529781d2012-07-23 17:24:29 -0700862 } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
863 // We know how to merge an unresolved type with itself, 0 or Object. In this case we
864 // have two sub-classes and don't know how to merge. Create a new string-based unresolved
865 // type that reflects our lack of knowledge and that allows the rest of the unresolved
866 // mechanics to continue.
867 return reg_types->FromUnresolvedMerge(*this, incoming_type);
868 } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
869 // Something that is uninitialized hasn't had its constructor called. Mark any merge
870 // of this type with something that is initialized as conflicting. The cases of a merge
871 // with itself, 0 or Object are handled above.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700872 return reg_types->Conflict();
873 } else { // Two reference types, compute Join
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800874 mirror::Class* c1 = GetClass();
875 mirror::Class* c2 = incoming_type.GetClass();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700876 DCHECK(c1 != NULL && !c1->IsPrimitive());
877 DCHECK(c2 != NULL && !c2->IsPrimitive());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800878 mirror::Class* join_class = ClassJoin(c1, c2);
Ian Rogersb4903572012-10-11 11:52:56 -0700879 if (c1 == join_class && !IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700880 return *this;
Ian Rogersb4903572012-10-11 11:52:56 -0700881 } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700882 return incoming_type;
883 } else {
Ian Rogersb4903572012-10-11 11:52:56 -0700884 return reg_types->FromClass(join_class, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700885 }
886 }
887 } else {
888 return reg_types->Conflict(); // Unexpected types => Conflict
889 }
890}
891
Ian Rogersad0b3a32012-04-16 14:50:24 -0700892// See comment in reg_type.h
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800893mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700894 DCHECK(!s->IsPrimitive()) << PrettyClass(s);
895 DCHECK(!t->IsPrimitive()) << PrettyClass(t);
896 if (s == t) {
897 return s;
898 } else if (s->IsAssignableFrom(t)) {
899 return s;
900 } else if (t->IsAssignableFrom(s)) {
901 return t;
902 } else if (s->IsArrayClass() && t->IsArrayClass()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800903 mirror::Class* s_ct = s->GetComponentType();
904 mirror::Class* t_ct = t->GetComponentType();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700905 if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
906 // Given the types aren't the same, if either array is of primitive types then the only
907 // common parent is java.lang.Object
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800908 mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object
Ian Rogersad0b3a32012-04-16 14:50:24 -0700909 DCHECK(result->IsObjectClass());
910 return result;
911 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800912 mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700913 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800914 mirror::ClassLoader* class_loader = s->GetClassLoader();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700915 std::string descriptor("[");
916 descriptor += ClassHelper(common_elem).GetDescriptor();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800917 mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700918 DCHECK(array_class != NULL);
919 return array_class;
920 } else {
921 size_t s_depth = s->Depth();
922 size_t t_depth = t->Depth();
923 // Get s and t to the same depth in the hierarchy
924 if (s_depth > t_depth) {
925 while (s_depth > t_depth) {
926 s = s->GetSuperClass();
927 s_depth--;
928 }
929 } else {
930 while (t_depth > s_depth) {
931 t = t->GetSuperClass();
932 t_depth--;
933 }
934 }
935 // Go up the hierarchy until we get to the common parent
936 while (s != t) {
937 s = s->GetSuperClass();
938 t = t->GetSuperClass();
939 }
940 return s;
941 }
942}
943
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800944void RegType::CheckInvariants() const {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800945 if (IsConstant() || IsConstantLo() || IsConstantHi()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800946 CHECK(descriptor_.empty()) << *this;
947 CHECK(klass_ == NULL) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800948 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800949}
950
951UninitializedType::UninitializedType(mirror::Class* klass, std::string& descriptor,
952 uint32_t allocation_pc, uint16_t cache_id)
953 : RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {
954}
955
956void UninitializedType::CheckInvariants() const {
957 CHECK_EQ(allocation_pc_, 0U) << *this;
958}
959
960void UninitialisedThisReferenceType::CheckInvariants() const {
961 UninitializedType::CheckInvariants();
962}
963
964UninitialisedThisReferenceType::UninitialisedThisReferenceType(mirror::Class* klass,
965 std::string& descriptor, uint16_t cache_id) : UninitializedType(klass, descriptor, 0, cache_id) {
966}
967
968void UnresolvedUninitialisedThisRefType::CheckInvariants() const {
969 UninitializedType::CheckInvariants();
970 CHECK(!descriptor_.empty()) << *this;
971 CHECK(klass_ == NULL) << *this;
972}
973
974void UnresolvedUninitializedRefType::CheckInvariants() const {
975 UninitializedType::CheckInvariants();
976 CHECK(!descriptor_.empty()) << *this;
977 CHECK(klass_ == NULL) << *this;
978}
979
980void UnresolvedMergedType::CheckInvariants() const {
981 // Unresolved merged types: merged types should be defined.
982 CHECK(descriptor_.empty()) << *this;
983 CHECK(klass_ == NULL) << *this;
984 CHECK_NE(merged_types_.first, 0U) << *this;
985 CHECK_NE(merged_types_.second, 0U) << *this;
986}
987
988void UnresolvedReferenceType::CheckInvariants() const {
989 CHECK(!descriptor_.empty()) << *this;
990 CHECK(klass_ == NULL) << *this;
991}
992
993void UnresolvedSuperClass::CheckInvariants() const {
994 // Unresolved merged types: merged types should be defined.
995 CHECK(descriptor_.empty()) << *this;
996 CHECK(klass_ == NULL) << *this;
997 CHECK_NE(unresolved_child_id_, 0U) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800998}
999
1000std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
Ian Rogers776ac1f2012-04-13 23:36:36 -07001001 os << rhs.Dump();
1002 return os;
1003}
1004
Elliott Hughesa21039c2012-06-21 12:09:25 -07001005} // namespace verifier
1006} // namespace art