blob: c7a1b4f047c37caf9971032aa5de5023463849d0 [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
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080017#include "reg_type_cache-inl.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070018
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080019#include "base/casts.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070020#include "dex_file-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080021#include "mirror/class-inl.h"
22#include "mirror/object-inl.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070023#include "object_utils.h"
24
25namespace art {
26namespace verifier {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080027bool RegTypeCache::primitive_initialized_ = false;
28uint16_t RegTypeCache::primitive_start_ = 0;
29uint16_t RegTypeCache::primitive_count_ = 0;
Ian Rogers776ac1f2012-04-13 23:36:36 -070030
Ian Rogersb4903572012-10-11 11:52:56 -070031static bool MatchingPrecisionForClass(RegType* entry, bool precise)
32 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
33 return (entry->IsPreciseReference() == precise) || (entry->GetClass()->IsFinal() && !precise);
34}
35
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080036void RegTypeCache::FillPrimitiveTypes() {
37 entries_.push_back(UndefinedType::GetInstance());
38 entries_.push_back(ConflictType::GetInstance());
39 entries_.push_back(BooleanType::GetInstance());
40 entries_.push_back(ByteType::GetInstance());
41 entries_.push_back(ShortType::GetInstance());
42 entries_.push_back(CharType::GetInstance());
43 entries_.push_back(IntegerType::GetInstance());
44 entries_.push_back(LongLoType::GetInstance());
45 entries_.push_back(LongHiType::GetInstance());
46 entries_.push_back(FloatType::GetInstance());
47 entries_.push_back(DoubleLoType::GetInstance());
48 entries_.push_back(DoubleHiType::GetInstance());
49 DCHECK_EQ(entries_.size(), primitive_count_);
50}
51
52const RegType& RegTypeCache::FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, bool precise) {
53 CHECK(RegTypeCache::primitive_initialized_);
54 if (std::string(descriptor).length() == 1) {
55 switch (descriptor[0]) {
56 case 'Z':
57 return Boolean();
58 case 'B':
59 return Byte();
60 case 'S':
61 return Short();
62 case 'C':
63 return Char();
64 case 'I':
65 return Integer();
66 case 'J':
67 return LongLo();
68 case 'F':
69 return Float();
70 case 'D':
71 return DoubleLo();
72 case 'V': // For void types, conflict types.
73 default:
Ian Rogersad0b3a32012-04-16 14:50:24 -070074 return Conflict();
Ian Rogers776ac1f2012-04-13 23:36:36 -070075 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -080076 } else if (descriptor[0] == 'L' || descriptor[0] == '[') {
77 return From(loader, descriptor, precise);
78 } else {
79 return Conflict();
80 }
81};
82
83const art::verifier::RegType& RegTypeCache::GetFromId(uint16_t id) const {
84 DCHECK_LT(id, entries_.size());
85 RegType* result = entries_[id];
86 DCHECK(result != NULL);
87 return *result;
88}
89
90const RegType& RegTypeCache::RegTypeFromPrimitiveType(
91 Primitive::Type prim_type) const {
92 CHECK(RegTypeCache::primitive_initialized_);
93 switch (prim_type) {
94 case Primitive::kPrimBoolean:
95 return *BooleanType::GetInstance();
96 case Primitive::kPrimByte:
97 return *ByteType::GetInstance();
98 case Primitive::kPrimShort:
99 return *ShortType::GetInstance();
100 case Primitive::kPrimChar:
101 return *CharType::GetInstance();
102 case Primitive::kPrimInt:
103 return *IntegerType::GetInstance();
104 case Primitive::kPrimLong:
105 return *LongLoType::GetInstance();
106 case Primitive::kPrimFloat:
107 return *FloatType::GetInstance();
108 case Primitive::kPrimDouble:
109 return *DoubleLoType::GetInstance();
110 case Primitive::kPrimVoid:
111 default:
112 return *ConflictType::GetInstance();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700113 }
114}
115
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800116bool RegTypeCache::MatchDescriptor(size_t idx, std::string& descriptor, bool precise) {
117 ClassHelper kh;
118 RegType* cur_entry = entries_[idx];
119 // Check if we have matching descriptors and precision
120 // in cases where the descriptor available
121 if (cur_entry->descriptor_ != "" &&
122 MatchingPrecisionForClass(cur_entry, precise) &&
123 descriptor == cur_entry->descriptor_) {
124 return true;
125 }
126 // check resolved and unresolved references, ignore uninitialized references
127 if (cur_entry->HasClass()) {
128 kh.ChangeClass(cur_entry->GetClass());
129 // So we might have cases where we have the class but not the descriptor
130 // for that class we need the class helper to get the descriptor
131 // and match it with the one we are given.
132 if (MatchingPrecisionForClass(cur_entry, precise) &&
133 (strcmp(descriptor.c_str(), kh.GetDescriptor()) == 0)) {
134 return true;
135 }
136 } else if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
137 return true;
138 }
139 return false;
140}
141
142mirror::Class* RegTypeCache::ResolveClass(std::string descriptor, mirror::ClassLoader* loader) {
143 // Class was not found, must create new type.
144 // Try resolving class
145 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
146 mirror::Class* klass = NULL;
147 if (can_load_classes_) {
148 klass = class_linker->FindClass(descriptor.c_str(), loader);
149 } else {
150 klass = class_linker->LookupClass(descriptor.c_str(), loader);
151 }
152 return klass;
153}
154void RegTypeCache::ClearException() {
155 if (can_load_classes_) {
156 DCHECK(Thread::Current()->IsExceptionPending());
157 Thread::Current()->ClearException();
158 } else {
159 DCHECK(!Thread::Current()->IsExceptionPending());
160 }
161}
162const RegType& RegTypeCache::From(mirror::ClassLoader* loader, std::string descriptor, bool precise) {
163 // Try resolving class.
164 mirror::Class* klass = ResolveClass(descriptor, loader);
165 if (klass != NULL) {
166 // Class resolved, first look for the class in the list of entries
167 for (size_t i = primitive_count_; i < entries_.size(); i++) {
168 if (entries_[i]->HasClass()) {
169 if (MatchDescriptor(i, descriptor, precise)) {
170 return *(entries_[i]);
171 }
172 }
173 }
174 // Class was not found, must create new type.
175
176 // Create a type if:
177 // 1-The class is instantiable ( not Abstract or Interface ), we should
178 // abort failing the verification if we get that.
179 // 2- And, the class should be instantiable (Not interface, Abstract or a
180 // primitive type) OR it is imprecise.
181
182 // Create a precise type if :
183 // 1-The class is final.
184 // 2-OR the precise was passed as true .
185 CHECK(!precise || klass->IsInstantiable());
186 RegType* entry;
187 // Create an imprecise type if we can'tt tell for a fact that it is precise.
188 if (klass->IsFinal() || precise) {
189 entry = new PreciseReferenceType(klass, descriptor, entries_.size());
190 } else {
191 entry = new ReferenceType(klass, descriptor, entries_.size());
192 }
193 entries_.push_back(entry);
194 return *entry;
195 } else { // Class not resolved.
196 // We tried loading the class and failed, this might get an exception raised
197 // so we want to clear it before we go on.
198 ClearException();
199 // Unable to resolve class. Look through unresolved types in the catch and see
200 // if we have it created before.
201 for (size_t i = primitive_count_; i < entries_.size(); i++) {
202 if (entries_[i]->IsUnresolvedReference() &&
203 entries_[i]->descriptor_ == descriptor) {
204 return *(entries_[i]);
205 }
206 }
207 if (IsValidDescriptor(descriptor.c_str())) {
208 RegType* entry = new UnresolvedReferenceType(descriptor, entries_.size());
209 entries_.push_back(entry);
210 return *entry;
211 } else {
212 // The descriptor is broken return the unknown type as there's nothing sensible that
213 // could be done at runtime
214 return Conflict();
215 }
216 }
217}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800218const RegType& RegTypeCache::FromClass(mirror::Class* klass, bool precise) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700219 if (klass->IsPrimitive()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800220 return RegTypeFromPrimitiveType(klass->GetPrimitiveType());
221
Ian Rogers776ac1f2012-04-13 23:36:36 -0700222 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800223 // Look for the reference in the list of entries to have.
224 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700225 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700226 if ((cur_entry->HasClass()) &&
227 MatchingPrecisionForClass(cur_entry, precise) && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700228 return *cur_entry;
229 }
230 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800231 // No reference to the class was found, create new reference.
232 RegType* entry;
233 std::string empty = "";
234 if (precise) {
235 entry = new PreciseReferenceType(klass, empty, entries_.size());
236 } else {
237 entry = new ReferenceType(klass, empty, entries_.size());
238 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700239 entries_.push_back(entry);
240 return *entry;
241 }
242}
243
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800244RegTypeCache::~RegTypeCache() {
245 CHECK_LE(primitive_count_, entries_.size());
246 // Delete only the non primitive types.
247 if (primitive_count_ == static_cast<uint16_t>(entries_.size())) {
248 // All entries are primitive, nothing to delete.
249 return;
250 }
251 std::vector<RegType*>::iterator non_primitive_begin = entries_.begin();
252 std::advance(non_primitive_begin, primitive_count_);
253 STLDeleteContainerPointers(non_primitive_begin, entries_.end());
254}
255
256void RegTypeCache::ShutDown() {
257 if (RegTypeCache::primitive_initialized_) {
258 UndefinedType::Destroy();
259 ConflictType::Destroy();
260 BooleanType::Destroy();
261 ByteType::Destroy();
262 ShortType::Destroy();
263 CharType::Destroy();
264 IntegerType::Destroy();
265 LongLoType::Destroy();
266 LongHiType::Destroy();
267 FloatType::GetInstance();
268 DoubleLoType::Destroy();
269 DoubleHiType::Destroy();
270 RegTypeCache::primitive_initialized_ = false;
271 RegTypeCache::primitive_count_ = 0;
272 }
273}
274
275void RegTypeCache::CreatePrimitiveTypes() {
276 CreatePrimitiveTypeInstance<UndefinedType>(NULL, "");
277 CreatePrimitiveTypeInstance<ConflictType>(NULL, "");
278 CreatePrimitiveTypeInstance<BooleanType>(NULL, "Z");
279 CreatePrimitiveTypeInstance<ByteType>(NULL, "B");
280 CreatePrimitiveTypeInstance<ShortType>(NULL, "S");
281 CreatePrimitiveTypeInstance<CharType>(NULL, "C");
282 CreatePrimitiveTypeInstance<IntegerType>(NULL, "I");
283 CreatePrimitiveTypeInstance<LongLoType>(NULL, "J");
284 CreatePrimitiveTypeInstance<LongHiType>(NULL, "J");
285 CreatePrimitiveTypeInstance<FloatType>(NULL, "F");
286 CreatePrimitiveTypeInstance<DoubleLoType>(NULL, "D");
287 CreatePrimitiveTypeInstance<DoubleHiType>(NULL, "D");
288}
289
Ian Rogers529781d2012-07-23 17:24:29 -0700290const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left, const RegType& right) {
291 std::set<uint16_t> types;
292 if (left.IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800293 RegType& non_const(const_cast<RegType&>(left));
294 types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700295 } else {
296 types.insert(left.GetId());
297 }
298 if (right.IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800299 RegType& non_const(const_cast<RegType&>(right));
300 std::set<uint16_t> right_types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700301 types.insert(right_types.begin(), right_types.end());
302 } else {
303 types.insert(right.GetId());
304 }
305 // Check if entry already exists.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800306 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers529781d2012-07-23 17:24:29 -0700307 RegType* cur_entry = entries_[i];
308 if (cur_entry->IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800309 std::set<uint16_t> cur_entry_types =
310 (down_cast<UnresolvedMergedType*>(cur_entry))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700311 if (cur_entry_types == types) {
312 return *cur_entry;
313 }
314 }
315 }
316 // Create entry.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800317 RegType* entry = new UnresolvedMergedType(left.GetId(), right.GetId(), this, entries_.size());
Ian Rogers529781d2012-07-23 17:24:29 -0700318 entries_.push_back(entry);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800319#ifndef NDEBUG
320 UnresolvedMergedType* tmp_entry = down_cast<UnresolvedMergedType*>(entry);
321 std::set<uint16_t> check_types = tmp_entry->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700322 CHECK(check_types == types);
323#endif
324 return *entry;
325}
Ian Rogers529781d2012-07-23 17:24:29 -0700326const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
327 // Check if entry already exists.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800328 for (size_t i = primitive_count_; i < entries_.size(); i++) {
329 RegType* cur_entry = entries_[i];
330 if (cur_entry->IsUnresolvedSuperClass()) {
331 UnresolvedSuperClass* tmp_entry =
332 down_cast<UnresolvedSuperClass*>(cur_entry);
333 uint16_t unresolved_super_child_id =
334 tmp_entry->GetUnresolvedSuperClassChildId();
335 if (unresolved_super_child_id == child.GetId()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700336 return *cur_entry;
337 }
338 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800339 }
340 RegType* entry = new UnresolvedSuperClass(child.GetId(), this, entries_.size());
341 entries_.push_back(entry);
342 return *entry;
343}
344const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
345 RegType* entry = NULL;
346 RegType* cur_entry = NULL;
347 if (type.IsUnresolvedTypes()) {
348 std::string descriptor(type.GetDescriptor());
349 for (size_t i = primitive_count_; i < entries_.size(); i++) {
350 cur_entry = entries_[i];
351 if (cur_entry->IsUnresolvedAndUninitializedReference() &&
352 down_cast<UnresolvedUninitializedRefType*>(cur_entry)->GetAllocationPc() == allocation_pc &&
353 (cur_entry->GetDescriptor() == descriptor)) {
354 return *cur_entry;
355 }
356 }
357 entry = new UnresolvedUninitializedRefType(descriptor, allocation_pc, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700358 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800359 mirror::Class* klass = type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800360 for (size_t i = primitive_count_; i < entries_.size(); i++) {
361 cur_entry = entries_[i];
Ian Rogers776ac1f2012-04-13 23:36:36 -0700362 if (cur_entry->IsUninitializedReference() &&
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800363 down_cast<UninitialisedReferenceType*>(cur_entry)
364 ->GetAllocationPc() == allocation_pc &&
Ian Rogers776ac1f2012-04-13 23:36:36 -0700365 cur_entry->GetClass() == klass) {
366 return *cur_entry;
367 }
368 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800369 std::string descriptor = "";
370 entry = new UninitialisedReferenceType(klass, descriptor, allocation_pc, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700371 }
372 entries_.push_back(entry);
373 return *entry;
374}
Ian Rogers776ac1f2012-04-13 23:36:36 -0700375const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
376 RegType* entry;
377 if (uninit_type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800378 std::string descriptor(uninit_type.GetDescriptor());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800379 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700380 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800381 if (cur_entry->IsUnresolvedReference() &&
382 cur_entry->GetDescriptor() == descriptor) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700383 return *cur_entry;
384 }
385 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800386 entry = new UnresolvedReferenceType(descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700387 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800388 mirror::Class* klass = uninit_type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800389 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700390 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700391 if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700392 return *cur_entry;
393 }
394 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800395 std::string descriptor = "";
396 entry = new PreciseReferenceType(klass, descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700397 }
398 entries_.push_back(entry);
399 return *entry;
400}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800401const RegType& RegTypeCache::ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
402 return FromCat1Const(std::numeric_limits<jbyte>::min(), false);
403}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800404const RegType& RegTypeCache::ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
405 return FromCat1Const(std::numeric_limits<jshort>::min(), false);
406}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800407const RegType& RegTypeCache::IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
408 return FromCat1Const(std::numeric_limits<jint>::max(), false);
409}
Ian Rogersad0b3a32012-04-16 14:50:24 -0700410const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700411 RegType* entry;
412 if (type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800413 std::string descriptor(type.GetDescriptor());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800414 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700415 RegType* cur_entry = entries_[i];
416 if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
417 cur_entry->GetDescriptor() == descriptor) {
418 return *cur_entry;
419 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700420 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800421 entry = new UnresolvedUninitialisedThisRefType(descriptor, entries_.size());
Ian Rogersad0b3a32012-04-16 14:50:24 -0700422 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800423 mirror::Class* klass = type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800424 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700425 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800426 if (cur_entry->IsUninitializedThisReference() &&
427 cur_entry->GetClass() == klass) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700428 return *cur_entry;
429 }
430 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800431 std::string descriptor = "";
432 entry = new UninitialisedThisReferenceType(klass, descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700433 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700434 entries_.push_back(entry);
435 return *entry;
436}
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800437const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800438 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700439 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800440 if (cur_entry->IsConstant() && cur_entry->IsPreciseConstant() == precise &&
441 (down_cast<ConstantType*>(cur_entry))->ConstantValue() == value) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700442 return *cur_entry;
443 }
444 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800445 RegType* entry;
446 if (precise) {
447 entry = new PreciseConstType(value, entries_.size());
448 } else {
449 entry = new ImpreciseConstType(value, entries_.size());
450 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800451 entries_.push_back(entry);
452 return *entry;
453}
454
455const RegType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800456 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800457 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800458 if (cur_entry->IsConstantLo() && (cur_entry->IsPrecise() == precise) &&
459 (down_cast<ConstantType*>(cur_entry))->ConstantValueLo() == value) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800460 return *cur_entry;
461 }
462 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800463 RegType* entry;
464 if (precise) {
465 entry = new PreciseConstLoType(value, entries_.size());
466 } else {
467 entry = new ImpreciseConstLoType(value, entries_.size());
468 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800469 entries_.push_back(entry);
470 return *entry;
471}
472
473const RegType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800474 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800475 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800476 if (cur_entry->IsConstantHi() && (cur_entry->IsPrecise() == precise) &&
477 (down_cast<ConstantType*>(cur_entry))->ConstantValueHi() == value) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800478 return *cur_entry;
479 }
480 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800481 RegType* entry;
482 if (precise) {
483 entry = new PreciseConstHiType(value, entries_.size());
484 } else {
485 entry = new ImpreciseConstHiType(value, entries_.size());
486 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700487 entries_.push_back(entry);
488 return *entry;
489}
490
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800491const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::ClassLoader* loader) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700492 CHECK(array.IsArrayTypes());
493 if (array.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800494 std::string descriptor(array.GetDescriptor());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700495 std::string component(descriptor.substr(1, descriptor.size() - 1));
Ian Rogersb4903572012-10-11 11:52:56 -0700496 return FromDescriptor(loader, component.c_str(), false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700497 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800498 mirror::Class* klass = array.GetClass()->GetComponentType();
Ian Rogersb4903572012-10-11 11:52:56 -0700499 return FromClass(klass, klass->IsFinal());
500 }
501}
502
503void RegTypeCache::Dump(std::ostream& os) {
Ian Rogersb4903572012-10-11 11:52:56 -0700504 for (size_t i = 0; i < entries_.size(); i++) {
505 RegType* cur_entry = entries_[i];
506 if (cur_entry != NULL) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800507 os << i << ": " << cur_entry->Dump() << "\n";
Ian Rogersb4903572012-10-11 11:52:56 -0700508 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700509 }
510}
511
Elliott Hughesa21039c2012-06-21 12:09:25 -0700512} // namespace verifier
513} // namespace art