blob: 7153768ec75e0661801214e8d852ae2fc75152d9 [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 Asal02c42232013-04-30 12:09:45 -0700182 DCHECK(!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) {
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700192 DCHECK(!(klass->IsAbstract()) || klass->IsArrayClass());
193 DCHECK(!klass->IsInterface());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800194 entry = new PreciseReferenceType(klass, descriptor, entries_.size());
195 } else {
196 entry = new ReferenceType(klass, descriptor, entries_.size());
197 }
198 entries_.push_back(entry);
199 return *entry;
200 } else { // Class not resolved.
201 // We tried loading the class and failed, this might get an exception raised
202 // so we want to clear it before we go on.
203 ClearException();
204 // Unable to resolve class. Look through unresolved types in the catch and see
205 // if we have it created before.
206 for (size_t i = primitive_count_; i < entries_.size(); i++) {
207 if (entries_[i]->IsUnresolvedReference() &&
208 entries_[i]->descriptor_ == descriptor) {
209 return *(entries_[i]);
210 }
211 }
212 if (IsValidDescriptor(descriptor.c_str())) {
213 RegType* entry = new UnresolvedReferenceType(descriptor, entries_.size());
214 entries_.push_back(entry);
215 return *entry;
216 } else {
217 // The descriptor is broken return the unknown type as there's nothing sensible that
218 // could be done at runtime
219 return Conflict();
220 }
221 }
222}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800223const RegType& RegTypeCache::FromClass(mirror::Class* klass, bool precise) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700224 if (klass->IsPrimitive()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800225 return RegTypeFromPrimitiveType(klass->GetPrimitiveType());
226
Ian Rogers776ac1f2012-04-13 23:36:36 -0700227 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800228 // Look for the reference in the list of entries to have.
229 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700230 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700231 if ((cur_entry->HasClass()) &&
232 MatchingPrecisionForClass(cur_entry, precise) && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700233 return *cur_entry;
234 }
235 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800236 // No reference to the class was found, create new reference.
237 RegType* entry;
238 std::string empty = "";
239 if (precise) {
240 entry = new PreciseReferenceType(klass, empty, entries_.size());
241 } else {
242 entry = new ReferenceType(klass, empty, entries_.size());
243 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700244 entries_.push_back(entry);
245 return *entry;
246 }
247}
248
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800249RegTypeCache::~RegTypeCache() {
250 CHECK_LE(primitive_count_, entries_.size());
251 // Delete only the non primitive types.
Ian Rogers62d6c772013-02-27 08:32:07 -0800252 if (entries_.size() == kNumPrimitives) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800253 // All entries are primitive, nothing to delete.
254 return;
255 }
256 std::vector<RegType*>::iterator non_primitive_begin = entries_.begin();
Ian Rogers62d6c772013-02-27 08:32:07 -0800257 std::advance(non_primitive_begin, kNumPrimitives);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800258 STLDeleteContainerPointers(non_primitive_begin, entries_.end());
259}
260
261void RegTypeCache::ShutDown() {
262 if (RegTypeCache::primitive_initialized_) {
263 UndefinedType::Destroy();
264 ConflictType::Destroy();
265 BooleanType::Destroy();
266 ByteType::Destroy();
267 ShortType::Destroy();
268 CharType::Destroy();
269 IntegerType::Destroy();
270 LongLoType::Destroy();
271 LongHiType::Destroy();
Ian Rogers25ae7eb2013-04-18 16:06:05 -0700272 FloatType::Destroy();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800273 DoubleLoType::Destroy();
274 DoubleHiType::Destroy();
Ian Rogers62d6c772013-02-27 08:32:07 -0800275 RegTypeCache::primitive_initialized_ = false;
276 RegTypeCache::primitive_count_ = 0;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800277 }
278}
279
280void RegTypeCache::CreatePrimitiveTypes() {
281 CreatePrimitiveTypeInstance<UndefinedType>(NULL, "");
282 CreatePrimitiveTypeInstance<ConflictType>(NULL, "");
283 CreatePrimitiveTypeInstance<BooleanType>(NULL, "Z");
284 CreatePrimitiveTypeInstance<ByteType>(NULL, "B");
285 CreatePrimitiveTypeInstance<ShortType>(NULL, "S");
286 CreatePrimitiveTypeInstance<CharType>(NULL, "C");
287 CreatePrimitiveTypeInstance<IntegerType>(NULL, "I");
288 CreatePrimitiveTypeInstance<LongLoType>(NULL, "J");
289 CreatePrimitiveTypeInstance<LongHiType>(NULL, "J");
290 CreatePrimitiveTypeInstance<FloatType>(NULL, "F");
291 CreatePrimitiveTypeInstance<DoubleLoType>(NULL, "D");
292 CreatePrimitiveTypeInstance<DoubleHiType>(NULL, "D");
293}
294
Ian Rogers529781d2012-07-23 17:24:29 -0700295const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left, const RegType& right) {
296 std::set<uint16_t> types;
297 if (left.IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800298 RegType& non_const(const_cast<RegType&>(left));
299 types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700300 } else {
301 types.insert(left.GetId());
302 }
303 if (right.IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800304 RegType& non_const(const_cast<RegType&>(right));
305 std::set<uint16_t> right_types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700306 types.insert(right_types.begin(), right_types.end());
307 } else {
308 types.insert(right.GetId());
309 }
310 // Check if entry already exists.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800311 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers529781d2012-07-23 17:24:29 -0700312 RegType* cur_entry = entries_[i];
313 if (cur_entry->IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800314 std::set<uint16_t> cur_entry_types =
315 (down_cast<UnresolvedMergedType*>(cur_entry))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700316 if (cur_entry_types == types) {
317 return *cur_entry;
318 }
319 }
320 }
321 // Create entry.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800322 RegType* entry = new UnresolvedMergedType(left.GetId(), right.GetId(), this, entries_.size());
Ian Rogers529781d2012-07-23 17:24:29 -0700323 entries_.push_back(entry);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800324#ifndef NDEBUG
325 UnresolvedMergedType* tmp_entry = down_cast<UnresolvedMergedType*>(entry);
326 std::set<uint16_t> check_types = tmp_entry->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700327 CHECK(check_types == types);
328#endif
329 return *entry;
330}
Ian Rogers529781d2012-07-23 17:24:29 -0700331const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
332 // Check if entry already exists.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800333 for (size_t i = primitive_count_; i < entries_.size(); i++) {
334 RegType* cur_entry = entries_[i];
335 if (cur_entry->IsUnresolvedSuperClass()) {
336 UnresolvedSuperClass* tmp_entry =
337 down_cast<UnresolvedSuperClass*>(cur_entry);
338 uint16_t unresolved_super_child_id =
339 tmp_entry->GetUnresolvedSuperClassChildId();
340 if (unresolved_super_child_id == child.GetId()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700341 return *cur_entry;
342 }
343 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800344 }
345 RegType* entry = new UnresolvedSuperClass(child.GetId(), this, entries_.size());
346 entries_.push_back(entry);
347 return *entry;
348}
349const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
350 RegType* entry = NULL;
351 RegType* cur_entry = NULL;
352 if (type.IsUnresolvedTypes()) {
353 std::string descriptor(type.GetDescriptor());
354 for (size_t i = primitive_count_; i < entries_.size(); i++) {
355 cur_entry = entries_[i];
356 if (cur_entry->IsUnresolvedAndUninitializedReference() &&
357 down_cast<UnresolvedUninitializedRefType*>(cur_entry)->GetAllocationPc() == allocation_pc &&
358 (cur_entry->GetDescriptor() == descriptor)) {
359 return *cur_entry;
360 }
361 }
362 entry = new UnresolvedUninitializedRefType(descriptor, allocation_pc, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700363 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800364 mirror::Class* klass = type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800365 for (size_t i = primitive_count_; i < entries_.size(); i++) {
366 cur_entry = entries_[i];
Ian Rogers776ac1f2012-04-13 23:36:36 -0700367 if (cur_entry->IsUninitializedReference() &&
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800368 down_cast<UninitialisedReferenceType*>(cur_entry)
369 ->GetAllocationPc() == allocation_pc &&
Ian Rogers776ac1f2012-04-13 23:36:36 -0700370 cur_entry->GetClass() == klass) {
371 return *cur_entry;
372 }
373 }
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700374 std::string descriptor("");
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800375 entry = new UninitialisedReferenceType(klass, descriptor, allocation_pc, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700376 }
377 entries_.push_back(entry);
378 return *entry;
379}
Ian Rogers776ac1f2012-04-13 23:36:36 -0700380const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
381 RegType* entry;
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700382
Ian Rogers776ac1f2012-04-13 23:36:36 -0700383 if (uninit_type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800384 std::string descriptor(uninit_type.GetDescriptor());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800385 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700386 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800387 if (cur_entry->IsUnresolvedReference() &&
388 cur_entry->GetDescriptor() == descriptor) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700389 return *cur_entry;
390 }
391 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800392 entry = new UnresolvedReferenceType(descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700393 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800394 mirror::Class* klass = uninit_type.GetClass();
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700395 if(uninit_type.IsUninitializedThisReference() && !klass->IsFinal()) {
396 // For uninitialized this reference look for reference types that are not precise.
397 for (size_t i = primitive_count_; i < entries_.size(); i++) {
398 RegType* cur_entry = entries_[i];
399 if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
400 return *cur_entry;
401 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700402 }
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700403 std::string descriptor("");
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700404 entry = new ReferenceType(klass, descriptor, entries_.size());
405 } else {
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700406 std::string descriptor;
407 if (klass->IsFinal()) {
408 if (klass->IsInstantiable()) {
409 for (size_t i = primitive_count_; i < entries_.size(); i++) {
410 RegType* cur_entry = entries_[i];
411 if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
412 return *cur_entry;
413 }
414 }
415 // Precise type was not found , create one !
416 entry = new PreciseReferenceType(klass, descriptor, entries_.size());
417 } else {
418 return Conflict();
419 }
420 } else {
421 // Not a final class, create an imprecise reference. Look up if we have it in the cache first.
422 for (size_t i = primitive_count_; i < entries_.size(); i++) {
423 RegType* cur_entry = entries_[i];
424 if (cur_entry->IsReference() && !(cur_entry->IsPrecise()) &&
425 cur_entry->GetClass() == klass) {
426 return *cur_entry;
427 }
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700428 }
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700429 entry = new ReferenceType(klass, descriptor, entries_.size());
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700430 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700431 }
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700432 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700433 entries_.push_back(entry);
434 return *entry;
435}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800436const RegType& RegTypeCache::ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
437 return FromCat1Const(std::numeric_limits<jbyte>::min(), false);
438}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800439const RegType& RegTypeCache::ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
440 return FromCat1Const(std::numeric_limits<jshort>::min(), false);
441}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800442const RegType& RegTypeCache::IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
443 return FromCat1Const(std::numeric_limits<jint>::max(), false);
444}
Ian Rogersad0b3a32012-04-16 14:50:24 -0700445const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700446 RegType* entry;
447 if (type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800448 std::string descriptor(type.GetDescriptor());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800449 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700450 RegType* cur_entry = entries_[i];
451 if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
452 cur_entry->GetDescriptor() == descriptor) {
453 return *cur_entry;
454 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700455 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800456 entry = new UnresolvedUninitialisedThisRefType(descriptor, entries_.size());
Ian Rogersad0b3a32012-04-16 14:50:24 -0700457 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800458 mirror::Class* klass = type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800459 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700460 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800461 if (cur_entry->IsUninitializedThisReference() &&
462 cur_entry->GetClass() == klass) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700463 return *cur_entry;
464 }
465 }
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700466 std::string descriptor("");
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800467 entry = new UninitialisedThisReferenceType(klass, descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700468 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700469 entries_.push_back(entry);
470 return *entry;
471}
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800472const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800473 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700474 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800475 if (cur_entry->IsConstant() && cur_entry->IsPreciseConstant() == precise &&
476 (down_cast<ConstantType*>(cur_entry))->ConstantValue() == value) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700477 return *cur_entry;
478 }
479 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800480 RegType* entry;
481 if (precise) {
482 entry = new PreciseConstType(value, entries_.size());
483 } else {
484 entry = new ImpreciseConstType(value, entries_.size());
485 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800486 entries_.push_back(entry);
487 return *entry;
488}
489
490const RegType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800491 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800492 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800493 if (cur_entry->IsConstantLo() && (cur_entry->IsPrecise() == precise) &&
494 (down_cast<ConstantType*>(cur_entry))->ConstantValueLo() == value) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800495 return *cur_entry;
496 }
497 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800498 RegType* entry;
499 if (precise) {
500 entry = new PreciseConstLoType(value, entries_.size());
501 } else {
502 entry = new ImpreciseConstLoType(value, entries_.size());
503 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800504 entries_.push_back(entry);
505 return *entry;
506}
507
508const RegType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800509 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800510 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800511 if (cur_entry->IsConstantHi() && (cur_entry->IsPrecise() == precise) &&
512 (down_cast<ConstantType*>(cur_entry))->ConstantValueHi() == value) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800513 return *cur_entry;
514 }
515 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800516 RegType* entry;
517 if (precise) {
518 entry = new PreciseConstHiType(value, entries_.size());
519 } else {
520 entry = new ImpreciseConstHiType(value, entries_.size());
521 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700522 entries_.push_back(entry);
523 return *entry;
524}
525
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800526const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::ClassLoader* loader) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700527 CHECK(array.IsArrayTypes());
528 if (array.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800529 std::string descriptor(array.GetDescriptor());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700530 std::string component(descriptor.substr(1, descriptor.size() - 1));
Ian Rogersb4903572012-10-11 11:52:56 -0700531 return FromDescriptor(loader, component.c_str(), false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700532 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800533 mirror::Class* klass = array.GetClass()->GetComponentType();
Ian Rogersb4903572012-10-11 11:52:56 -0700534 return FromClass(klass, klass->IsFinal());
535 }
536}
537
538void RegTypeCache::Dump(std::ostream& os) {
Ian Rogersb4903572012-10-11 11:52:56 -0700539 for (size_t i = 0; i < entries_.size(); i++) {
540 RegType* cur_entry = entries_[i];
541 if (cur_entry != NULL) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800542 os << i << ": " << cur_entry->Dump() << "\n";
Ian Rogersb4903572012-10-11 11:52:56 -0700543 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700544 }
545}
546
Elliott Hughesa21039c2012-06-21 12:09:25 -0700547} // namespace verifier
548} // namespace art