blob: c8aa4fd2c15b9819961c327a4adcb7945d637c96 [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
Ian Rogers7b078e82014-09-10 14:44:24 -070017#include "reg_type-inl.h"
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080018
19#include "base/casts.h"
Ian Rogers98379392014-02-24 16:53:16 -080020#include "class_linker-inl.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"
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080026#include "reg_type_cache-inl.h"
Ian Rogers637c65b2013-05-31 11:46:00 -070027#include "scoped_thread_state_change.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
Ian Rogers7b078e82014-09-10 14:44:24 -070035const UndefinedType* UndefinedType::instance_ = nullptr;
36const ConflictType* ConflictType::instance_ = nullptr;
37const BooleanType* BooleanType::instance_ = nullptr;
38const ByteType* ByteType::instance_ = nullptr;
39const ShortType* ShortType::instance_ = nullptr;
40const CharType* CharType::instance_ = nullptr;
41const FloatType* FloatType::instance_ = nullptr;
42const LongLoType* LongLoType::instance_ = nullptr;
43const LongHiType* LongHiType::instance_ = nullptr;
44const DoubleLoType* DoubleLoType::instance_ = nullptr;
45const DoubleHiType* DoubleHiType::instance_ = nullptr;
46const IntegerType* IntegerType::instance_ = nullptr;
Ian Rogers637c65b2013-05-31 11:46:00 -070047
48PrimitiveType::PrimitiveType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
49 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
50 : RegType(klass, descriptor, cache_id) {
Ian Rogers7b078e82014-09-10 14:44:24 -070051 CHECK(klass != nullptr);
Ian Rogers637c65b2013-05-31 11:46:00 -070052 CHECK(!descriptor.empty());
53}
54
55Cat1Type::Cat1Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
56 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
57 : PrimitiveType(klass, descriptor, cache_id) {
58}
59
60Cat2Type::Cat2Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
61 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
62 : PrimitiveType(klass, descriptor, cache_id) {
63}
64
Ian Rogersd8f69b02014-09-10 21:43:52 +000065std::string PreciseConstType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080066 std::stringstream result;
67 uint32_t val = ConstantValue();
68 if (val == 0) {
69 CHECK(IsPreciseConstant());
70 result << "Zero/null";
Ian Rogers776ac1f2012-04-13 23:36:36 -070071 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080072 result << "Precise ";
73 if (IsConstantShort()) {
74 result << StringPrintf("Constant: %d", val);
75 } else {
76 result << StringPrintf("Constant: 0x%x", val);
Ian Rogers776ac1f2012-04-13 23:36:36 -070077 }
78 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080079 return result.str();
80}
81
Ian Rogersd8f69b02014-09-10 21:43:52 +000082std::string BooleanType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -070083 return "Boolean";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080084}
85
Ian Rogersd8f69b02014-09-10 21:43:52 +000086std::string ConflictType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080087 return "Conflict";
88}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -070089
Ian Rogersd8f69b02014-09-10 21:43:52 +000090std::string ByteType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080091 return "Byte";
92}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -070093
Ian Rogersd8f69b02014-09-10 21:43:52 +000094std::string ShortType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -070095 return "Short";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080096}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -070097
Ian Rogersd8f69b02014-09-10 21:43:52 +000098std::string CharType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080099 return "Char";
100}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700101
Ian Rogersd8f69b02014-09-10 21:43:52 +0000102std::string FloatType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700103 return "Float";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800104}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700105
Ian Rogersd8f69b02014-09-10 21:43:52 +0000106std::string LongLoType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700107 return "Long (Low Half)";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800108}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700109
Ian Rogersd8f69b02014-09-10 21:43:52 +0000110std::string LongHiType::Dump() const {
Ian Rogers41c65c12013-09-05 16:57:17 -0700111 return "Long (High Half)";
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800112}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700113
Ian Rogersd8f69b02014-09-10 21:43:52 +0000114std::string DoubleLoType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800115 return "Double (Low Half)";
116}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700117
Ian Rogersd8f69b02014-09-10 21:43:52 +0000118std::string DoubleHiType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800119 return "Double (High Half)";
120}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700121
Ian Rogersd8f69b02014-09-10 21:43:52 +0000122std::string IntegerType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800123 return "Integer";
124}
125
Ian Rogers7b078e82014-09-10 14:44:24 -0700126const DoubleHiType* DoubleHiType::CreateInstance(mirror::Class* klass,
127 const std::string& descriptor,
128 uint16_t cache_id) {
129 CHECK(instance_ == nullptr);
130 instance_ = new DoubleHiType(klass, descriptor, cache_id);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800131 return instance_;
132}
133
134void DoubleHiType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700135 if (instance_ != nullptr) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800136 delete instance_;
Ian Rogers7b078e82014-09-10 14:44:24 -0700137 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800138 }
139}
140
Ian Rogers7b078e82014-09-10 14:44:24 -0700141const DoubleLoType* DoubleLoType::CreateInstance(mirror::Class* klass,
142 const std::string& descriptor,
143 uint16_t cache_id) {
144 CHECK(instance_ == nullptr);
145 instance_ = new DoubleLoType(klass, descriptor, cache_id);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800146 return instance_;
147}
148
149void DoubleLoType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700150 if (instance_ != nullptr) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800151 delete instance_;
Ian Rogers7b078e82014-09-10 14:44:24 -0700152 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800153 }
154}
155
Ian Rogers7b078e82014-09-10 14:44:24 -0700156const LongLoType* LongLoType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
157 uint16_t cache_id) {
158 CHECK(instance_ == nullptr);
159 instance_ = new LongLoType(klass, descriptor, cache_id);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800160 return instance_;
161}
162
Ian Rogers7b078e82014-09-10 14:44:24 -0700163const LongHiType* LongHiType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
164 uint16_t cache_id) {
165 CHECK(instance_ == nullptr);
166 instance_ = new LongHiType(klass, descriptor, cache_id);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800167 return instance_;
168}
169
170void LongHiType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700171 if (instance_ != nullptr) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800172 delete instance_;
Ian Rogers7b078e82014-09-10 14:44:24 -0700173 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800174 }
175}
176
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800177void LongLoType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700178 if (instance_ != nullptr) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800179 delete instance_;
Ian Rogers7b078e82014-09-10 14:44:24 -0700180 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800181 }
182}
183
Ian Rogers7b078e82014-09-10 14:44:24 -0700184const FloatType* FloatType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
185 uint16_t cache_id) {
186 CHECK(instance_ == nullptr);
187 instance_ = new FloatType(klass, descriptor, cache_id);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800188 return instance_;
189}
190
191void FloatType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700192 if (instance_ != nullptr) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800193 delete instance_;
Ian Rogers7b078e82014-09-10 14:44:24 -0700194 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800195 }
196}
197
Ian Rogers7b078e82014-09-10 14:44:24 -0700198const CharType* CharType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
199 uint16_t cache_id) {
200 CHECK(instance_ == nullptr);
201 instance_ = new CharType(klass, descriptor, cache_id);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800202 return instance_;
203}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700204
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800205void CharType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700206 if (instance_ != nullptr) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800207 delete instance_;
Ian Rogers7b078e82014-09-10 14:44:24 -0700208 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800209 }
210}
211
Ian Rogers7b078e82014-09-10 14:44:24 -0700212const ShortType* ShortType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
213 uint16_t cache_id) {
214 CHECK(instance_ == nullptr);
215 instance_ = new ShortType(klass, descriptor, cache_id);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800216 return instance_;
217}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700218
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800219void ShortType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700220 if (instance_ != nullptr) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800221 delete instance_;
Ian Rogers7b078e82014-09-10 14:44:24 -0700222 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800223 }
224}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700225
Ian Rogers7b078e82014-09-10 14:44:24 -0700226const ByteType* ByteType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
227 uint16_t cache_id) {
228 CHECK(instance_ == nullptr);
229 instance_ = new ByteType(klass, descriptor, cache_id);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800230 return instance_;
231}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700232
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800233void ByteType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700234 if (instance_ != nullptr) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800235 delete instance_;
Ian Rogers7b078e82014-09-10 14:44:24 -0700236 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800237 }
238}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700239
Ian Rogers7b078e82014-09-10 14:44:24 -0700240const IntegerType* IntegerType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
241 uint16_t cache_id) {
242 CHECK(instance_ == nullptr);
243 instance_ = new IntegerType(klass, descriptor, cache_id);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800244 return instance_;
245}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700246
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800247void IntegerType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700248 if (instance_ != nullptr) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800249 delete instance_;
Ian Rogers7b078e82014-09-10 14:44:24 -0700250 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800251 }
252}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700253
Ian Rogers7b078e82014-09-10 14:44:24 -0700254const ConflictType* ConflictType::CreateInstance(mirror::Class* klass,
255 const std::string& descriptor,
256 uint16_t cache_id) {
257 CHECK(instance_ == nullptr);
258 instance_ = new ConflictType(klass, descriptor, cache_id);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800259 return instance_;
260}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700261
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800262void ConflictType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700263 if (instance_ != nullptr) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800264 delete instance_;
Ian Rogers7b078e82014-09-10 14:44:24 -0700265 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800266 }
267}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700268
Ian Rogers7b078e82014-09-10 14:44:24 -0700269const BooleanType* BooleanType::CreateInstance(mirror::Class* klass, const std::string& descriptor,
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800270 uint16_t cache_id) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700271 CHECK(BooleanType::instance_ == nullptr);
272 instance_ = new BooleanType(klass, descriptor, cache_id);
273 return BooleanType::instance_;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800274}
275
276void BooleanType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700277 if (BooleanType::instance_ != nullptr) {
278 delete instance_;
279 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800280 }
281}
282
Ian Rogersd8f69b02014-09-10 21:43:52 +0000283std::string UndefinedType::Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800284 return "Undefined";
285}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700286
Ian Rogers7b078e82014-09-10 14:44:24 -0700287const UndefinedType* UndefinedType::CreateInstance(mirror::Class* klass,
288 const std::string& descriptor,
289 uint16_t cache_id) {
290 CHECK(instance_ == nullptr);
291 instance_ = new UndefinedType(klass, descriptor, cache_id);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800292 return instance_;
293}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700294
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800295void UndefinedType::Destroy() {
Ian Rogers7b078e82014-09-10 14:44:24 -0700296 if (instance_ != nullptr) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800297 delete instance_;
Ian Rogers7b078e82014-09-10 14:44:24 -0700298 instance_ = nullptr;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800299 }
300}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700301
Ian Rogers637c65b2013-05-31 11:46:00 -0700302PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, const std::string& descriptor,
303 uint16_t cache_id)
304 : RegType(klass, descriptor, cache_id) {
305 DCHECK(klass->IsInstantiable());
306}
307
Ian Rogersd8f69b02014-09-10 21:43:52 +0000308std::string UnresolvedMergedType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800309 std::stringstream result;
310 std::set<uint16_t> types = GetMergedTypes();
311 result << "UnresolvedMergedReferences(";
Mathieu Chartier02e25112013-08-14 16:14:24 -0700312 auto it = types.begin();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800313 result << reg_type_cache_->GetFromId(*it).Dump();
314 for (++it; it != types.end(); ++it) {
315 result << ", ";
316 result << reg_type_cache_->GetFromId(*it).Dump();
317 }
318 result << ")";
319 return result.str();
320}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700321
Ian Rogersd8f69b02014-09-10 21:43:52 +0000322std::string UnresolvedSuperClass::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800323 std::stringstream result;
324 uint16_t super_type_id = GetUnresolvedSuperClassChildId();
325 result << "UnresolvedSuperClass(" << reg_type_cache_->GetFromId(super_type_id).Dump() << ")";
326 return result.str();
327}
328
Ian Rogersd8f69b02014-09-10 21:43:52 +0000329std::string UnresolvedReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800330 std::stringstream result;
Ian Rogers1ff3c982014-08-12 02:30:58 -0700331 result << "Unresolved Reference" << ": " << PrettyDescriptor(GetDescriptor().c_str());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800332 return result.str();
333}
334
Ian Rogersd8f69b02014-09-10 21:43:52 +0000335std::string UnresolvedUninitializedRefType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800336 std::stringstream result;
Ian Rogers1ff3c982014-08-12 02:30:58 -0700337 result << "Unresolved And Uninitialized Reference" << ": "
338 << PrettyDescriptor(GetDescriptor().c_str())
339 << " Allocation PC: " << GetAllocationPc();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800340 return result.str();
341}
342
Ian Rogersd8f69b02014-09-10 21:43:52 +0000343std::string UnresolvedUninitializedThisRefType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800344 std::stringstream result;
Ian Rogers1ff3c982014-08-12 02:30:58 -0700345 result << "Unresolved And Uninitialized This Reference"
346 << PrettyDescriptor(GetDescriptor().c_str());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800347 return result.str();
348}
349
Ian Rogersd8f69b02014-09-10 21:43:52 +0000350std::string ReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800351 std::stringstream result;
352 result << "Reference" << ": " << PrettyDescriptor(GetClass());
353 return result.str();
354}
355
Ian Rogersd8f69b02014-09-10 21:43:52 +0000356std::string PreciseReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800357 std::stringstream result;
358 result << "Precise Reference" << ": "<< PrettyDescriptor(GetClass());
359 return result.str();
360}
361
Ian Rogersd8f69b02014-09-10 21:43:52 +0000362std::string UninitializedReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800363 std::stringstream result;
364 result << "Uninitialized Reference" << ": " << PrettyDescriptor(GetClass());
365 result << " Allocation PC: " << GetAllocationPc();
366 return result.str();
367}
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700368
Ian Rogersd8f69b02014-09-10 21:43:52 +0000369std::string UninitializedThisReferenceType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800370 std::stringstream result;
371 result << "Uninitialized This Reference" << ": " << PrettyDescriptor(GetClass());
372 result << "Allocation PC: " << GetAllocationPc();
373 return result.str();
374}
375
Ian Rogersd8f69b02014-09-10 21:43:52 +0000376std::string ImpreciseConstType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800377 std::stringstream result;
378 uint32_t val = ConstantValue();
379 if (val == 0) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800380 result << "Zero/null";
381 } else {
382 result << "Imprecise ";
383 if (IsConstantShort()) {
384 result << StringPrintf("Constant: %d", val);
385 } else {
386 result << StringPrintf("Constant: 0x%x", val);
387 }
388 }
389 return result.str();
390}
Ian Rogersd8f69b02014-09-10 21:43:52 +0000391std::string PreciseConstLoType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800392 std::stringstream result;
393
394 int32_t val = ConstantValueLo();
395 result << "Precise ";
396 if (val >= std::numeric_limits<jshort>::min() &&
397 val <= std::numeric_limits<jshort>::max()) {
398 result << StringPrintf("Low-half Constant: %d", val);
399 } else {
400 result << StringPrintf("Low-half Constant: 0x%x", val);
401 }
402 return result.str();
403}
404
Ian Rogersd8f69b02014-09-10 21:43:52 +0000405std::string ImpreciseConstLoType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800406 std::stringstream result;
407
408 int32_t val = ConstantValueLo();
409 result << "Imprecise ";
410 if (val >= std::numeric_limits<jshort>::min() &&
411 val <= std::numeric_limits<jshort>::max()) {
412 result << StringPrintf("Low-half Constant: %d", val);
413 } else {
414 result << StringPrintf("Low-half Constant: 0x%x", val);
415 }
416 return result.str();
417}
418
Ian Rogersd8f69b02014-09-10 21:43:52 +0000419std::string PreciseConstHiType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800420 std::stringstream result;
421 int32_t val = ConstantValueHi();
422 result << "Precise ";
423 if (val >= std::numeric_limits<jshort>::min() &&
424 val <= std::numeric_limits<jshort>::max()) {
425 result << StringPrintf("High-half Constant: %d", val);
426 } else {
427 result << StringPrintf("High-half Constant: 0x%x", val);
428 }
429 return result.str();
430}
431
Ian Rogersd8f69b02014-09-10 21:43:52 +0000432std::string ImpreciseConstHiType::Dump() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800433 std::stringstream result;
434 int32_t val = ConstantValueHi();
435 result << "Imprecise ";
436 if (val >= std::numeric_limits<jshort>::min() &&
437 val <= std::numeric_limits<jshort>::max()) {
438 result << StringPrintf("High-half Constant: %d", val);
439 } else {
440 result << StringPrintf("High-half Constant: 0x%x", val);
441 }
442 return result.str();
443}
444
Ian Rogersd8f69b02014-09-10 21:43:52 +0000445const RegType& RegType::HighHalf(RegTypeCache* cache) const {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800446 DCHECK(IsLowHalf());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800447 if (IsLongLo()) {
448 return cache->LongHi();
449 } else if (IsDoubleLo()) {
450 return cache->DoubleHi();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700451 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800452 DCHECK(IsImpreciseConstantLo());
Ian Rogers7b078e82014-09-10 14:44:24 -0700453 const ConstantType* const_val = down_cast<const ConstantType*>(this);
454 return cache->FromCat2ConstHi(const_val->ConstantValue(), false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700455 }
456}
457
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800458Primitive::Type RegType::GetPrimitiveType() const {
459 if (IsNonZeroReferenceTypes()) {
460 return Primitive::kPrimNot;
461 } else if (IsBooleanTypes()) {
462 return Primitive::kPrimBoolean;
463 } else if (IsByteTypes()) {
464 return Primitive::kPrimByte;
465 } else if (IsShortTypes()) {
466 return Primitive::kPrimShort;
467 } else if (IsCharTypes()) {
468 return Primitive::kPrimChar;
469 } else if (IsFloat()) {
470 return Primitive::kPrimFloat;
471 } else if (IsIntegralTypes()) {
472 return Primitive::kPrimInt;
473 } else if (IsDoubleLo()) {
474 return Primitive::kPrimDouble;
475 } else {
476 DCHECK(IsLongTypes());
477 return Primitive::kPrimLong;
478 }
479}
480
Ian Rogers637c65b2013-05-31 11:46:00 -0700481bool UninitializedType::IsUninitializedTypes() const {
482 return true;
483}
484
485bool UninitializedType::IsNonZeroReferenceTypes() const {
486 return true;
487}
488
489bool UnresolvedType::IsNonZeroReferenceTypes() const {
490 return true;
491}
Ian Rogers7b078e82014-09-10 14:44:24 -0700492
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800493std::set<uint16_t> UnresolvedMergedType::GetMergedTypes() const {
Ian Rogers529781d2012-07-23 17:24:29 -0700494 std::pair<uint16_t, uint16_t> refs = GetTopMergedTypes();
Ian Rogers7b078e82014-09-10 14:44:24 -0700495 const RegType& left = reg_type_cache_->GetFromId(refs.first);
496 const RegType& right = reg_type_cache_->GetFromId(refs.second);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800497
Ian Rogers529781d2012-07-23 17:24:29 -0700498 std::set<uint16_t> types;
Ian Rogers7b078e82014-09-10 14:44:24 -0700499 if (left.IsUnresolvedMergedReference()) {
500 types = down_cast<const UnresolvedMergedType*>(&left)->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700501 } else {
502 types.insert(refs.first);
503 }
Ian Rogers7b078e82014-09-10 14:44:24 -0700504 if (right.IsUnresolvedMergedReference()) {
505 std::set<uint16_t> right_types =
506 down_cast<const UnresolvedMergedType*>(&right)->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700507 types.insert(right_types.begin(), right_types.end());
508 } else {
509 types.insert(refs.second);
510 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800511 if (kIsDebugBuild) {
Mathieu Chartier02e25112013-08-14 16:14:24 -0700512 for (const auto& type : types) {
513 CHECK(!reg_type_cache_->GetFromId(type).IsUnresolvedMergedReference());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800514 }
Ian Rogers529781d2012-07-23 17:24:29 -0700515 }
Ian Rogers529781d2012-07-23 17:24:29 -0700516 return types;
517}
518
Ian Rogersd8f69b02014-09-10 21:43:52 +0000519const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700520 if (!IsUnresolvedTypes()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800521 mirror::Class* super_klass = GetClass()->GetSuperClass();
Ian Rogers7b078e82014-09-10 14:44:24 -0700522 if (super_klass != nullptr) {
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700523 // A super class of a precise type isn't precise as a precise type indicates the register
524 // holds exactly that type.
Ian Rogers1ff3c982014-08-12 02:30:58 -0700525 std::string temp;
526 return cache->FromClass(super_klass->GetDescriptor(&temp), super_klass, false);
Ian Rogers0d604842012-04-16 14:50:24 -0700527 } else {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700528 return cache->Zero();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700529 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700530 } else {
Ian Rogers529781d2012-07-23 17:24:29 -0700531 if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
Elliott Hughes80537bb2013-01-04 16:37:26 -0800532 GetDescriptor()[0] == '[') {
Ian Rogers529781d2012-07-23 17:24:29 -0700533 // Super class of all arrays is Object.
Ian Rogersb4903572012-10-11 11:52:56 -0700534 return cache->JavaLangObject(true);
Ian Rogers529781d2012-07-23 17:24:29 -0700535 } else {
536 return cache->FromUnresolvedSuperClass(*this);
537 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700538 }
539}
540
Ian Rogersd8f69b02014-09-10 21:43:52 +0000541bool RegType::IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800542 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
543 // Primitive arrays will always resolve
544 DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
545 return descriptor_[0] == '[';
546 } else if (HasClass()) {
547 mirror::Class* type = GetClass();
548 return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
549 } else {
550 return false;
551 }
552}
553
Ian Rogersd8f69b02014-09-10 21:43:52 +0000554bool RegType::IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800555 return IsReference() && GetClass()->IsObjectClass();
556}
557
Ian Rogersd8f69b02014-09-10 21:43:52 +0000558bool RegType::IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800559 if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
560 return descriptor_[0] == '[';
561 } else if (HasClass()) {
562 return GetClass()->IsArrayClass();
563 } else {
564 return false;
565 }
566}
567
Ian Rogersd8f69b02014-09-10 21:43:52 +0000568bool RegType::IsJavaLangObjectArray() const {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800569 if (HasClass()) {
570 mirror::Class* type = GetClass();
571 return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
572 }
573 return false;
574}
575
Ian Rogersd8f69b02014-09-10 21:43:52 +0000576bool RegType::IsInstantiableTypes() const {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800577 return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
578}
579
Ian Rogersd8f69b02014-09-10 21:43:52 +0000580static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
Sebastien Hertzaa0c00c2014-03-14 17:58:54 +0100581 return a.IsConstantTypes() ? b : a;
Ian Rogers776ac1f2012-04-13 23:36:36 -0700582}
583
Ian Rogersd8f69b02014-09-10 21:43:52 +0000584const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700585 DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller
Ian Rogers7b078e82014-09-10 14:44:24 -0700586 // Perform pointer equality tests for conflict to avoid virtual method dispatch.
587 const ConflictType& conflict = reg_types->Conflict();
588 if (this == &conflict) {
589 DCHECK(IsConflict());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700590 return *this; // Conflict MERGE * => Conflict
Ian Rogers7b078e82014-09-10 14:44:24 -0700591 } else if (&incoming_type == &conflict) {
592 DCHECK(incoming_type.IsConflict());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700593 return incoming_type; // * MERGE Conflict => Conflict
Ian Rogersad0b3a32012-04-16 14:50:24 -0700594 } else if (IsUndefined() || incoming_type.IsUndefined()) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700595 return conflict; // Unknown MERGE * => Conflict
Ian Rogers776ac1f2012-04-13 23:36:36 -0700596 } else if (IsConstant() && incoming_type.IsConstant()) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700597 const ConstantType& type1 = *down_cast<const ConstantType*>(this);
598 const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
599 int32_t val1 = type1.ConstantValue();
600 int32_t val2 = type2.ConstantValue();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700601 if (val1 >= 0 && val2 >= 0) {
602 // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
603 if (val1 >= val2) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700604 if (!type1.IsPreciseConstant()) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800605 return *this;
606 } else {
607 return reg_types->FromCat1Const(val1, false);
608 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700609 } else {
Ian Rogers7b078e82014-09-10 14:44:24 -0700610 if (!type2.IsPreciseConstant()) {
611 return type2;
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800612 } else {
613 return reg_types->FromCat1Const(val2, false);
614 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700615 }
616 } else if (val1 < 0 && val2 < 0) {
617 // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
618 if (val1 <= val2) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700619 if (!type1.IsPreciseConstant()) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800620 return *this;
621 } else {
622 return reg_types->FromCat1Const(val1, false);
623 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700624 } else {
Ian Rogers7b078e82014-09-10 14:44:24 -0700625 if (!type2.IsPreciseConstant()) {
626 return type2;
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800627 } else {
628 return reg_types->FromCat1Const(val2, false);
629 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700630 }
631 } else {
632 // Values are +ve and -ve, choose smallest signed type in which they both fit
Ian Rogers7b078e82014-09-10 14:44:24 -0700633 if (type1.IsConstantByte()) {
634 if (type2.IsConstantByte()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700635 return reg_types->ByteConstant();
Ian Rogers7b078e82014-09-10 14:44:24 -0700636 } else if (type2.IsConstantShort()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700637 return reg_types->ShortConstant();
638 } else {
639 return reg_types->IntConstant();
640 }
Ian Rogers7b078e82014-09-10 14:44:24 -0700641 } else if (type1.IsConstantShort()) {
642 if (type2.IsConstantShort()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700643 return reg_types->ShortConstant();
644 } else {
645 return reg_types->IntConstant();
646 }
647 } else {
648 return reg_types->IntConstant();
649 }
650 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800651 } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700652 const ConstantType& type1 = *down_cast<const ConstantType*>(this);
653 const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
654 int32_t val1 = type1.ConstantValueLo();
655 int32_t val2 = type2.ConstantValueLo();
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800656 return reg_types->FromCat2ConstLo(val1 | val2, false);
657 } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700658 const ConstantType& type1 = *down_cast<const ConstantType*>(this);
659 const ConstantType& type2 = *down_cast<const ConstantType*>(&incoming_type);
660 int32_t val1 = type1.ConstantValueHi();
661 int32_t val2 = type2.ConstantValueHi();
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800662 return reg_types->FromCat2ConstHi(val1 | val2, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700663 } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
664 if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
665 return reg_types->Boolean(); // boolean MERGE boolean => boolean
666 }
667 if (IsByteTypes() && incoming_type.IsByteTypes()) {
668 return reg_types->Byte(); // byte MERGE byte => byte
669 }
670 if (IsShortTypes() && incoming_type.IsShortTypes()) {
671 return reg_types->Short(); // short MERGE short => short
672 }
673 if (IsCharTypes() && incoming_type.IsCharTypes()) {
674 return reg_types->Char(); // char MERGE char => char
675 }
676 return reg_types->Integer(); // int MERGE * => int
677 } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
678 (IsLongTypes() && incoming_type.IsLongTypes()) ||
679 (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
680 (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
681 (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
682 // check constant case was handled prior to entry
683 DCHECK(!IsConstant() || !incoming_type.IsConstant());
684 // float/long/double MERGE float/long/double_constant => float/long/double
685 return SelectNonConstant(*this, incoming_type);
686 } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
687 if (IsZero() || incoming_type.IsZero()) {
688 return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref
689 } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
Ian Rogersb4903572012-10-11 11:52:56 -0700690 return reg_types->JavaLangObject(false); // Object MERGE ref => Object
Ian Rogers529781d2012-07-23 17:24:29 -0700691 } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
692 // We know how to merge an unresolved type with itself, 0 or Object. In this case we
693 // have two sub-classes and don't know how to merge. Create a new string-based unresolved
694 // type that reflects our lack of knowledge and that allows the rest of the unresolved
695 // mechanics to continue.
696 return reg_types->FromUnresolvedMerge(*this, incoming_type);
697 } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) {
698 // Something that is uninitialized hasn't had its constructor called. Mark any merge
699 // of this type with something that is initialized as conflicting. The cases of a merge
700 // with itself, 0 or Object are handled above.
Ian Rogers7b078e82014-09-10 14:44:24 -0700701 return conflict;
Ian Rogers776ac1f2012-04-13 23:36:36 -0700702 } else { // Two reference types, compute Join
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800703 mirror::Class* c1 = GetClass();
704 mirror::Class* c2 = incoming_type.GetClass();
Ian Rogers7b078e82014-09-10 14:44:24 -0700705 DCHECK(c1 != nullptr && !c1->IsPrimitive());
706 DCHECK(c2 != nullptr && !c2->IsPrimitive());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800707 mirror::Class* join_class = ClassJoin(c1, c2);
Ian Rogersb4903572012-10-11 11:52:56 -0700708 if (c1 == join_class && !IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700709 return *this;
Ian Rogersb4903572012-10-11 11:52:56 -0700710 } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700711 return incoming_type;
712 } else {
Ian Rogers1ff3c982014-08-12 02:30:58 -0700713 std::string temp;
714 return reg_types->FromClass(join_class->GetDescriptor(&temp), join_class, false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700715 }
716 }
717 } else {
Ian Rogers7b078e82014-09-10 14:44:24 -0700718 return conflict; // Unexpected types => Conflict
Ian Rogers776ac1f2012-04-13 23:36:36 -0700719 }
720}
721
Ian Rogersad0b3a32012-04-16 14:50:24 -0700722// See comment in reg_type.h
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800723mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700724 DCHECK(!s->IsPrimitive()) << PrettyClass(s);
725 DCHECK(!t->IsPrimitive()) << PrettyClass(t);
726 if (s == t) {
727 return s;
728 } else if (s->IsAssignableFrom(t)) {
729 return s;
730 } else if (t->IsAssignableFrom(s)) {
731 return t;
732 } else if (s->IsArrayClass() && t->IsArrayClass()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800733 mirror::Class* s_ct = s->GetComponentType();
734 mirror::Class* t_ct = t->GetComponentType();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700735 if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
736 // Given the types aren't the same, if either array is of primitive types then the only
737 // common parent is java.lang.Object
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800738 mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object
Ian Rogersad0b3a32012-04-16 14:50:24 -0700739 DCHECK(result->IsObjectClass());
740 return result;
741 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800742 mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700743 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Mathieu Chartierb74cd292014-05-29 14:31:33 -0700744 mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), &common_elem);
Ian Rogers7b078e82014-09-10 14:44:24 -0700745 DCHECK(array_class != nullptr);
Ian Rogersad0b3a32012-04-16 14:50:24 -0700746 return array_class;
747 } else {
748 size_t s_depth = s->Depth();
749 size_t t_depth = t->Depth();
750 // Get s and t to the same depth in the hierarchy
751 if (s_depth > t_depth) {
752 while (s_depth > t_depth) {
753 s = s->GetSuperClass();
754 s_depth--;
755 }
756 } else {
757 while (t_depth > s_depth) {
758 t = t->GetSuperClass();
759 t_depth--;
760 }
761 }
762 // Go up the hierarchy until we get to the common parent
763 while (s != t) {
764 s = s->GetSuperClass();
765 t = t->GetSuperClass();
766 }
767 return s;
768 }
769}
770
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800771void RegType::CheckInvariants() const {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800772 if (IsConstant() || IsConstantLo() || IsConstantHi()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800773 CHECK(descriptor_.empty()) << *this;
Ian Rogers54410912014-09-10 15:33:05 -0700774 CHECK(klass_.IsNull()) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800775 }
Ian Rogers54410912014-09-10 15:33:05 -0700776 if (!klass_.IsNull()) {
Ian Rogers637c65b2013-05-31 11:46:00 -0700777 CHECK(!descriptor_.empty()) << *this;
778 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800779}
780
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700781void RegType::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const {
782 klass_.VisitRootIfNonNull(visitor, root_info);
Mathieu Chartierc528dba2013-11-26 12:00:11 -0800783}
784
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700785void UninitializedThisReferenceType::CheckInvariants() const {
Ian Rogers637c65b2013-05-31 11:46:00 -0700786 CHECK_EQ(GetAllocationPc(), 0U) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800787}
788
Ian Rogers1bf8d4d2013-05-30 00:18:49 -0700789void UnresolvedUninitializedThisRefType::CheckInvariants() const {
Ian Rogers637c65b2013-05-31 11:46:00 -0700790 CHECK_EQ(GetAllocationPc(), 0U) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800791 CHECK(!descriptor_.empty()) << *this;
Ian Rogers54410912014-09-10 15:33:05 -0700792 CHECK(klass_.IsNull()) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800793}
794
795void UnresolvedUninitializedRefType::CheckInvariants() const {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800796 CHECK(!descriptor_.empty()) << *this;
Ian Rogers54410912014-09-10 15:33:05 -0700797 CHECK(klass_.IsNull()) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800798}
799
800void UnresolvedMergedType::CheckInvariants() const {
801 // Unresolved merged types: merged types should be defined.
802 CHECK(descriptor_.empty()) << *this;
Ian Rogers54410912014-09-10 15:33:05 -0700803 CHECK(klass_.IsNull()) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800804 CHECK_NE(merged_types_.first, 0U) << *this;
805 CHECK_NE(merged_types_.second, 0U) << *this;
806}
807
808void UnresolvedReferenceType::CheckInvariants() const {
809 CHECK(!descriptor_.empty()) << *this;
Ian Rogers54410912014-09-10 15:33:05 -0700810 CHECK(klass_.IsNull()) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800811}
812
813void UnresolvedSuperClass::CheckInvariants() const {
814 // Unresolved merged types: merged types should be defined.
815 CHECK(descriptor_.empty()) << *this;
Ian Rogers54410912014-09-10 15:33:05 -0700816 CHECK(klass_.IsNull()) << *this;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800817 CHECK_NE(unresolved_child_id_, 0U) << *this;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800818}
819
820std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
Ian Rogersd8f69b02014-09-10 21:43:52 +0000821 os << rhs.Dump();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700822 return os;
823}
824
Andreas Gampe16f149c2015-03-23 10:10:20 -0700825bool RegType::CanAssignArray(const RegType& src, RegTypeCache& reg_types,
826 Handle<mirror::ClassLoader> class_loader, bool* soft_error) const {
827 if (!IsArrayTypes() || !src.IsArrayTypes()) {
828 *soft_error = false;
829 return false;
830 }
831
832 const RegType& cmp1 = reg_types.GetComponentType(*this, class_loader.Get());
833 const RegType& cmp2 = reg_types.GetComponentType(src, class_loader.Get());
834
835 if (cmp1.IsAssignableFrom(cmp2)) {
836 return true;
837 }
838 if (cmp1.IsUnresolvedTypes()) {
839 if (cmp2.IsIntegralTypes() || cmp2.IsFloatTypes() || cmp2.IsArrayTypes()) {
840 *soft_error = false;
841 return false;
842 }
843 *soft_error = true;
844 return false;
845 }
846 if (cmp2.IsUnresolvedTypes()) {
847 if (cmp1.IsIntegralTypes() || cmp1.IsFloatTypes() || cmp1.IsArrayTypes()) {
848 *soft_error = false;
849 return false;
850 }
851 *soft_error = true;
852 return false;
853 }
854 if (!cmp1.IsArrayTypes() || !cmp2.IsArrayTypes()) {
855 *soft_error = false;
856 return false;
857 }
858 return cmp1.CanAssignArray(cmp2, reg_types, class_loader, soft_error);
859}
860
861
Elliott Hughesa21039c2012-06-21 12:09:25 -0700862} // namespace verifier
863} // namespace art