blob: 6228ba51e0b2474f8887d65688b985940a248eaf [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
180 // Create a type if:
181 // 1-The class is instantiable ( not Abstract or Interface ), we should
182 // abort failing the verification if we get that.
183 // 2- And, the class should be instantiable (Not interface, Abstract or a
184 // primitive type) OR it is imprecise.
185
186 // Create a precise type if :
187 // 1-The class is final.
188 // 2-OR the precise was passed as true .
189 CHECK(!precise || klass->IsInstantiable());
190 RegType* entry;
191 // Create an imprecise type if we can'tt tell for a fact that it is precise.
192 if (klass->IsFinal() || precise) {
193 entry = new PreciseReferenceType(klass, descriptor, entries_.size());
194 } else {
195 entry = new ReferenceType(klass, descriptor, entries_.size());
196 }
197 entries_.push_back(entry);
198 return *entry;
199 } else { // Class not resolved.
200 // We tried loading the class and failed, this might get an exception raised
201 // so we want to clear it before we go on.
202 ClearException();
203 // Unable to resolve class. Look through unresolved types in the catch and see
204 // if we have it created before.
205 for (size_t i = primitive_count_; i < entries_.size(); i++) {
206 if (entries_[i]->IsUnresolvedReference() &&
207 entries_[i]->descriptor_ == descriptor) {
208 return *(entries_[i]);
209 }
210 }
211 if (IsValidDescriptor(descriptor.c_str())) {
212 RegType* entry = new UnresolvedReferenceType(descriptor, entries_.size());
213 entries_.push_back(entry);
214 return *entry;
215 } else {
216 // The descriptor is broken return the unknown type as there's nothing sensible that
217 // could be done at runtime
218 return Conflict();
219 }
220 }
221}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800222const RegType& RegTypeCache::FromClass(mirror::Class* klass, bool precise) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700223 if (klass->IsPrimitive()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800224 return RegTypeFromPrimitiveType(klass->GetPrimitiveType());
225
Ian Rogers776ac1f2012-04-13 23:36:36 -0700226 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800227 // Look for the reference in the list of entries to have.
228 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700229 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700230 if ((cur_entry->HasClass()) &&
231 MatchingPrecisionForClass(cur_entry, precise) && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700232 return *cur_entry;
233 }
234 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800235 // No reference to the class was found, create new reference.
236 RegType* entry;
237 std::string empty = "";
238 if (precise) {
239 entry = new PreciseReferenceType(klass, empty, entries_.size());
240 } else {
241 entry = new ReferenceType(klass, empty, entries_.size());
242 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700243 entries_.push_back(entry);
244 return *entry;
245 }
246}
247
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800248RegTypeCache::~RegTypeCache() {
249 CHECK_LE(primitive_count_, entries_.size());
250 // Delete only the non primitive types.
Ian Rogers62d6c772013-02-27 08:32:07 -0800251 if (entries_.size() == kNumPrimitives) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800252 // All entries are primitive, nothing to delete.
253 return;
254 }
255 std::vector<RegType*>::iterator non_primitive_begin = entries_.begin();
Ian Rogers62d6c772013-02-27 08:32:07 -0800256 std::advance(non_primitive_begin, kNumPrimitives);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800257 STLDeleteContainerPointers(non_primitive_begin, entries_.end());
258}
259
260void RegTypeCache::ShutDown() {
261 if (RegTypeCache::primitive_initialized_) {
262 UndefinedType::Destroy();
263 ConflictType::Destroy();
264 BooleanType::Destroy();
265 ByteType::Destroy();
266 ShortType::Destroy();
267 CharType::Destroy();
268 IntegerType::Destroy();
269 LongLoType::Destroy();
270 LongHiType::Destroy();
271 FloatType::GetInstance();
272 DoubleLoType::Destroy();
273 DoubleHiType::Destroy();
Ian Rogers62d6c772013-02-27 08:32:07 -0800274 RegTypeCache::primitive_initialized_ = false;
275 RegTypeCache::primitive_count_ = 0;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800276 }
277}
278
279void RegTypeCache::CreatePrimitiveTypes() {
280 CreatePrimitiveTypeInstance<UndefinedType>(NULL, "");
281 CreatePrimitiveTypeInstance<ConflictType>(NULL, "");
282 CreatePrimitiveTypeInstance<BooleanType>(NULL, "Z");
283 CreatePrimitiveTypeInstance<ByteType>(NULL, "B");
284 CreatePrimitiveTypeInstance<ShortType>(NULL, "S");
285 CreatePrimitiveTypeInstance<CharType>(NULL, "C");
286 CreatePrimitiveTypeInstance<IntegerType>(NULL, "I");
287 CreatePrimitiveTypeInstance<LongLoType>(NULL, "J");
288 CreatePrimitiveTypeInstance<LongHiType>(NULL, "J");
289 CreatePrimitiveTypeInstance<FloatType>(NULL, "F");
290 CreatePrimitiveTypeInstance<DoubleLoType>(NULL, "D");
291 CreatePrimitiveTypeInstance<DoubleHiType>(NULL, "D");
292}
293
Ian Rogers529781d2012-07-23 17:24:29 -0700294const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left, const RegType& right) {
295 std::set<uint16_t> types;
296 if (left.IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800297 RegType& non_const(const_cast<RegType&>(left));
298 types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700299 } else {
300 types.insert(left.GetId());
301 }
302 if (right.IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800303 RegType& non_const(const_cast<RegType&>(right));
304 std::set<uint16_t> right_types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700305 types.insert(right_types.begin(), right_types.end());
306 } else {
307 types.insert(right.GetId());
308 }
309 // Check if entry already exists.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800310 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers529781d2012-07-23 17:24:29 -0700311 RegType* cur_entry = entries_[i];
312 if (cur_entry->IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800313 std::set<uint16_t> cur_entry_types =
314 (down_cast<UnresolvedMergedType*>(cur_entry))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700315 if (cur_entry_types == types) {
316 return *cur_entry;
317 }
318 }
319 }
320 // Create entry.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800321 RegType* entry = new UnresolvedMergedType(left.GetId(), right.GetId(), this, entries_.size());
Ian Rogers529781d2012-07-23 17:24:29 -0700322 entries_.push_back(entry);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800323#ifndef NDEBUG
324 UnresolvedMergedType* tmp_entry = down_cast<UnresolvedMergedType*>(entry);
325 std::set<uint16_t> check_types = tmp_entry->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700326 CHECK(check_types == types);
327#endif
328 return *entry;
329}
Ian Rogers529781d2012-07-23 17:24:29 -0700330const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
331 // Check if entry already exists.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800332 for (size_t i = primitive_count_; i < entries_.size(); i++) {
333 RegType* cur_entry = entries_[i];
334 if (cur_entry->IsUnresolvedSuperClass()) {
335 UnresolvedSuperClass* tmp_entry =
336 down_cast<UnresolvedSuperClass*>(cur_entry);
337 uint16_t unresolved_super_child_id =
338 tmp_entry->GetUnresolvedSuperClassChildId();
339 if (unresolved_super_child_id == child.GetId()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700340 return *cur_entry;
341 }
342 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800343 }
344 RegType* entry = new UnresolvedSuperClass(child.GetId(), this, entries_.size());
345 entries_.push_back(entry);
346 return *entry;
347}
348const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
349 RegType* entry = NULL;
350 RegType* cur_entry = NULL;
351 if (type.IsUnresolvedTypes()) {
352 std::string descriptor(type.GetDescriptor());
353 for (size_t i = primitive_count_; i < entries_.size(); i++) {
354 cur_entry = entries_[i];
355 if (cur_entry->IsUnresolvedAndUninitializedReference() &&
356 down_cast<UnresolvedUninitializedRefType*>(cur_entry)->GetAllocationPc() == allocation_pc &&
357 (cur_entry->GetDescriptor() == descriptor)) {
358 return *cur_entry;
359 }
360 }
361 entry = new UnresolvedUninitializedRefType(descriptor, allocation_pc, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700362 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800363 mirror::Class* klass = type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800364 for (size_t i = primitive_count_; i < entries_.size(); i++) {
365 cur_entry = entries_[i];
Ian Rogers776ac1f2012-04-13 23:36:36 -0700366 if (cur_entry->IsUninitializedReference() &&
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800367 down_cast<UninitialisedReferenceType*>(cur_entry)
368 ->GetAllocationPc() == allocation_pc &&
Ian Rogers776ac1f2012-04-13 23:36:36 -0700369 cur_entry->GetClass() == klass) {
370 return *cur_entry;
371 }
372 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800373 std::string descriptor = "";
374 entry = new UninitialisedReferenceType(klass, descriptor, allocation_pc, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700375 }
376 entries_.push_back(entry);
377 return *entry;
378}
Ian Rogers776ac1f2012-04-13 23:36:36 -0700379const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
380 RegType* entry;
381 if (uninit_type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800382 std::string descriptor(uninit_type.GetDescriptor());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800383 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700384 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800385 if (cur_entry->IsUnresolvedReference() &&
386 cur_entry->GetDescriptor() == descriptor) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700387 return *cur_entry;
388 }
389 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800390 entry = new UnresolvedReferenceType(descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700391 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800392 mirror::Class* klass = uninit_type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800393 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700394 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700395 if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700396 return *cur_entry;
397 }
398 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800399 std::string descriptor = "";
400 entry = new PreciseReferenceType(klass, descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700401 }
402 entries_.push_back(entry);
403 return *entry;
404}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800405const RegType& RegTypeCache::ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
406 return FromCat1Const(std::numeric_limits<jbyte>::min(), false);
407}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800408const RegType& RegTypeCache::ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
409 return FromCat1Const(std::numeric_limits<jshort>::min(), false);
410}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800411const RegType& RegTypeCache::IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
412 return FromCat1Const(std::numeric_limits<jint>::max(), false);
413}
Ian Rogersad0b3a32012-04-16 14:50:24 -0700414const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700415 RegType* entry;
416 if (type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800417 std::string descriptor(type.GetDescriptor());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800418 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700419 RegType* cur_entry = entries_[i];
420 if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
421 cur_entry->GetDescriptor() == descriptor) {
422 return *cur_entry;
423 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700424 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800425 entry = new UnresolvedUninitialisedThisRefType(descriptor, entries_.size());
Ian Rogersad0b3a32012-04-16 14:50:24 -0700426 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800427 mirror::Class* klass = type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800428 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700429 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800430 if (cur_entry->IsUninitializedThisReference() &&
431 cur_entry->GetClass() == klass) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700432 return *cur_entry;
433 }
434 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800435 std::string descriptor = "";
436 entry = new UninitialisedThisReferenceType(klass, descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700437 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700438 entries_.push_back(entry);
439 return *entry;
440}
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800441const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800442 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700443 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800444 if (cur_entry->IsConstant() && cur_entry->IsPreciseConstant() == precise &&
445 (down_cast<ConstantType*>(cur_entry))->ConstantValue() == value) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700446 return *cur_entry;
447 }
448 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800449 RegType* entry;
450 if (precise) {
451 entry = new PreciseConstType(value, entries_.size());
452 } else {
453 entry = new ImpreciseConstType(value, entries_.size());
454 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800455 entries_.push_back(entry);
456 return *entry;
457}
458
459const RegType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800460 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800461 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800462 if (cur_entry->IsConstantLo() && (cur_entry->IsPrecise() == precise) &&
463 (down_cast<ConstantType*>(cur_entry))->ConstantValueLo() == value) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800464 return *cur_entry;
465 }
466 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800467 RegType* entry;
468 if (precise) {
469 entry = new PreciseConstLoType(value, entries_.size());
470 } else {
471 entry = new ImpreciseConstLoType(value, entries_.size());
472 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800473 entries_.push_back(entry);
474 return *entry;
475}
476
477const RegType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800478 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800479 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800480 if (cur_entry->IsConstantHi() && (cur_entry->IsPrecise() == precise) &&
481 (down_cast<ConstantType*>(cur_entry))->ConstantValueHi() == value) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800482 return *cur_entry;
483 }
484 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800485 RegType* entry;
486 if (precise) {
487 entry = new PreciseConstHiType(value, entries_.size());
488 } else {
489 entry = new ImpreciseConstHiType(value, entries_.size());
490 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700491 entries_.push_back(entry);
492 return *entry;
493}
494
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800495const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::ClassLoader* loader) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700496 CHECK(array.IsArrayTypes());
497 if (array.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800498 std::string descriptor(array.GetDescriptor());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700499 std::string component(descriptor.substr(1, descriptor.size() - 1));
Ian Rogersb4903572012-10-11 11:52:56 -0700500 return FromDescriptor(loader, component.c_str(), false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700501 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800502 mirror::Class* klass = array.GetClass()->GetComponentType();
Ian Rogersb4903572012-10-11 11:52:56 -0700503 return FromClass(klass, klass->IsFinal());
504 }
505}
506
507void RegTypeCache::Dump(std::ostream& os) {
Ian Rogersb4903572012-10-11 11:52:56 -0700508 for (size_t i = 0; i < entries_.size(); i++) {
509 RegType* cur_entry = entries_[i];
510 if (cur_entry != NULL) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800511 os << i << ": " << cur_entry->Dump() << "\n";
Ian Rogersb4903572012-10-11 11:52:56 -0700512 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700513 }
514}
515
Elliott Hughesa21039c2012-06-21 12:09:25 -0700516} // namespace verifier
517} // namespace art