Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 1 | /* |
| 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 Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 17 | #include "reg_type-inl.h" |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 18 | |
| 19 | #include "base/casts.h" |
Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 20 | #include "class_linker-inl.h" |
Ian Rogers | 4f6ad8a | 2013-03-18 15:27:28 -0700 | [diff] [blame] | 21 | #include "dex_file-inl.h" |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 22 | #include "mirror/class.h" |
| 23 | #include "mirror/class-inl.h" |
| 24 | #include "mirror/object-inl.h" |
Ian Rogers | 693ff61 | 2013-02-01 10:56:12 -0800 | [diff] [blame] | 25 | #include "mirror/object_array-inl.h" |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 26 | #include "reg_type_cache-inl.h" |
Ian Rogers | 637c65b | 2013-05-31 11:46:00 -0700 | [diff] [blame] | 27 | #include "scoped_thread_state_change.h" |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 28 | |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 29 | #include <limits> |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 30 | #include <sstream> |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 31 | |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 32 | namespace art { |
| 33 | namespace verifier { |
| 34 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 35 | const UndefinedType* UndefinedType::instance_ = nullptr; |
| 36 | const ConflictType* ConflictType::instance_ = nullptr; |
| 37 | const BooleanType* BooleanType::instance_ = nullptr; |
| 38 | const ByteType* ByteType::instance_ = nullptr; |
| 39 | const ShortType* ShortType::instance_ = nullptr; |
| 40 | const CharType* CharType::instance_ = nullptr; |
| 41 | const FloatType* FloatType::instance_ = nullptr; |
| 42 | const LongLoType* LongLoType::instance_ = nullptr; |
| 43 | const LongHiType* LongHiType::instance_ = nullptr; |
| 44 | const DoubleLoType* DoubleLoType::instance_ = nullptr; |
| 45 | const DoubleHiType* DoubleHiType::instance_ = nullptr; |
| 46 | const IntegerType* IntegerType::instance_ = nullptr; |
Ian Rogers | 637c65b | 2013-05-31 11:46:00 -0700 | [diff] [blame] | 47 | |
| 48 | PrimitiveType::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 Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 51 | CHECK(klass != nullptr); |
Ian Rogers | 637c65b | 2013-05-31 11:46:00 -0700 | [diff] [blame] | 52 | CHECK(!descriptor.empty()); |
| 53 | } |
| 54 | |
| 55 | Cat1Type::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 | |
| 60 | Cat2Type::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 Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 65 | std::string PreciseConstType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 66 | std::stringstream result; |
| 67 | uint32_t val = ConstantValue(); |
| 68 | if (val == 0) { |
| 69 | CHECK(IsPreciseConstant()); |
| 70 | result << "Zero/null"; |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 71 | } else { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 72 | result << "Precise "; |
| 73 | if (IsConstantShort()) { |
| 74 | result << StringPrintf("Constant: %d", val); |
| 75 | } else { |
| 76 | result << StringPrintf("Constant: 0x%x", val); |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 77 | } |
| 78 | } |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 79 | return result.str(); |
| 80 | } |
| 81 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 82 | std::string BooleanType::Dump() const { |
Ian Rogers | 41c65c1 | 2013-09-05 16:57:17 -0700 | [diff] [blame] | 83 | return "Boolean"; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 84 | } |
| 85 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 86 | std::string ConflictType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 87 | return "Conflict"; |
| 88 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 89 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 90 | std::string ByteType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 91 | return "Byte"; |
| 92 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 93 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 94 | std::string ShortType::Dump() const { |
Ian Rogers | 41c65c1 | 2013-09-05 16:57:17 -0700 | [diff] [blame] | 95 | return "Short"; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 96 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 97 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 98 | std::string CharType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 99 | return "Char"; |
| 100 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 101 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 102 | std::string FloatType::Dump() const { |
Ian Rogers | 41c65c1 | 2013-09-05 16:57:17 -0700 | [diff] [blame] | 103 | return "Float"; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 104 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 105 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 106 | std::string LongLoType::Dump() const { |
Ian Rogers | 41c65c1 | 2013-09-05 16:57:17 -0700 | [diff] [blame] | 107 | return "Long (Low Half)"; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 108 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 109 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 110 | std::string LongHiType::Dump() const { |
Ian Rogers | 41c65c1 | 2013-09-05 16:57:17 -0700 | [diff] [blame] | 111 | return "Long (High Half)"; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 112 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 113 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 114 | std::string DoubleLoType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 115 | return "Double (Low Half)"; |
| 116 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 117 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 118 | std::string DoubleHiType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 119 | return "Double (High Half)"; |
| 120 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 121 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 122 | std::string IntegerType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 123 | return "Integer"; |
| 124 | } |
| 125 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 126 | const 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 Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 131 | return instance_; |
| 132 | } |
| 133 | |
| 134 | void DoubleHiType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 135 | if (instance_ != nullptr) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 136 | delete instance_; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 137 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 138 | } |
| 139 | } |
| 140 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 141 | const 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 Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 146 | return instance_; |
| 147 | } |
| 148 | |
| 149 | void DoubleLoType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 150 | if (instance_ != nullptr) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 151 | delete instance_; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 152 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 153 | } |
| 154 | } |
| 155 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 156 | const 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 Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 160 | return instance_; |
| 161 | } |
| 162 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 163 | const 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 Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 167 | return instance_; |
| 168 | } |
| 169 | |
| 170 | void LongHiType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 171 | if (instance_ != nullptr) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 172 | delete instance_; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 173 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 174 | } |
| 175 | } |
| 176 | |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 177 | void LongLoType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 178 | if (instance_ != nullptr) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 179 | delete instance_; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 180 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 181 | } |
| 182 | } |
| 183 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 184 | const 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 Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 188 | return instance_; |
| 189 | } |
| 190 | |
| 191 | void FloatType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 192 | if (instance_ != nullptr) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 193 | delete instance_; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 194 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 195 | } |
| 196 | } |
| 197 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 198 | const 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 Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 202 | return instance_; |
| 203 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 204 | |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 205 | void CharType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 206 | if (instance_ != nullptr) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 207 | delete instance_; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 208 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 209 | } |
| 210 | } |
| 211 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 212 | const 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 Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 216 | return instance_; |
| 217 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 218 | |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 219 | void ShortType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 220 | if (instance_ != nullptr) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 221 | delete instance_; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 222 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 223 | } |
| 224 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 225 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 226 | const 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 Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 230 | return instance_; |
| 231 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 232 | |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 233 | void ByteType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 234 | if (instance_ != nullptr) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 235 | delete instance_; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 236 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 237 | } |
| 238 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 239 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 240 | const 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 Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 244 | return instance_; |
| 245 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 246 | |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 247 | void IntegerType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 248 | if (instance_ != nullptr) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 249 | delete instance_; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 250 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 251 | } |
| 252 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 253 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 254 | const 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 Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 259 | return instance_; |
| 260 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 261 | |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 262 | void ConflictType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 263 | if (instance_ != nullptr) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 264 | delete instance_; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 265 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 266 | } |
| 267 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 268 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 269 | const BooleanType* BooleanType::CreateInstance(mirror::Class* klass, const std::string& descriptor, |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 270 | uint16_t cache_id) { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 271 | CHECK(BooleanType::instance_ == nullptr); |
| 272 | instance_ = new BooleanType(klass, descriptor, cache_id); |
| 273 | return BooleanType::instance_; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 274 | } |
| 275 | |
| 276 | void BooleanType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 277 | if (BooleanType::instance_ != nullptr) { |
| 278 | delete instance_; |
| 279 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 280 | } |
| 281 | } |
| 282 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 283 | std::string UndefinedType::Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 284 | return "Undefined"; |
| 285 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 286 | |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 287 | const 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 Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 292 | return instance_; |
| 293 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 294 | |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 295 | void UndefinedType::Destroy() { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 296 | if (instance_ != nullptr) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 297 | delete instance_; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 298 | instance_ = nullptr; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 299 | } |
| 300 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 301 | |
Ian Rogers | 637c65b | 2013-05-31 11:46:00 -0700 | [diff] [blame] | 302 | PreciseReferenceType::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 Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 308 | std::string UnresolvedMergedType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 309 | std::stringstream result; |
| 310 | std::set<uint16_t> types = GetMergedTypes(); |
| 311 | result << "UnresolvedMergedReferences("; |
Mathieu Chartier | 02e2511 | 2013-08-14 16:14:24 -0700 | [diff] [blame] | 312 | auto it = types.begin(); |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 313 | 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 Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 321 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 322 | std::string UnresolvedSuperClass::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 323 | 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 Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 329 | std::string UnresolvedReferenceType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 330 | std::stringstream result; |
Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 331 | result << "Unresolved Reference" << ": " << PrettyDescriptor(GetDescriptor().c_str()); |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 332 | return result.str(); |
| 333 | } |
| 334 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 335 | std::string UnresolvedUninitializedRefType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 336 | std::stringstream result; |
Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 337 | result << "Unresolved And Uninitialized Reference" << ": " |
| 338 | << PrettyDescriptor(GetDescriptor().c_str()) |
| 339 | << " Allocation PC: " << GetAllocationPc(); |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 340 | return result.str(); |
| 341 | } |
| 342 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 343 | std::string UnresolvedUninitializedThisRefType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 344 | std::stringstream result; |
Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 345 | result << "Unresolved And Uninitialized This Reference" |
| 346 | << PrettyDescriptor(GetDescriptor().c_str()); |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 347 | return result.str(); |
| 348 | } |
| 349 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 350 | std::string ReferenceType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 351 | std::stringstream result; |
| 352 | result << "Reference" << ": " << PrettyDescriptor(GetClass()); |
| 353 | return result.str(); |
| 354 | } |
| 355 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 356 | std::string PreciseReferenceType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 357 | std::stringstream result; |
| 358 | result << "Precise Reference" << ": "<< PrettyDescriptor(GetClass()); |
| 359 | return result.str(); |
| 360 | } |
| 361 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 362 | std::string UninitializedReferenceType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 363 | std::stringstream result; |
| 364 | result << "Uninitialized Reference" << ": " << PrettyDescriptor(GetClass()); |
| 365 | result << " Allocation PC: " << GetAllocationPc(); |
| 366 | return result.str(); |
| 367 | } |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 368 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 369 | std::string UninitializedThisReferenceType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 370 | std::stringstream result; |
| 371 | result << "Uninitialized This Reference" << ": " << PrettyDescriptor(GetClass()); |
| 372 | result << "Allocation PC: " << GetAllocationPc(); |
| 373 | return result.str(); |
| 374 | } |
| 375 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 376 | std::string ImpreciseConstType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 377 | std::stringstream result; |
| 378 | uint32_t val = ConstantValue(); |
| 379 | if (val == 0) { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 380 | 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 Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 391 | std::string PreciseConstLoType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 392 | 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 Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 405 | std::string ImpreciseConstLoType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 406 | 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 Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 419 | std::string PreciseConstHiType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 420 | 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 Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 432 | std::string ImpreciseConstHiType::Dump() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 433 | 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 Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 445 | const RegType& RegType::HighHalf(RegTypeCache* cache) const { |
Ian Rogers | 2bcb4a4 | 2012-11-08 10:39:18 -0800 | [diff] [blame] | 446 | DCHECK(IsLowHalf()); |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 447 | if (IsLongLo()) { |
| 448 | return cache->LongHi(); |
| 449 | } else if (IsDoubleLo()) { |
| 450 | return cache->DoubleHi(); |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 451 | } else { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 452 | DCHECK(IsImpreciseConstantLo()); |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 453 | const ConstantType* const_val = down_cast<const ConstantType*>(this); |
| 454 | return cache->FromCat2ConstHi(const_val->ConstantValue(), false); |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 455 | } |
| 456 | } |
| 457 | |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 458 | Primitive::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 Rogers | 637c65b | 2013-05-31 11:46:00 -0700 | [diff] [blame] | 481 | bool UninitializedType::IsUninitializedTypes() const { |
| 482 | return true; |
| 483 | } |
| 484 | |
| 485 | bool UninitializedType::IsNonZeroReferenceTypes() const { |
| 486 | return true; |
| 487 | } |
| 488 | |
| 489 | bool UnresolvedType::IsNonZeroReferenceTypes() const { |
| 490 | return true; |
| 491 | } |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 492 | |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 493 | std::set<uint16_t> UnresolvedMergedType::GetMergedTypes() const { |
Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 494 | std::pair<uint16_t, uint16_t> refs = GetTopMergedTypes(); |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 495 | const RegType& left = reg_type_cache_->GetFromId(refs.first); |
| 496 | const RegType& right = reg_type_cache_->GetFromId(refs.second); |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 497 | |
Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 498 | std::set<uint16_t> types; |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 499 | if (left.IsUnresolvedMergedReference()) { |
| 500 | types = down_cast<const UnresolvedMergedType*>(&left)->GetMergedTypes(); |
Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 501 | } else { |
| 502 | types.insert(refs.first); |
| 503 | } |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 504 | if (right.IsUnresolvedMergedReference()) { |
| 505 | std::set<uint16_t> right_types = |
| 506 | down_cast<const UnresolvedMergedType*>(&right)->GetMergedTypes(); |
Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 507 | types.insert(right_types.begin(), right_types.end()); |
| 508 | } else { |
| 509 | types.insert(refs.second); |
| 510 | } |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 511 | if (kIsDebugBuild) { |
Mathieu Chartier | 02e2511 | 2013-08-14 16:14:24 -0700 | [diff] [blame] | 512 | for (const auto& type : types) { |
| 513 | CHECK(!reg_type_cache_->GetFromId(type).IsUnresolvedMergedReference()); |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 514 | } |
Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 515 | } |
Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 516 | return types; |
| 517 | } |
| 518 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 519 | const RegType& RegType::GetSuperClass(RegTypeCache* cache) const { |
Ian Rogers | ad0b3a3 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 520 | if (!IsUnresolvedTypes()) { |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 521 | mirror::Class* super_klass = GetClass()->GetSuperClass(); |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 522 | if (super_klass != nullptr) { |
Sameer Abu Asal | 02c4223 | 2013-04-30 12:09:45 -0700 | [diff] [blame] | 523 | // A super class of a precise type isn't precise as a precise type indicates the register |
| 524 | // holds exactly that type. |
Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 525 | std::string temp; |
| 526 | return cache->FromClass(super_klass->GetDescriptor(&temp), super_klass, false); |
Ian Rogers | 0d60484 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 527 | } else { |
Ian Rogers | ad0b3a3 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 528 | return cache->Zero(); |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 529 | } |
Ian Rogers | ad0b3a3 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 530 | } else { |
Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 531 | if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() && |
Elliott Hughes | 80537bb | 2013-01-04 16:37:26 -0800 | [diff] [blame] | 532 | GetDescriptor()[0] == '[') { |
Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 533 | // Super class of all arrays is Object. |
Ian Rogers | b490357 | 2012-10-11 11:52:56 -0700 | [diff] [blame] | 534 | return cache->JavaLangObject(true); |
Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 535 | } else { |
| 536 | return cache->FromUnresolvedSuperClass(*this); |
| 537 | } |
Ian Rogers | ad0b3a3 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 538 | } |
| 539 | } |
| 540 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 541 | bool RegType::IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 542 | 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 Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 554 | bool RegType::IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 555 | return IsReference() && GetClass()->IsObjectClass(); |
| 556 | } |
| 557 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 558 | bool RegType::IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 559 | 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 Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 568 | bool RegType::IsJavaLangObjectArray() const { |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 569 | if (HasClass()) { |
| 570 | mirror::Class* type = GetClass(); |
| 571 | return type->IsArrayClass() && type->GetComponentType()->IsObjectClass(); |
| 572 | } |
| 573 | return false; |
| 574 | } |
| 575 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 576 | bool RegType::IsInstantiableTypes() const { |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 577 | return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable()); |
| 578 | } |
| 579 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 580 | static const RegType& SelectNonConstant(const RegType& a, const RegType& b) { |
Sebastien Hertz | aa0c00c | 2014-03-14 17:58:54 +0100 | [diff] [blame] | 581 | return a.IsConstantTypes() ? b : a; |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 582 | } |
| 583 | |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 584 | const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const { |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 585 | DCHECK(!Equals(incoming_type)); // Trivial equality handled by caller |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 586 | // 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 Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 590 | return *this; // Conflict MERGE * => Conflict |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 591 | } else if (&incoming_type == &conflict) { |
| 592 | DCHECK(incoming_type.IsConflict()); |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 593 | return incoming_type; // * MERGE Conflict => Conflict |
Ian Rogers | ad0b3a3 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 594 | } else if (IsUndefined() || incoming_type.IsUndefined()) { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 595 | return conflict; // Unknown MERGE * => Conflict |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 596 | } else if (IsConstant() && incoming_type.IsConstant()) { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 597 | 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 Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 601 | if (val1 >= 0 && val2 >= 0) { |
| 602 | // +ve1 MERGE +ve2 => MAX(+ve1, +ve2) |
| 603 | if (val1 >= val2) { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 604 | if (!type1.IsPreciseConstant()) { |
Ian Rogers | 2bcb4a4 | 2012-11-08 10:39:18 -0800 | [diff] [blame] | 605 | return *this; |
| 606 | } else { |
| 607 | return reg_types->FromCat1Const(val1, false); |
| 608 | } |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 609 | } else { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 610 | if (!type2.IsPreciseConstant()) { |
| 611 | return type2; |
Ian Rogers | 2bcb4a4 | 2012-11-08 10:39:18 -0800 | [diff] [blame] | 612 | } else { |
| 613 | return reg_types->FromCat1Const(val2, false); |
| 614 | } |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 615 | } |
| 616 | } else if (val1 < 0 && val2 < 0) { |
| 617 | // -ve1 MERGE -ve2 => MIN(-ve1, -ve2) |
| 618 | if (val1 <= val2) { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 619 | if (!type1.IsPreciseConstant()) { |
Ian Rogers | 2bcb4a4 | 2012-11-08 10:39:18 -0800 | [diff] [blame] | 620 | return *this; |
| 621 | } else { |
| 622 | return reg_types->FromCat1Const(val1, false); |
| 623 | } |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 624 | } else { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 625 | if (!type2.IsPreciseConstant()) { |
| 626 | return type2; |
Ian Rogers | 2bcb4a4 | 2012-11-08 10:39:18 -0800 | [diff] [blame] | 627 | } else { |
| 628 | return reg_types->FromCat1Const(val2, false); |
| 629 | } |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 630 | } |
| 631 | } else { |
| 632 | // Values are +ve and -ve, choose smallest signed type in which they both fit |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 633 | if (type1.IsConstantByte()) { |
| 634 | if (type2.IsConstantByte()) { |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 635 | return reg_types->ByteConstant(); |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 636 | } else if (type2.IsConstantShort()) { |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 637 | return reg_types->ShortConstant(); |
| 638 | } else { |
| 639 | return reg_types->IntConstant(); |
| 640 | } |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 641 | } else if (type1.IsConstantShort()) { |
| 642 | if (type2.IsConstantShort()) { |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 643 | return reg_types->ShortConstant(); |
| 644 | } else { |
| 645 | return reg_types->IntConstant(); |
| 646 | } |
| 647 | } else { |
| 648 | return reg_types->IntConstant(); |
| 649 | } |
| 650 | } |
Ian Rogers | 2bcb4a4 | 2012-11-08 10:39:18 -0800 | [diff] [blame] | 651 | } else if (IsConstantLo() && incoming_type.IsConstantLo()) { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 652 | 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 Rogers | 2bcb4a4 | 2012-11-08 10:39:18 -0800 | [diff] [blame] | 656 | return reg_types->FromCat2ConstLo(val1 | val2, false); |
| 657 | } else if (IsConstantHi() && incoming_type.IsConstantHi()) { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 658 | 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 Rogers | 2bcb4a4 | 2012-11-08 10:39:18 -0800 | [diff] [blame] | 662 | return reg_types->FromCat2ConstHi(val1 | val2, false); |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 663 | } 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 Rogers | b490357 | 2012-10-11 11:52:56 -0700 | [diff] [blame] | 690 | return reg_types->JavaLangObject(false); // Object MERGE ref => Object |
Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 691 | } 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 Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 701 | return conflict; |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 702 | } else { // Two reference types, compute Join |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 703 | mirror::Class* c1 = GetClass(); |
| 704 | mirror::Class* c2 = incoming_type.GetClass(); |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 705 | DCHECK(c1 != nullptr && !c1->IsPrimitive()); |
| 706 | DCHECK(c2 != nullptr && !c2->IsPrimitive()); |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 707 | mirror::Class* join_class = ClassJoin(c1, c2); |
Ian Rogers | b490357 | 2012-10-11 11:52:56 -0700 | [diff] [blame] | 708 | if (c1 == join_class && !IsPreciseReference()) { |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 709 | return *this; |
Ian Rogers | b490357 | 2012-10-11 11:52:56 -0700 | [diff] [blame] | 710 | } else if (c2 == join_class && !incoming_type.IsPreciseReference()) { |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 711 | return incoming_type; |
| 712 | } else { |
Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 713 | std::string temp; |
| 714 | return reg_types->FromClass(join_class->GetDescriptor(&temp), join_class, false); |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 715 | } |
| 716 | } |
| 717 | } else { |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 718 | return conflict; // Unexpected types => Conflict |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 719 | } |
| 720 | } |
| 721 | |
Ian Rogers | ad0b3a3 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 722 | // See comment in reg_type.h |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 723 | mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) { |
Ian Rogers | ad0b3a3 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 724 | 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 Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 733 | mirror::Class* s_ct = s->GetComponentType(); |
| 734 | mirror::Class* t_ct = t->GetComponentType(); |
Ian Rogers | ad0b3a3 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 735 | 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 Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 738 | mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object |
Ian Rogers | ad0b3a3 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 739 | DCHECK(result->IsObjectClass()); |
| 740 | return result; |
| 741 | } |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 742 | mirror::Class* common_elem = ClassJoin(s_ct, t_ct); |
Ian Rogers | ad0b3a3 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 743 | ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); |
Mathieu Chartier | b74cd29 | 2014-05-29 14:31:33 -0700 | [diff] [blame] | 744 | mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), &common_elem); |
Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 745 | DCHECK(array_class != nullptr); |
Ian Rogers | ad0b3a3 | 2012-04-16 14:50:24 -0700 | [diff] [blame] | 746 | 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 Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 771 | void RegType::CheckInvariants() const { |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 772 | if (IsConstant() || IsConstantLo() || IsConstantHi()) { |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 773 | CHECK(descriptor_.empty()) << *this; |
Ian Rogers | 5441091 | 2014-09-10 15:33:05 -0700 | [diff] [blame] | 774 | CHECK(klass_.IsNull()) << *this; |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 775 | } |
Ian Rogers | 5441091 | 2014-09-10 15:33:05 -0700 | [diff] [blame] | 776 | if (!klass_.IsNull()) { |
Ian Rogers | 637c65b | 2013-05-31 11:46:00 -0700 | [diff] [blame] | 777 | CHECK(!descriptor_.empty()) << *this; |
| 778 | } |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 779 | } |
| 780 | |
Mathieu Chartier | bb87e0f | 2015-04-03 11:21:55 -0700 | [diff] [blame] | 781 | void RegType::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const { |
| 782 | klass_.VisitRootIfNonNull(visitor, root_info); |
Mathieu Chartier | c528dba | 2013-11-26 12:00:11 -0800 | [diff] [blame] | 783 | } |
| 784 | |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 785 | void UninitializedThisReferenceType::CheckInvariants() const { |
Ian Rogers | 637c65b | 2013-05-31 11:46:00 -0700 | [diff] [blame] | 786 | CHECK_EQ(GetAllocationPc(), 0U) << *this; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 787 | } |
| 788 | |
Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 789 | void UnresolvedUninitializedThisRefType::CheckInvariants() const { |
Ian Rogers | 637c65b | 2013-05-31 11:46:00 -0700 | [diff] [blame] | 790 | CHECK_EQ(GetAllocationPc(), 0U) << *this; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 791 | CHECK(!descriptor_.empty()) << *this; |
Ian Rogers | 5441091 | 2014-09-10 15:33:05 -0700 | [diff] [blame] | 792 | CHECK(klass_.IsNull()) << *this; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 793 | } |
| 794 | |
| 795 | void UnresolvedUninitializedRefType::CheckInvariants() const { |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 796 | CHECK(!descriptor_.empty()) << *this; |
Ian Rogers | 5441091 | 2014-09-10 15:33:05 -0700 | [diff] [blame] | 797 | CHECK(klass_.IsNull()) << *this; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 798 | } |
| 799 | |
| 800 | void UnresolvedMergedType::CheckInvariants() const { |
| 801 | // Unresolved merged types: merged types should be defined. |
| 802 | CHECK(descriptor_.empty()) << *this; |
Ian Rogers | 5441091 | 2014-09-10 15:33:05 -0700 | [diff] [blame] | 803 | CHECK(klass_.IsNull()) << *this; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 804 | CHECK_NE(merged_types_.first, 0U) << *this; |
| 805 | CHECK_NE(merged_types_.second, 0U) << *this; |
| 806 | } |
| 807 | |
| 808 | void UnresolvedReferenceType::CheckInvariants() const { |
| 809 | CHECK(!descriptor_.empty()) << *this; |
Ian Rogers | 5441091 | 2014-09-10 15:33:05 -0700 | [diff] [blame] | 810 | CHECK(klass_.IsNull()) << *this; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 811 | } |
| 812 | |
| 813 | void UnresolvedSuperClass::CheckInvariants() const { |
| 814 | // Unresolved merged types: merged types should be defined. |
| 815 | CHECK(descriptor_.empty()) << *this; |
Ian Rogers | 5441091 | 2014-09-10 15:33:05 -0700 | [diff] [blame] | 816 | CHECK(klass_.IsNull()) << *this; |
Sameer Abu Asal | 51a5fb7 | 2013-02-19 14:25:01 -0800 | [diff] [blame] | 817 | CHECK_NE(unresolved_child_id_, 0U) << *this; |
Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 818 | } |
| 819 | |
| 820 | std::ostream& operator<<(std::ostream& os, const RegType& rhs) { |
Ian Rogers | d8f69b0 | 2014-09-10 21:43:52 +0000 | [diff] [blame] | 821 | os << rhs.Dump(); |
Ian Rogers | 776ac1f | 2012-04-13 23:36:36 -0700 | [diff] [blame] | 822 | return os; |
| 823 | } |
| 824 | |
Andreas Gampe | 16f149c | 2015-03-23 10:10:20 -0700 | [diff] [blame] | 825 | bool 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 Hughes | a21039c | 2012-06-21 12:09:25 -0700 | [diff] [blame] | 862 | } // namespace verifier |
| 863 | } // namespace art |