blob: 197b1207e818356835dfa08cc876cdf183bb6a13 [file] [log] [blame]
Ian Rogers776ac1f2012-04-13 23:36:36 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "reg_type.h"
18
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080019
20#include "base/casts.h"
Ian Rogers98379392014-02-24 16:53:16 -080021#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070022#include "dex_file-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080023#include "mirror/class.h"
24#include "mirror/class-inl.h"
25#include "mirror/object-inl.h"
Ian Rogers693ff612013-02-01 10:56:12 -080026#include "mirror/object_array-inl.h"
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
Ian Rogersd8f69b02014-09-10 21:43:52 +000084std::string PreciseConstType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080085 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
Ian Rogersd8f69b02014-09-10 21:43:52 +0000101std::string BooleanType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700102 return "Boolean";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800103}
104
Ian Rogersd8f69b02014-09-10 21:43:52 +0000105std::string ConflictType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800106 return "Conflict";
107}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700108
Ian Rogersd8f69b02014-09-10 21:43:52 +0000109std::string ByteType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800110 return "Byte";
111}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700112
Ian Rogersd8f69b02014-09-10 21:43:52 +0000113std::string ShortType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700114 return "Short";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800115}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700116
Ian Rogersd8f69b02014-09-10 21:43:52 +0000117std::string CharType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800118 return "Char";
119}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700120
Ian Rogersd8f69b02014-09-10 21:43:52 +0000121std::string FloatType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700122 return "Float";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800123}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700124
Ian Rogersd8f69b02014-09-10 21:43:52 +0000125std::string LongLoType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700126 return "Long (Low Half)";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800127}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700128
Ian Rogersd8f69b02014-09-10 21:43:52 +0000129std::string LongHiType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700130 return "Long (High Half)";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800131}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700132
Ian Rogersd8f69b02014-09-10 21:43:52 +0000133std::string DoubleLoType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800134 return "Double (Low Half)";
135}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700136
Ian Rogersd8f69b02014-09-10 21:43:52 +0000137std::string DoubleHiType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800138 return "Double (High Half)";
139}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700140
Ian Rogersd8f69b02014-09-10 21:43:52 +0000141std::string IntegerType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800142 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() {
Brian Carlstromdf629502013-07-17 22:39:56 -0700214 CHECK(instance_ != NULL);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800215 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() {
Brian Carlstromdf629502013-07-17 22:39:56 -0700358 if (BooleanType::instance != NULL) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800359 delete instance;
360 instance = NULL;
361 }
362}
363
Ian Rogersd8f69b02014-09-10 21:43:52 +0000364std::string UndefinedType::Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800365 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
Ian Rogersd8f69b02014-09-10 21:43:52 +0000394std::string UnresolvedMergedType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800395 std::stringstream result;
396 std::set<uint16_t> types = GetMergedTypes();
397 result << "UnresolvedMergedReferences(";
Mathieu Chartier02e25112013-08-14 16:14:24 -0700398 auto it = types.begin();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800399 result << reg_type_cache_->GetFromId(*it).Dump();
400 for (++it; it != types.end(); ++it) {
401 result << ", ";
402 result << reg_type_cache_->GetFromId(*it).Dump();
403 }
404 result << ")";
405 return result.str();
406}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700407
Ian Rogersd8f69b02014-09-10 21:43:52 +0000408std::string UnresolvedSuperClass::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800409 std::stringstream result;
410 uint16_t super_type_id = GetUnresolvedSuperClassChildId();
411 result << "UnresolvedSuperClass(" << reg_type_cache_->GetFromId(super_type_id).Dump() << ")";
412 return result.str();
413}
414
Ian Rogersd8f69b02014-09-10 21:43:52 +0000415std::string UnresolvedReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800416 std::stringstream result;
Ian Rogers1ff3c982014-08-12 02:30:58 -0700417 result << "Unresolved Reference" << ": " << PrettyDescriptor(GetDescriptor().c_str());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800418 return result.str();
419}
420
Ian Rogersd8f69b02014-09-10 21:43:52 +0000421std::string UnresolvedUninitializedRefType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800422 std::stringstream result;
Ian Rogers1ff3c982014-08-12 02:30:58 -0700423 result << "Unresolved And Uninitialized Reference" << ": "
424 << PrettyDescriptor(GetDescriptor().c_str())
425 << " Allocation PC: " << GetAllocationPc();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800426 return result.str();
427}
428
Ian Rogersd8f69b02014-09-10 21:43:52 +0000429std::string UnresolvedUninitializedThisRefType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800430 std::stringstream result;
Ian Rogers1ff3c982014-08-12 02:30:58 -0700431 result << "Unresolved And Uninitialized This Reference"
432 << PrettyDescriptor(GetDescriptor().c_str());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800433 return result.str();
434}
435
Ian Rogersd8f69b02014-09-10 21:43:52 +0000436std::string ReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800437 std::stringstream result;
438 result << "Reference" << ": " << PrettyDescriptor(GetClass());
439 return result.str();
440}
441
Ian Rogersd8f69b02014-09-10 21:43:52 +0000442std::string PreciseReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800443 std::stringstream result;
444 result << "Precise Reference" << ": "<< PrettyDescriptor(GetClass());
445 return result.str();
446}
447
Ian Rogersd8f69b02014-09-10 21:43:52 +0000448std::string UninitializedReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800449 std::stringstream result;
450 result << "Uninitialized Reference" << ": " << PrettyDescriptor(GetClass());
451 result << " Allocation PC: " << GetAllocationPc();
452 return result.str();
453}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700454
Ian Rogersd8f69b02014-09-10 21:43:52 +0000455std::string UninitializedThisReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800456 std::stringstream result;
457 result << "Uninitialized This Reference" << ": " << PrettyDescriptor(GetClass());
458 result << "Allocation PC: " << GetAllocationPc();
459 return result.str();
460}
461
Ian Rogersd8f69b02014-09-10 21:43:52 +0000462std::string ImpreciseConstType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800463 std::stringstream result;
464 uint32_t val = ConstantValue();
465 if (val == 0) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800466 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}
Ian Rogersd8f69b02014-09-10 21:43:52 +0000477std::string PreciseConstLoType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800478 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
Ian Rogersd8f69b02014-09-10 21:43:52 +0000491std::string ImpreciseConstLoType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800492 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
Ian Rogersd8f69b02014-09-10 21:43:52 +0000505std::string PreciseConstHiType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800506 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
Ian Rogersd8f69b02014-09-10 21:43:52 +0000518std::string ImpreciseConstHiType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800519 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
Ian Rogersd8f69b02014-09-10 21:43:52 +0000535const RegType& UndefinedType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800536 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
Ian Rogersd8f69b02014-09-10 21:43:52 +0000543const 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();
Ian Rogersd8f69b02014-09-10 21:43:52 +0000591 const RegType& _left(reg_type_cache_->GetFromId(refs.first));
592 RegType& __left(const_cast<RegType&>(_left));
593 UnresolvedMergedType* left = down_cast<UnresolvedMergedType*>(&__left);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800594
Ian Rogersd8f69b02014-09-10 21:43:52 +0000595 RegType& _right(
596 const_cast<RegType&>(reg_type_cache_->GetFromId(refs.second)));
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800597 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) {
Mathieu Chartier02e25112013-08-14 16:14:24 -0700612 for (const auto& type : types) {
613 CHECK(!reg_type_cache_->GetFromId(type).IsUnresolvedMergedReference());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800614 }
Ian Rogers529781d2012-07-23 17:24:29 -0700615 }
Ian Rogers529781d2012-07-23 17:24:29 -0700616 return types;
617}
618
Ian Rogersd8f69b02014-09-10 21:43:52 +0000619const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700620 if (!IsUnresolvedTypes()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800621 mirror::Class* super_klass = GetClass()->GetSuperClass();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700622 if (super_klass != NULL) {
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700623 // A super class of a precise type isn't precise as a precise type indicates the register
624 // holds exactly that type.
Ian Rogers1ff3c982014-08-12 02:30:58 -0700625 std::string temp;
626 return cache->FromClass(super_klass->GetDescriptor(&temp), 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
Ian Rogersd8f69b02014-09-10 21:43:52 +0000641bool RegType::CanAccess(const RegType& other) const {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700642 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 Rogersd8f69b02014-09-10 21:43:52 +0000657bool 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 Rogersd8f69b02014-09-10 21:43:52 +0000668bool RegType::IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800669 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 Rogersd8f69b02014-09-10 21:43:52 +0000681bool RegType::IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800682 return IsReference() && GetClass()->IsObjectClass();
683}
684
Ian Rogersd8f69b02014-09-10 21:43:52 +0000685bool RegType::IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800686 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
687 return descriptor_[0] == '[';
688 } else if (HasClass()) {
689 return GetClass()->IsArrayClass();
690 } else {
691 return false;
692 }
693}
694
Ian Rogersd8f69b02014-09-10 21:43:52 +0000695bool RegType::IsJavaLangObjectArray() const {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800696 if (HasClass()) {
697 mirror::Class* type = GetClass();
698 return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
699 }
700 return false;
701}
702
Ian Rogersd8f69b02014-09-10 21:43:52 +0000703bool RegType::IsInstantiableTypes() const {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800704 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 Rogersd8f69b02014-09-10 21:43:52 +0000711static bool AssignableFrom(const RegType& lhs, const RegType& rhs, bool strict)
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700712 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
713 if (lhs.Equals(rhs)) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700714 return true;
715 } else {
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700716 if (lhs.IsBoolean()) {
717 return rhs.IsBooleanTypes();
718 } else if (lhs.IsByte()) {
719 return rhs.IsByteTypes();
720 } else if (lhs.IsShort()) {
721 return rhs.IsShortTypes();
722 } else if (lhs.IsChar()) {
723 return rhs.IsCharTypes();
724 } else if (lhs.IsInteger()) {
725 return rhs.IsIntegralTypes();
726 } else if (lhs.IsFloat()) {
727 return rhs.IsFloatTypes();
728 } else if (lhs.IsLongLo()) {
729 return rhs.IsLongTypes();
730 } else if (lhs.IsDoubleLo()) {
731 return rhs.IsDoubleTypes();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800732 } else {
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700733 CHECK(lhs.IsReferenceTypes())
734 << "Unexpected register type in IsAssignableFrom: '"
735 << lhs << "' := '" << rhs << "'";
736 if (rhs.IsZero()) {
737 return true; // All reference types can be assigned null.
738 } else if (!rhs.IsReferenceTypes()) {
739 return false; // Expect rhs to be a reference type.
740 } else if (lhs.IsJavaLangObject()) {
741 return true; // All reference types can be assigned to Object.
742 } else if (!strict && !lhs.IsUnresolvedTypes() && lhs.GetClass()->IsInterface()) {
743 // If we're not strict allow assignment to any interface, see comment in ClassJoin.
Ian Rogersfae370a2013-06-05 08:33:27 -0700744 return true;
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700745 } else if (lhs.IsJavaLangObjectArray()) {
746 return rhs.IsObjectArrayTypes(); // All reference arrays may be assigned to Object[]
747 } else if (lhs.HasClass() && rhs.HasClass() &&
748 lhs.GetClass()->IsAssignableFrom(rhs.GetClass())) {
749 // We're assignable from the Class point-of-view.
750 return true;
Ian Rogersfae370a2013-06-05 08:33:27 -0700751 } else {
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700752 // Unresolved types are only assignable for null and equality.
Ian Rogersfae370a2013-06-05 08:33:27 -0700753 return false;
754 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700755 }
756 }
757}
758
Ian Rogersd8f69b02014-09-10 21:43:52 +0000759bool RegType::IsAssignableFrom(const RegType& src) const {
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700760 return AssignableFrom(*this, src, false);
761}
762
Ian Rogersd8f69b02014-09-10 21:43:52 +0000763bool RegType::IsStrictlyAssignableFrom(const RegType& src) const {
Ian Rogers16e3d2c2013-06-07 12:57:00 -0700764 return AssignableFrom(*this, src, true);
765}
766
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800767int32_t ConstantType::ConstantValueLo() const {
768 DCHECK(IsConstantLo());
769 return constant_;
770}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700771
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800772int32_t ConstantType::ConstantValueHi() const {
773 if (IsConstantHi() || IsPreciseConstantHi() || IsImpreciseConstantHi()) {
774 return constant_;
775 } else {
776 DCHECK(false);
777 return 0;
778 }
779}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700780
Ian Rogersd8f69b02014-09-10 21:43:52 +0000781static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
Sebastien Hertzaa0c00c2014-03-14 17:58:54 +0100782 return a.IsConstantTypes() ? b : a;
Ian Rogers776ac1f2012-04-13 23:36:36 -0700783}
784
Ian Rogersd8f69b02014-09-10 21:43:52 +0000785const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700786 DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800787 if (IsConflict()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700788 return *this; // Conflict MERGE * => Conflict
789 } else if (incoming_type.IsConflict()) {
790 return incoming_type; // * MERGE Conflict => Conflict
Ian Rogersad0b3a32012-04-16 14:50:24 -0700791 } else if (IsUndefined() || incoming_type.IsUndefined()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700792 return reg_types->Conflict(); // Unknown MERGE * => Conflict
793 } else if (IsConstant() && incoming_type.IsConstant()) {
794 int32_t val1 = ConstantValue();
795 int32_t val2 = incoming_type.ConstantValue();
796 if (val1 >= 0 && val2 >= 0) {
797 // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
798 if (val1 >= val2) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800799 if (!IsPreciseConstant()) {
800 return *this;
801 } else {
802 return reg_types->FromCat1Const(val1, false);
803 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700804 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800805 if (!incoming_type.IsPreciseConstant()) {
806 return incoming_type;
807 } else {
808 return reg_types->FromCat1Const(val2, false);
809 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700810 }
811 } else if (val1 < 0 && val2 < 0) {
812 // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
813 if (val1 <= val2) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800814 if (!IsPreciseConstant()) {
815 return *this;
816 } else {
817 return reg_types->FromCat1Const(val1, false);
818 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700819 } else {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800820 if (!incoming_type.IsPreciseConstant()) {
821 return incoming_type;
822 } else {
823 return reg_types->FromCat1Const(val2, false);
824 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700825 }
826 } else {
827 // Values are +ve and -ve, choose smallest signed type in which they both fit
828 if (IsConstantByte()) {
829 if (incoming_type.IsConstantByte()) {
830 return reg_types->ByteConstant();
831 } else if (incoming_type.IsConstantShort()) {
832 return reg_types->ShortConstant();
833 } else {
834 return reg_types->IntConstant();
835 }
836 } else if (IsConstantShort()) {
837 if (incoming_type.IsConstantShort()) {
838 return reg_types->ShortConstant();
839 } else {
840 return reg_types->IntConstant();
841 }
842 } else {
843 return reg_types->IntConstant();
844 }
845 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800846 } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
847 int32_t val1 = ConstantValueLo();
848 int32_t val2 = incoming_type.ConstantValueLo();
849 return reg_types->FromCat2ConstLo(val1 | val2, false);
850 } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
851 int32_t val1 = ConstantValueHi();
852 int32_t val2 = incoming_type.ConstantValueHi();
853 return reg_types->FromCat2ConstHi(val1 | val2, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700854 } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
855 if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
856 return reg_types->Boolean(); // boolean MERGE boolean => boolean
857 }
858 if (IsByteTypes() && incoming_type.IsByteTypes()) {
859 return reg_types->Byte(); // byte MERGE byte => byte
860 }
861 if (IsShortTypes() && incoming_type.IsShortTypes()) {
862 return reg_types->Short(); // short MERGE short => short
863 }
864 if (IsCharTypes() && incoming_type.IsCharTypes()) {
865 return reg_types->Char(); // char MERGE char => char
866 }
867 return reg_types->Integer(); // int MERGE * => int
868 } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
869 (IsLongTypes() && incoming_type.IsLongTypes()) ||
870 (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
871 (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
872 (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
873 // check constant case was handled prior to entry
874 DCHECK(!IsConstant() || !incoming_type.IsConstant());
875 // float/long/double MERGE float/long/double_constant => float/long/double
876 return SelectNonConstant(*this, incoming_type);
877 } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
878 if (IsZero() || incoming_type.IsZero()) {
879 return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref
880 } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
Ian Rogersb4903572012-10-11 11:52:56 -0700881 return reg_types->JavaLangObject(false); // Object MERGE ref => Object
Ian Rogers529781d2012-07-23 17:24:29 -0700882 } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
883 // We know how to merge an unresolved type with itself, 0 or Object. In this case we
884 // have two sub-classes and don't know how to merge. Create a new string-based unresolved
885 // type that reflects our lack of knowledge and that allows the rest of the unresolved
886 // mechanics to continue.
887 return reg_types->FromUnresolvedMerge(*this, incoming_type);
888 } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
889 // Something that is uninitialized hasn't had its constructor called. Mark any merge
890 // of this type with something that is initialized as conflicting. The cases of a merge
891 // with itself, 0 or Object are handled above.
Ian Rogers776ac1f2012-04-13 23:36:36 -0700892 return reg_types->Conflict();
893 } else { // Two reference types, compute Join
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800894 mirror::Class* c1 = GetClass();
895 mirror::Class* c2 = incoming_type.GetClass();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700896 DCHECK(c1 != NULL && !c1->IsPrimitive());
897 DCHECK(c2 != NULL && !c2->IsPrimitive());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800898 mirror::Class* join_class = ClassJoin(c1, c2);
Ian Rogersb4903572012-10-11 11:52:56 -0700899 if (c1 == join_class && !IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700900 return *this;
Ian Rogersb4903572012-10-11 11:52:56 -0700901 } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700902 return incoming_type;
903 } else {
Ian Rogers1ff3c982014-08-12 02:30:58 -0700904 std::string temp;
905 return reg_types->FromClass(join_class->GetDescriptor(&temp), join_class, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700906 }
907 }
908 } else {
909 return reg_types->Conflict(); // Unexpected types => Conflict
910 }
911}
912
Ian Rogersad0b3a32012-04-16 14:50:24 -0700913// See comment in reg_type.h
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800914mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700915 DCHECK(!s->IsPrimitive()) << PrettyClass(s);
916 DCHECK(!t->IsPrimitive()) << PrettyClass(t);
917 if (s == t) {
918 return s;
919 } else if (s->IsAssignableFrom(t)) {
920 return s;
921 } else if (t->IsAssignableFrom(s)) {
922 return t;
923 } else if (s->IsArrayClass() && t->IsArrayClass()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800924 mirror::Class* s_ct = s->GetComponentType();
925 mirror::Class* t_ct = t->GetComponentType();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700926 if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
927 // Given the types aren't the same, if either array is of primitive types then the only
928 // common parent is java.lang.Object
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800929 mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object
Ian Rogersad0b3a32012-04-16 14:50:24 -0700930 DCHECK(result->IsObjectClass());
931 return result;
932 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800933 mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700934 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Mathieu Chartierb74cd292014-05-29 14:31:33 -0700935 mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), &common_elem);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700936 DCHECK(array_class != NULL);
937 return array_class;
938 } else {
939 size_t s_depth = s->Depth();
940 size_t t_depth = t->Depth();
941 // Get s and t to the same depth in the hierarchy
942 if (s_depth > t_depth) {
943 while (s_depth > t_depth) {
944 s = s->GetSuperClass();
945 s_depth--;
946 }
947 } else {
948 while (t_depth > s_depth) {
949 t = t->GetSuperClass();
950 t_depth--;
951 }
952 }
953 // Go up the hierarchy until we get to the common parent
954 while (s != t) {
955 s = s->GetSuperClass();
956 t = t->GetSuperClass();
957 }
958 return s;
959 }
960}
961
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800962void RegType::CheckInvariants() const {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800963 if (IsConstant() || IsConstantLo() || IsConstantHi()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800964 CHECK(descriptor_.empty()) << *this;
Ian Rogersd8f69b02014-09-10 21:43:52 +0000965 CHECK(klass_ == NULL) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800966 }
Ian Rogersd8f69b02014-09-10 21:43:52 +0000967 if (klass_ != NULL) {
Ian Rogers637c65b2013-05-31 11:46:00 -0700968 CHECK(!descriptor_.empty()) << *this;
969 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800970}
971
Mathieu Chartier83c8ee02014-01-28 14:50:23 -0800972void RegType::VisitRoots(RootCallback* callback, void* arg) {
Ian Rogersd8f69b02014-09-10 21:43:52 +0000973 if (klass_ != nullptr) {
974 callback(reinterpret_cast<mirror::Object**>(&klass_), arg, 0, kRootUnknown);
Mathieu Chartierc528dba2013-11-26 12:00:11 -0800975 }
976}
977
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700978void UninitializedThisReferenceType::CheckInvariants() const {
Ian Rogers637c65b2013-05-31 11:46:00 -0700979 CHECK_EQ(GetAllocationPc(), 0U) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800980}
981
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700982void UnresolvedUninitializedThisRefType::CheckInvariants() const {
Ian Rogers637c65b2013-05-31 11:46:00 -0700983 CHECK_EQ(GetAllocationPc(), 0U) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800984 CHECK(!descriptor_.empty()) << *this;
Ian Rogersd8f69b02014-09-10 21:43:52 +0000985 CHECK(klass_ == NULL) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800986}
987
988void UnresolvedUninitializedRefType::CheckInvariants() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800989 CHECK(!descriptor_.empty()) << *this;
Ian Rogersd8f69b02014-09-10 21:43:52 +0000990 CHECK(klass_ == NULL) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800991}
992
993void UnresolvedMergedType::CheckInvariants() const {
994 // Unresolved merged types: merged types should be defined.
995 CHECK(descriptor_.empty()) << *this;
Ian Rogersd8f69b02014-09-10 21:43:52 +0000996 CHECK(klass_ == NULL) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800997 CHECK_NE(merged_types_.first, 0U) << *this;
998 CHECK_NE(merged_types_.second, 0U) << *this;
999}
1000
1001void UnresolvedReferenceType::CheckInvariants() const {
1002 CHECK(!descriptor_.empty()) << *this;
Ian Rogersd8f69b02014-09-10 21:43:52 +00001003 CHECK(klass_ == NULL) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -08001004}
1005
1006void UnresolvedSuperClass::CheckInvariants() const {
1007 // Unresolved merged types: merged types should be defined.
1008 CHECK(descriptor_.empty()) << *this;
Ian Rogersd8f69b02014-09-10 21:43:52 +00001009 CHECK(klass_ == NULL) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -08001010 CHECK_NE(unresolved_child_id_, 0U) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001011}
1012
1013std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
Ian Rogersd8f69b02014-09-10 21:43:52 +00001014 os << rhs.Dump();
Ian Rogers776ac1f2012-04-13 23:36:36 -07001015 return os;
1016}
1017
Elliott Hughesa21039c2012-06-21 12:09:25 -07001018} // namespace verifier
1019} // namespace art