blob: 8e23b743f0a49d44d4f71fdf1346f1610477de94 [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);
Ian Rogers62d6c772013-02-27 08:32:07 -0800151 if (klass != NULL && !klass->IsLoaded()) {
152 // We found the class but without it being loaded its not safe for use.
153 klass = NULL;
154 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800155 }
156 return klass;
157}
158void RegTypeCache::ClearException() {
159 if (can_load_classes_) {
160 DCHECK(Thread::Current()->IsExceptionPending());
161 Thread::Current()->ClearException();
162 } else {
163 DCHECK(!Thread::Current()->IsExceptionPending());
164 }
165}
166const RegType& RegTypeCache::From(mirror::ClassLoader* loader, std::string descriptor, bool precise) {
167 // Try resolving class.
168 mirror::Class* klass = ResolveClass(descriptor, loader);
169 if (klass != NULL) {
170 // Class resolved, first look for the class in the list of entries
171 for (size_t i = primitive_count_; i < entries_.size(); i++) {
172 if (entries_[i]->HasClass()) {
173 if (MatchDescriptor(i, descriptor, precise)) {
174 return *(entries_[i]);
175 }
176 }
177 }
178 // Class was not found, must create new type.
179
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700180 //To pass the verification, the type should be imprecise,
181 // instantiable or an interface with the precise type set to false.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800182 CHECK(!precise || klass->IsInstantiable());
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700183
184 // Create a precise type if:
185 // 1- Class is final and NOT an interface. a precise interface
186 // is meaningless !!
187 // 2- Precise Flag passed as true.
188
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800189 RegType* entry;
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700190 // Create an imprecise type if we can't tell for a fact that it is precise.
191 if ((klass->IsFinal()) || precise) {
192 CHECK(!(klass->IsAbstract()) || klass->IsArrayClass());
193 CHECK(!klass->IsInterface());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800194 entry = new PreciseReferenceType(klass, descriptor, entries_.size());
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700195
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800196 } else {
197 entry = new ReferenceType(klass, descriptor, entries_.size());
198 }
199 entries_.push_back(entry);
200 return *entry;
201 } else { // Class not resolved.
202 // We tried loading the class and failed, this might get an exception raised
203 // so we want to clear it before we go on.
204 ClearException();
205 // Unable to resolve class. Look through unresolved types in the catch and see
206 // if we have it created before.
207 for (size_t i = primitive_count_; i < entries_.size(); i++) {
208 if (entries_[i]->IsUnresolvedReference() &&
209 entries_[i]->descriptor_ == descriptor) {
210 return *(entries_[i]);
211 }
212 }
213 if (IsValidDescriptor(descriptor.c_str())) {
214 RegType* entry = new UnresolvedReferenceType(descriptor, entries_.size());
215 entries_.push_back(entry);
216 return *entry;
217 } else {
218 // The descriptor is broken return the unknown type as there's nothing sensible that
219 // could be done at runtime
220 return Conflict();
221 }
222 }
223}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800224const RegType& RegTypeCache::FromClass(mirror::Class* klass, bool precise) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700225 if (klass->IsPrimitive()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800226 return RegTypeFromPrimitiveType(klass->GetPrimitiveType());
227
Ian Rogers776ac1f2012-04-13 23:36:36 -0700228 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800229 // Look for the reference in the list of entries to have.
230 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700231 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700232 if ((cur_entry->HasClass()) &&
233 MatchingPrecisionForClass(cur_entry, precise) && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700234 return *cur_entry;
235 }
236 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800237 // No reference to the class was found, create new reference.
238 RegType* entry;
239 std::string empty = "";
240 if (precise) {
241 entry = new PreciseReferenceType(klass, empty, entries_.size());
242 } else {
243 entry = new ReferenceType(klass, empty, entries_.size());
244 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700245 entries_.push_back(entry);
246 return *entry;
247 }
248}
249
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800250RegTypeCache::~RegTypeCache() {
251 CHECK_LE(primitive_count_, entries_.size());
252 // Delete only the non primitive types.
Ian Rogers62d6c772013-02-27 08:32:07 -0800253 if (entries_.size() == kNumPrimitives) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800254 // All entries are primitive, nothing to delete.
255 return;
256 }
257 std::vector<RegType*>::iterator non_primitive_begin = entries_.begin();
Ian Rogers62d6c772013-02-27 08:32:07 -0800258 std::advance(non_primitive_begin, kNumPrimitives);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800259 STLDeleteContainerPointers(non_primitive_begin, entries_.end());
260}
261
262void RegTypeCache::ShutDown() {
263 if (RegTypeCache::primitive_initialized_) {
264 UndefinedType::Destroy();
265 ConflictType::Destroy();
266 BooleanType::Destroy();
267 ByteType::Destroy();
268 ShortType::Destroy();
269 CharType::Destroy();
270 IntegerType::Destroy();
271 LongLoType::Destroy();
272 LongHiType::Destroy();
Ian Rogers25ae7eb2013-04-18 16:06:05 -0700273 FloatType::Destroy();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800274 DoubleLoType::Destroy();
275 DoubleHiType::Destroy();
Ian Rogers62d6c772013-02-27 08:32:07 -0800276 RegTypeCache::primitive_initialized_ = false;
277 RegTypeCache::primitive_count_ = 0;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800278 }
279}
280
281void RegTypeCache::CreatePrimitiveTypes() {
282 CreatePrimitiveTypeInstance<UndefinedType>(NULL, "");
283 CreatePrimitiveTypeInstance<ConflictType>(NULL, "");
284 CreatePrimitiveTypeInstance<BooleanType>(NULL, "Z");
285 CreatePrimitiveTypeInstance<ByteType>(NULL, "B");
286 CreatePrimitiveTypeInstance<ShortType>(NULL, "S");
287 CreatePrimitiveTypeInstance<CharType>(NULL, "C");
288 CreatePrimitiveTypeInstance<IntegerType>(NULL, "I");
289 CreatePrimitiveTypeInstance<LongLoType>(NULL, "J");
290 CreatePrimitiveTypeInstance<LongHiType>(NULL, "J");
291 CreatePrimitiveTypeInstance<FloatType>(NULL, "F");
292 CreatePrimitiveTypeInstance<DoubleLoType>(NULL, "D");
293 CreatePrimitiveTypeInstance<DoubleHiType>(NULL, "D");
294}
295
Ian Rogers529781d2012-07-23 17:24:29 -0700296const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left, const RegType& right) {
297 std::set<uint16_t> types;
298 if (left.IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800299 RegType& non_const(const_cast<RegType&>(left));
300 types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700301 } else {
302 types.insert(left.GetId());
303 }
304 if (right.IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800305 RegType& non_const(const_cast<RegType&>(right));
306 std::set<uint16_t> right_types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700307 types.insert(right_types.begin(), right_types.end());
308 } else {
309 types.insert(right.GetId());
310 }
311 // Check if entry already exists.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800312 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers529781d2012-07-23 17:24:29 -0700313 RegType* cur_entry = entries_[i];
314 if (cur_entry->IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800315 std::set<uint16_t> cur_entry_types =
316 (down_cast<UnresolvedMergedType*>(cur_entry))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700317 if (cur_entry_types == types) {
318 return *cur_entry;
319 }
320 }
321 }
322 // Create entry.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800323 RegType* entry = new UnresolvedMergedType(left.GetId(), right.GetId(), this, entries_.size());
Ian Rogers529781d2012-07-23 17:24:29 -0700324 entries_.push_back(entry);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800325#ifndef NDEBUG
326 UnresolvedMergedType* tmp_entry = down_cast<UnresolvedMergedType*>(entry);
327 std::set<uint16_t> check_types = tmp_entry->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700328 CHECK(check_types == types);
329#endif
330 return *entry;
331}
Ian Rogers529781d2012-07-23 17:24:29 -0700332const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
333 // Check if entry already exists.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800334 for (size_t i = primitive_count_; i < entries_.size(); i++) {
335 RegType* cur_entry = entries_[i];
336 if (cur_entry->IsUnresolvedSuperClass()) {
337 UnresolvedSuperClass* tmp_entry =
338 down_cast<UnresolvedSuperClass*>(cur_entry);
339 uint16_t unresolved_super_child_id =
340 tmp_entry->GetUnresolvedSuperClassChildId();
341 if (unresolved_super_child_id == child.GetId()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700342 return *cur_entry;
343 }
344 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800345 }
346 RegType* entry = new UnresolvedSuperClass(child.GetId(), this, entries_.size());
347 entries_.push_back(entry);
348 return *entry;
349}
350const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
351 RegType* entry = NULL;
352 RegType* cur_entry = NULL;
353 if (type.IsUnresolvedTypes()) {
354 std::string descriptor(type.GetDescriptor());
355 for (size_t i = primitive_count_; i < entries_.size(); i++) {
356 cur_entry = entries_[i];
357 if (cur_entry->IsUnresolvedAndUninitializedReference() &&
358 down_cast<UnresolvedUninitializedRefType*>(cur_entry)->GetAllocationPc() == allocation_pc &&
359 (cur_entry->GetDescriptor() == descriptor)) {
360 return *cur_entry;
361 }
362 }
363 entry = new UnresolvedUninitializedRefType(descriptor, allocation_pc, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700364 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800365 mirror::Class* klass = type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800366 for (size_t i = primitive_count_; i < entries_.size(); i++) {
367 cur_entry = entries_[i];
Ian Rogers776ac1f2012-04-13 23:36:36 -0700368 if (cur_entry->IsUninitializedReference() &&
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800369 down_cast<UninitialisedReferenceType*>(cur_entry)
370 ->GetAllocationPc() == allocation_pc &&
Ian Rogers776ac1f2012-04-13 23:36:36 -0700371 cur_entry->GetClass() == klass) {
372 return *cur_entry;
373 }
374 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800375 std::string descriptor = "";
376 entry = new UninitialisedReferenceType(klass, descriptor, allocation_pc, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700377 }
378 entries_.push_back(entry);
379 return *entry;
380}
Ian Rogers776ac1f2012-04-13 23:36:36 -0700381const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
382 RegType* entry;
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700383
Ian Rogers776ac1f2012-04-13 23:36:36 -0700384 if (uninit_type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800385 std::string descriptor(uninit_type.GetDescriptor());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800386 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700387 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800388 if (cur_entry->IsUnresolvedReference() &&
389 cur_entry->GetDescriptor() == descriptor) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700390 return *cur_entry;
391 }
392 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800393 entry = new UnresolvedReferenceType(descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700394 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800395 mirror::Class* klass = uninit_type.GetClass();
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700396 if(uninit_type.IsUninitializedThisReference() && !klass->IsFinal()) {
397 // For uninitialized this reference look for reference types that are not precise.
398 for (size_t i = primitive_count_; i < entries_.size(); i++) {
399 RegType* cur_entry = entries_[i];
400 if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
401 return *cur_entry;
402 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700403 }
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700404 std::string descriptor = "";
405 entry = new ReferenceType(klass, descriptor, entries_.size());
406 } else {
407 for (size_t i = primitive_count_; i < entries_.size(); i++) {
408 RegType* cur_entry = entries_[i];
409 if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
410 return *cur_entry;
411 }
412 }
413 std::string descriptor = "";
414 entry = new PreciseReferenceType(klass, descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700415 }
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700416 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700417 entries_.push_back(entry);
418 return *entry;
419}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800420const RegType& RegTypeCache::ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
421 return FromCat1Const(std::numeric_limits<jbyte>::min(), false);
422}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800423const RegType& RegTypeCache::ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
424 return FromCat1Const(std::numeric_limits<jshort>::min(), false);
425}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800426const RegType& RegTypeCache::IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
427 return FromCat1Const(std::numeric_limits<jint>::max(), false);
428}
Ian Rogersad0b3a32012-04-16 14:50:24 -0700429const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700430 RegType* entry;
431 if (type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800432 std::string descriptor(type.GetDescriptor());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800433 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700434 RegType* cur_entry = entries_[i];
435 if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
436 cur_entry->GetDescriptor() == descriptor) {
437 return *cur_entry;
438 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700439 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800440 entry = new UnresolvedUninitialisedThisRefType(descriptor, entries_.size());
Ian Rogersad0b3a32012-04-16 14:50:24 -0700441 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800442 mirror::Class* klass = type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800443 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700444 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800445 if (cur_entry->IsUninitializedThisReference() &&
446 cur_entry->GetClass() == klass) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700447 return *cur_entry;
448 }
449 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800450 std::string descriptor = "";
451 entry = new UninitialisedThisReferenceType(klass, descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700452 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700453 entries_.push_back(entry);
454 return *entry;
455}
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800456const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800457 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700458 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800459 if (cur_entry->IsConstant() && cur_entry->IsPreciseConstant() == precise &&
460 (down_cast<ConstantType*>(cur_entry))->ConstantValue() == value) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700461 return *cur_entry;
462 }
463 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800464 RegType* entry;
465 if (precise) {
466 entry = new PreciseConstType(value, entries_.size());
467 } else {
468 entry = new ImpreciseConstType(value, entries_.size());
469 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800470 entries_.push_back(entry);
471 return *entry;
472}
473
474const RegType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800475 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800476 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800477 if (cur_entry->IsConstantLo() && (cur_entry->IsPrecise() == precise) &&
478 (down_cast<ConstantType*>(cur_entry))->ConstantValueLo() == value) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800479 return *cur_entry;
480 }
481 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800482 RegType* entry;
483 if (precise) {
484 entry = new PreciseConstLoType(value, entries_.size());
485 } else {
486 entry = new ImpreciseConstLoType(value, entries_.size());
487 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800488 entries_.push_back(entry);
489 return *entry;
490}
491
492const RegType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800493 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800494 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800495 if (cur_entry->IsConstantHi() && (cur_entry->IsPrecise() == precise) &&
496 (down_cast<ConstantType*>(cur_entry))->ConstantValueHi() == value) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800497 return *cur_entry;
498 }
499 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800500 RegType* entry;
501 if (precise) {
502 entry = new PreciseConstHiType(value, entries_.size());
503 } else {
504 entry = new ImpreciseConstHiType(value, entries_.size());
505 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700506 entries_.push_back(entry);
507 return *entry;
508}
509
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800510const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::ClassLoader* loader) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700511 CHECK(array.IsArrayTypes());
512 if (array.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800513 std::string descriptor(array.GetDescriptor());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700514 std::string component(descriptor.substr(1, descriptor.size() - 1));
Ian Rogersb4903572012-10-11 11:52:56 -0700515 return FromDescriptor(loader, component.c_str(), false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700516 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800517 mirror::Class* klass = array.GetClass()->GetComponentType();
Ian Rogersb4903572012-10-11 11:52:56 -0700518 return FromClass(klass, klass->IsFinal());
519 }
520}
521
522void RegTypeCache::Dump(std::ostream& os) {
Ian Rogersb4903572012-10-11 11:52:56 -0700523 for (size_t i = 0; i < entries_.size(); i++) {
524 RegType* cur_entry = entries_[i];
525 if (cur_entry != NULL) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800526 os << i << ": " << cur_entry->Dump() << "\n";
Ian Rogersb4903572012-10-11 11:52:56 -0700527 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700528 }
529}
530
Elliott Hughesa21039c2012-06-21 12:09:25 -0700531} // namespace verifier
532} // namespace art