blob: 32679f610026b0b51178555bc4d61e79ae3f6d97 [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) {
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700497 DCHECK(klass->IsInstantiable());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800498}
499
500UnresolvedUninitialisedThisRefType::UnresolvedUninitialisedThisRefType(std::string& descriptor,
501 uint16_t cache_id)
502 : UninitializedType(NULL, descriptor, 0, cache_id) {
503}
504
505UnresolvedUninitializedRefType::UnresolvedUninitializedRefType( std::string& descriptor,
506 uint32_t allocation_pc, uint16_t cache_id)
507 : UninitializedType(NULL, descriptor, allocation_pc, cache_id) {
508}
509
510UninitialisedReferenceType::UninitialisedReferenceType(mirror::Class* klass,
511 std::string& descriptor, uint32_t allocation_pc, uint16_t cache_id)
512 : UninitializedType(klass, descriptor, allocation_pc, cache_id) {
513}
514
515LongHiType::LongHiType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
516 : RegType(klass, descriptor, cache_id) {
517}
518
519FloatType::FloatType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
520 : RegType(klass, descriptor, cache_id) {
521}
522
523DoubleLoType::DoubleLoType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
524 : RegType(klass, descriptor, cache_id) {
525}
526
527DoubleHiType::DoubleHiType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
528 : RegType(klass, descriptor, cache_id) {
529}
530
531LongLoType::LongLoType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
532 : RegType(klass, descriptor, cache_id) {
533}
534
535const 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
578std::set<uint16_t> UnresolvedMergedType::GetMergedTypes() const {
Ian Rogers529781d2012-07-23 17:24:29 -0700579 std::pair<uint16_t, uint16_t> refs = GetTopMergedTypes();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800580 const RegType& _left(reg_type_cache_->GetFromId(refs.first));
581 RegType& __left(const_cast<RegType&>(_left));
582 UnresolvedMergedType* left = down_cast<UnresolvedMergedType*>(&__left);
583
584 RegType& _right(
585 const_cast<RegType&>(reg_type_cache_->GetFromId(refs.second)));
586 UnresolvedMergedType* right = down_cast<UnresolvedMergedType*>(&_right);
587
Ian Rogers529781d2012-07-23 17:24:29 -0700588 std::set<uint16_t> types;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800589 if (left->IsUnresolvedMergedReference()) {
590 types = left->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700591 } else {
592 types.insert(refs.first);
593 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800594 if (right->IsUnresolvedMergedReference()) {
595 std::set<uint16_t> right_types = right->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700596 types.insert(right_types.begin(), right_types.end());
597 } else {
598 types.insert(refs.second);
599 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800600 if (kIsDebugBuild) {
601 typedef std::set<uint16_t>::const_iterator It; // TODO: C++0x auto
602 for (It it = types.begin(); it != types.end(); ++it) {
603 CHECK(!reg_type_cache_->GetFromId(*it).IsUnresolvedMergedReference());
604 }
Ian Rogers529781d2012-07-23 17:24:29 -0700605 }
Ian Rogers529781d2012-07-23 17:24:29 -0700606 return types;
607}
608
Ian Rogersad0b3a32012-04-16 14:50:24 -0700609const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
610 if (!IsUnresolvedTypes()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800611 mirror::Class* super_klass = GetClass()->GetSuperClass();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700612 if (super_klass != NULL) {
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700613 // A super class of a precise type isn't precise as a precise type indicates the register
614 // holds exactly that type.
615 return cache->FromClass(super_klass, false);
Ian Rogers0d604842012-04-16 14:50:24 -0700616 } else {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700617 return cache->Zero();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700618 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700619 } else {
Ian Rogers529781d2012-07-23 17:24:29 -0700620 if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
Elliott Hughes80537bb2013-01-04 16:37:26 -0800621 GetDescriptor()[0] == '[') {
Ian Rogers529781d2012-07-23 17:24:29 -0700622 // Super class of all arrays is Object.
Ian Rogersb4903572012-10-11 11:52:56 -0700623 return cache->JavaLangObject(true);
Ian Rogers529781d2012-07-23 17:24:29 -0700624 } else {
625 return cache->FromUnresolvedSuperClass(*this);
626 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700627 }
628}
629
630bool RegType::CanAccess(const RegType& other) const {
631 if (Equals(other)) {
632 return true; // Trivial accessibility.
633 } else {
634 bool this_unresolved = IsUnresolvedTypes();
635 bool other_unresolved = other.IsUnresolvedTypes();
636 if (!this_unresolved && !other_unresolved) {
637 return GetClass()->CanAccess(other.GetClass());
638 } else if (!other_unresolved) {
639 return other.GetClass()->IsPublic(); // Be conservative, only allow if other is public.
640 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800641 return false; // More complicated test not possible on unresolved types, be conservative.
Ian Rogerse1758fe2012-04-19 11:31:15 -0700642 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700643 }
644}
645
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800646bool RegType::CanAccessMember(mirror::Class* klass, uint32_t access_flags) const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800647 if ((access_flags & kAccPublic) != 0) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700648 return true;
649 }
650 if (!IsUnresolvedTypes()) {
651 return GetClass()->CanAccessMember(klass, access_flags);
652 } else {
653 return false; // More complicated test not possible on unresolved types, be conservative.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700654 }
655}
656
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800657bool RegType::IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
658 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
659 // Primitive arrays will always resolve
660 DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
661 return descriptor_[0] == '[';
662 } else if (HasClass()) {
663 mirror::Class* type = GetClass();
664 return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
665 } else {
666 return false;
667 }
668}
669
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800670bool RegType::IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
671 return IsReference() && GetClass()->IsObjectClass();
672}
673
674bool RegType::IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
675 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
676 return descriptor_[0] == '[';
677 } else if (HasClass()) {
678 return GetClass()->IsArrayClass();
679 } else {
680 return false;
681 }
682}
683
684bool RegType::IsJavaLangObjectArray() const {
685 if (HasClass()) {
686 mirror::Class* type = GetClass();
687 return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
688 }
689 return false;
690}
691
692bool RegType::IsInstantiableTypes() const {
693 return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
694}
695
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800696ImpreciseConstType::ImpreciseConstType(uint32_t constat, uint16_t cache_id)
697 : ConstantType(constat, cache_id) {
698}
699
Ian Rogers776ac1f2012-04-13 23:36:36 -0700700bool RegType::IsAssignableFrom(const RegType& src) const {
701 if (Equals(src)) {
702 return true;
703 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800704 if (IsBoolean()) {
705 return src.IsBooleanTypes();
706 } else if (IsByte()) {
707 return src.IsByteTypes();
708 } else if (IsShort()) {
709 return src.IsShortTypes();
710 } else if (IsChar()) {
711 return src.IsCharTypes();
712 } else if (IsInteger()) {
713 return src.IsIntegralTypes();
714 } else if (IsFloat()) {
715 return src.IsFloatTypes();
716 } else if (IsLongLo()) {
717 return src.IsLongTypes();
718 } else if (IsDoubleLo()) {
719 return src.IsDoubleTypes();
720 } else {
721 if (!IsReferenceTypes()) {
722 LOG(FATAL) << "Unexpected register type in 4bleFrom: '" << src << "'";
723 }
724 if (src.IsZero()) {
725 return true; // all reference types can be assigned null
726 } else if (!src.IsReferenceTypes()) {
727 return false; // expect src to be a reference type
728 } else if (IsJavaLangObject()) {
729 return true; // all reference types can be assigned to Object
730 } else if (!IsUnresolvedTypes() && GetClass()->IsInterface()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700731 return true; // We allow assignment to any interface, see comment in ClassJoin
732 } else if (IsJavaLangObjectArray()) {
733 return src.IsObjectArrayTypes(); // All reference arrays may be assigned to Object[]
734 } else if (!IsUnresolvedTypes() && !src.IsUnresolvedTypes() &&
735 GetClass()->IsAssignableFrom(src.GetClass())) {
736 // We're assignable from the Class point-of-view
737 return true;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800738 } else if (IsUnresolvedTypes()) {
739 // Unresolved types are only assignable for null, Object and equality.
740 return (src.IsZero() || src.IsJavaLangObject());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700741 } else {
742 return false;
743 }
744 }
745 }
746}
747
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800748int32_t ConstantType::ConstantValue() const {
749 DCHECK(IsConstantTypes());
750 return constant_;
751}
752int32_t ConstantType::ConstantValueLo() const {
753 DCHECK(IsConstantLo());
754 return constant_;
755}
756int32_t ConstantType::ConstantValueHi() const {
757 if (IsConstantHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()) {
758 return constant_;
759 } else {
760 DCHECK(false);
761 return 0;
762 }
763}
Ian Rogers776ac1f2012-04-13 23:36:36 -0700764static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
765 return a.IsConstant() ? b : a;
766}
767
768const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
769 DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800770 if (IsConflict()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700771 return *this; // Conflict MERGE * => Conflict
772 } else if (incoming_type.IsConflict()) {
773 return incoming_type; // * MERGE Conflict => Conflict
Ian Rogersad0b3a32012-04-16 14:50:24 -0700774 } else if (IsUndefined() || incoming_type.IsUndefined()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700775 return reg_types->Conflict(); // Unknown MERGE * => Conflict
776 } else if (IsConstant() && incoming_type.IsConstant()) {
777 int32_t val1 = ConstantValue();
778 int32_t val2 = incoming_type.ConstantValue();
779 if (val1 >= 0 && val2 >= 0) {
780 // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
781 if (val1 >= val2) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800782 if (!IsPreciseConstant()) {
783 return *this;
784 } else {
785 return reg_types->FromCat1Const(val1, false);
786 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700787 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800788 if (!incoming_type.IsPreciseConstant()) {
789 return incoming_type;
790 } else {
791 return reg_types->FromCat1Const(val2, false);
792 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700793 }
794 } else if (val1 < 0 && val2 < 0) {
795 // -ve1 MERGE -ve2 => MIN(-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 {
810 // Values are +ve and -ve, choose smallest signed type in which they both fit
811 if (IsConstantByte()) {
812 if (incoming_type.IsConstantByte()) {
813 return reg_types->ByteConstant();
814 } else if (incoming_type.IsConstantShort()) {
815 return reg_types->ShortConstant();
816 } else {
817 return reg_types->IntConstant();
818 }
819 } else if (IsConstantShort()) {
820 if (incoming_type.IsConstantShort()) {
821 return reg_types->ShortConstant();
822 } else {
823 return reg_types->IntConstant();
824 }
825 } else {
826 return reg_types->IntConstant();
827 }
828 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800829 } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
830 int32_t val1 = ConstantValueLo();
831 int32_t val2 = incoming_type.ConstantValueLo();
832 return reg_types->FromCat2ConstLo(val1 | val2, false);
833 } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
834 int32_t val1 = ConstantValueHi();
835 int32_t val2 = incoming_type.ConstantValueHi();
836 return reg_types->FromCat2ConstHi(val1 | val2, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700837 } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
838 if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
839 return reg_types->Boolean(); // boolean MERGE boolean => boolean
840 }
841 if (IsByteTypes() && incoming_type.IsByteTypes()) {
842 return reg_types->Byte(); // byte MERGE byte => byte
843 }
844 if (IsShortTypes() && incoming_type.IsShortTypes()) {
845 return reg_types->Short(); // short MERGE short => short
846 }
847 if (IsCharTypes() && incoming_type.IsCharTypes()) {
848 return reg_types->Char(); // char MERGE char => char
849 }
850 return reg_types->Integer(); // int MERGE * => int
851 } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
852 (IsLongTypes() && incoming_type.IsLongTypes()) ||
853 (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
854 (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
855 (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
856 // check constant case was handled prior to entry
857 DCHECK(!IsConstant() || !incoming_type.IsConstant());
858 // float/long/double MERGE float/long/double_constant => float/long/double
859 return SelectNonConstant(*this, incoming_type);
860 } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
861 if (IsZero() || incoming_type.IsZero()) {
862 return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref
863 } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
Ian Rogersb4903572012-10-11 11:52:56 -0700864 return reg_types->JavaLangObject(false); // Object MERGE ref => Object
Ian Rogers529781d2012-07-23 17:24:29 -0700865 } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
866 // We know how to merge an unresolved type with itself, 0 or Object. In this case we
867 // have two sub-classes and don't know how to merge. Create a new string-based unresolved
868 // type that reflects our lack of knowledge and that allows the rest of the unresolved
869 // mechanics to continue.
870 return reg_types->FromUnresolvedMerge(*this, incoming_type);
871 } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
872 // Something that is uninitialized hasn't had its constructor called. Mark any merge
873 // of this type with something that is initialized as conflicting. The cases of a merge
874 // with itself, 0 or Object are handled above.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700875 return reg_types->Conflict();
876 } else { // Two reference types, compute Join
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800877 mirror::Class* c1 = GetClass();
878 mirror::Class* c2 = incoming_type.GetClass();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700879 DCHECK(c1 != NULL && !c1->IsPrimitive());
880 DCHECK(c2 != NULL && !c2->IsPrimitive());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800881 mirror::Class* join_class = ClassJoin(c1, c2);
Ian Rogersb4903572012-10-11 11:52:56 -0700882 if (c1 == join_class && !IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700883 return *this;
Ian Rogersb4903572012-10-11 11:52:56 -0700884 } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700885 return incoming_type;
886 } else {
Ian Rogersb4903572012-10-11 11:52:56 -0700887 return reg_types->FromClass(join_class, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700888 }
889 }
890 } else {
891 return reg_types->Conflict(); // Unexpected types => Conflict
892 }
893}
894
Ian Rogersad0b3a32012-04-16 14:50:24 -0700895// See comment in reg_type.h
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800896mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700897 DCHECK(!s->IsPrimitive()) << PrettyClass(s);
898 DCHECK(!t->IsPrimitive()) << PrettyClass(t);
899 if (s == t) {
900 return s;
901 } else if (s->IsAssignableFrom(t)) {
902 return s;
903 } else if (t->IsAssignableFrom(s)) {
904 return t;
905 } else if (s->IsArrayClass() && t->IsArrayClass()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800906 mirror::Class* s_ct = s->GetComponentType();
907 mirror::Class* t_ct = t->GetComponentType();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700908 if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
909 // Given the types aren't the same, if either array is of primitive types then the only
910 // common parent is java.lang.Object
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800911 mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object
Ian Rogersad0b3a32012-04-16 14:50:24 -0700912 DCHECK(result->IsObjectClass());
913 return result;
914 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800915 mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700916 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800917 mirror::ClassLoader* class_loader = s->GetClassLoader();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700918 std::string descriptor("[");
919 descriptor += ClassHelper(common_elem).GetDescriptor();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800920 mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700921 DCHECK(array_class != NULL);
922 return array_class;
923 } else {
924 size_t s_depth = s->Depth();
925 size_t t_depth = t->Depth();
926 // Get s and t to the same depth in the hierarchy
927 if (s_depth > t_depth) {
928 while (s_depth > t_depth) {
929 s = s->GetSuperClass();
930 s_depth--;
931 }
932 } else {
933 while (t_depth > s_depth) {
934 t = t->GetSuperClass();
935 t_depth--;
936 }
937 }
938 // Go up the hierarchy until we get to the common parent
939 while (s != t) {
940 s = s->GetSuperClass();
941 t = t->GetSuperClass();
942 }
943 return s;
944 }
945}
946
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800947void RegType::CheckInvariants() const {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800948 if (IsConstant() || IsConstantLo() || IsConstantHi()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800949 CHECK(descriptor_.empty()) << *this;
950 CHECK(klass_ == NULL) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800951 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800952}
953
954UninitializedType::UninitializedType(mirror::Class* klass, std::string& descriptor,
955 uint32_t allocation_pc, uint16_t cache_id)
956 : RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {
957}
958
959void UninitializedType::CheckInvariants() const {
960 CHECK_EQ(allocation_pc_, 0U) << *this;
961}
962
963void UninitialisedThisReferenceType::CheckInvariants() const {
964 UninitializedType::CheckInvariants();
965}
966
967UninitialisedThisReferenceType::UninitialisedThisReferenceType(mirror::Class* klass,
968 std::string& descriptor, uint16_t cache_id) : UninitializedType(klass, descriptor, 0, cache_id) {
969}
970
971void UnresolvedUninitialisedThisRefType::CheckInvariants() const {
972 UninitializedType::CheckInvariants();
973 CHECK(!descriptor_.empty()) << *this;
974 CHECK(klass_ == NULL) << *this;
975}
976
977void UnresolvedUninitializedRefType::CheckInvariants() const {
978 UninitializedType::CheckInvariants();
979 CHECK(!descriptor_.empty()) << *this;
980 CHECK(klass_ == NULL) << *this;
981}
982
983void UnresolvedMergedType::CheckInvariants() const {
984 // Unresolved merged types: merged types should be defined.
985 CHECK(descriptor_.empty()) << *this;
986 CHECK(klass_ == NULL) << *this;
987 CHECK_NE(merged_types_.first, 0U) << *this;
988 CHECK_NE(merged_types_.second, 0U) << *this;
989}
990
991void UnresolvedReferenceType::CheckInvariants() const {
992 CHECK(!descriptor_.empty()) << *this;
993 CHECK(klass_ == NULL) << *this;
994}
995
996void UnresolvedSuperClass::CheckInvariants() const {
997 // Unresolved merged types: merged types should be defined.
998 CHECK(descriptor_.empty()) << *this;
999 CHECK(klass_ == NULL) << *this;
1000 CHECK_NE(unresolved_child_id_, 0U) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001001}
1002
1003std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
Ian Rogers776ac1f2012-04-13 23:36:36 -07001004 os << rhs.Dump();
1005 return os;
1006}
1007
Elliott Hughesa21039c2012-06-21 12:09:25 -07001008} // namespace verifier
1009} // namespace art