blob: aac7e37403cd854299d06807f28fd699d73dcabf [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) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800117 RegType* cur_entry = entries_[idx];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800118 if (cur_entry->HasClass()) {
Sameer Abu Asal2c6de222013-05-02 17:38:59 -0700119 // Check the descriptor in the reg_type if available.
120 if(!cur_entry->descriptor_.empty()) {
121 if (descriptor == cur_entry->descriptor_ && MatchingPrecisionForClass(cur_entry, precise)) {
122 return true;
123 }
124 } else {
125 // Descriptor not found in reg_type , maybe available in Class object.
126 // So we might have cases where we have the class but not the descriptor
127 // for that class we need the class helper to get the descriptor
128 // and match it with the one we are given.
129 ClassHelper kh(cur_entry->GetClass());
130 if ((strcmp(descriptor.c_str(), kh.GetDescriptor()) == 0) &&
131 MatchingPrecisionForClass(cur_entry, precise)) {
132 return true;
133 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800134 }
135 } else if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
136 return true;
137 }
138 return false;
139}
140
Sameer Abu Asal2c6de222013-05-02 17:38:59 -0700141
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800142mirror::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) {
Sameer Abu Asal2c6de222013-05-02 17:38:59 -0700167
168 // Try looking up the class in the cache first.
169 for (size_t i = primitive_count_; i < entries_.size(); i++) {
170 if (MatchDescriptor(i, descriptor, precise)) {
171 return *(entries_[i]);
172 }
173 }
174 // Class not found in the cache, will create a new type for that.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800175 // Try resolving class.
176 mirror::Class* klass = ResolveClass(descriptor, loader);
177 if (klass != NULL) {
178 // Class resolved, first look for the class in the list of entries
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800179 // Class was not found, must create new type.
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 // Create a precise type if:
Sameer Abu Asal2c6de222013-05-02 17:38:59 -0700184 // 1- Class is final and NOT an interface. a precise interface is meaningless !!
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700185 // 2- Precise Flag passed as true.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800186 RegType* entry;
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700187 // Create an imprecise type if we can't tell for a fact that it is precise.
188 if ((klass->IsFinal()) || precise) {
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700189 DCHECK(!(klass->IsAbstract()) || klass->IsArrayClass());
190 DCHECK(!klass->IsInterface());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800191 entry = new PreciseReferenceType(klass, descriptor, entries_.size());
192 } else {
193 entry = new ReferenceType(klass, descriptor, entries_.size());
194 }
195 entries_.push_back(entry);
196 return *entry;
197 } else { // Class not resolved.
198 // We tried loading the class and failed, this might get an exception raised
199 // so we want to clear it before we go on.
200 ClearException();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800201 if (IsValidDescriptor(descriptor.c_str())) {
202 RegType* entry = new UnresolvedReferenceType(descriptor, entries_.size());
203 entries_.push_back(entry);
204 return *entry;
205 } else {
206 // The descriptor is broken return the unknown type as there's nothing sensible that
207 // could be done at runtime
208 return Conflict();
209 }
210 }
211}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800212const RegType& RegTypeCache::FromClass(mirror::Class* klass, bool precise) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700213 if (klass->IsPrimitive()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800214 return RegTypeFromPrimitiveType(klass->GetPrimitiveType());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700215 } else {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800216 // Look for the reference in the list of entries to have.
217 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700218 RegType* cur_entry = entries_[i];
Sameer Abu Asal2c6de222013-05-02 17:38:59 -0700219 if ((cur_entry->HasClass()) && cur_entry->GetClass() == klass &&
220 MatchingPrecisionForClass(cur_entry, precise)) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700221 return *cur_entry;
222 }
223 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800224 // No reference to the class was found, create new reference.
225 RegType* entry;
226 std::string empty = "";
227 if (precise) {
228 entry = new PreciseReferenceType(klass, empty, entries_.size());
229 } else {
230 entry = new ReferenceType(klass, empty, entries_.size());
231 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700232 entries_.push_back(entry);
233 return *entry;
234 }
235}
236
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800237RegTypeCache::~RegTypeCache() {
238 CHECK_LE(primitive_count_, entries_.size());
239 // Delete only the non primitive types.
Ian Rogers62d6c772013-02-27 08:32:07 -0800240 if (entries_.size() == kNumPrimitives) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800241 // All entries are primitive, nothing to delete.
242 return;
243 }
244 std::vector<RegType*>::iterator non_primitive_begin = entries_.begin();
Ian Rogers62d6c772013-02-27 08:32:07 -0800245 std::advance(non_primitive_begin, kNumPrimitives);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800246 STLDeleteContainerPointers(non_primitive_begin, entries_.end());
247}
248
249void RegTypeCache::ShutDown() {
250 if (RegTypeCache::primitive_initialized_) {
251 UndefinedType::Destroy();
252 ConflictType::Destroy();
253 BooleanType::Destroy();
254 ByteType::Destroy();
255 ShortType::Destroy();
256 CharType::Destroy();
257 IntegerType::Destroy();
258 LongLoType::Destroy();
259 LongHiType::Destroy();
Ian Rogers25ae7eb2013-04-18 16:06:05 -0700260 FloatType::Destroy();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800261 DoubleLoType::Destroy();
262 DoubleHiType::Destroy();
Ian Rogers62d6c772013-02-27 08:32:07 -0800263 RegTypeCache::primitive_initialized_ = false;
264 RegTypeCache::primitive_count_ = 0;
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800265 }
266}
267
268void RegTypeCache::CreatePrimitiveTypes() {
269 CreatePrimitiveTypeInstance<UndefinedType>(NULL, "");
270 CreatePrimitiveTypeInstance<ConflictType>(NULL, "");
271 CreatePrimitiveTypeInstance<BooleanType>(NULL, "Z");
272 CreatePrimitiveTypeInstance<ByteType>(NULL, "B");
273 CreatePrimitiveTypeInstance<ShortType>(NULL, "S");
274 CreatePrimitiveTypeInstance<CharType>(NULL, "C");
275 CreatePrimitiveTypeInstance<IntegerType>(NULL, "I");
276 CreatePrimitiveTypeInstance<LongLoType>(NULL, "J");
277 CreatePrimitiveTypeInstance<LongHiType>(NULL, "J");
278 CreatePrimitiveTypeInstance<FloatType>(NULL, "F");
279 CreatePrimitiveTypeInstance<DoubleLoType>(NULL, "D");
280 CreatePrimitiveTypeInstance<DoubleHiType>(NULL, "D");
281}
282
Ian Rogers529781d2012-07-23 17:24:29 -0700283const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left, const RegType& right) {
284 std::set<uint16_t> types;
285 if (left.IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800286 RegType& non_const(const_cast<RegType&>(left));
287 types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700288 } else {
289 types.insert(left.GetId());
290 }
291 if (right.IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800292 RegType& non_const(const_cast<RegType&>(right));
293 std::set<uint16_t> right_types = (down_cast<UnresolvedMergedType*>(&non_const))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700294 types.insert(right_types.begin(), right_types.end());
295 } else {
296 types.insert(right.GetId());
297 }
298 // Check if entry already exists.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800299 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers529781d2012-07-23 17:24:29 -0700300 RegType* cur_entry = entries_[i];
301 if (cur_entry->IsUnresolvedMergedReference()) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800302 std::set<uint16_t> cur_entry_types =
303 (down_cast<UnresolvedMergedType*>(cur_entry))->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700304 if (cur_entry_types == types) {
305 return *cur_entry;
306 }
307 }
308 }
309 // Create entry.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800310 RegType* entry = new UnresolvedMergedType(left.GetId(), right.GetId(), this, entries_.size());
Ian Rogers529781d2012-07-23 17:24:29 -0700311 entries_.push_back(entry);
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800312#ifndef NDEBUG
313 UnresolvedMergedType* tmp_entry = down_cast<UnresolvedMergedType*>(entry);
314 std::set<uint16_t> check_types = tmp_entry->GetMergedTypes();
Ian Rogers529781d2012-07-23 17:24:29 -0700315 CHECK(check_types == types);
316#endif
317 return *entry;
318}
Ian Rogers529781d2012-07-23 17:24:29 -0700319const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
320 // Check if entry already exists.
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800321 for (size_t i = primitive_count_; i < entries_.size(); i++) {
322 RegType* cur_entry = entries_[i];
323 if (cur_entry->IsUnresolvedSuperClass()) {
324 UnresolvedSuperClass* tmp_entry =
325 down_cast<UnresolvedSuperClass*>(cur_entry);
326 uint16_t unresolved_super_child_id =
327 tmp_entry->GetUnresolvedSuperClassChildId();
328 if (unresolved_super_child_id == child.GetId()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700329 return *cur_entry;
330 }
331 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800332 }
333 RegType* entry = new UnresolvedSuperClass(child.GetId(), this, entries_.size());
334 entries_.push_back(entry);
335 return *entry;
336}
337const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
338 RegType* entry = NULL;
339 RegType* cur_entry = NULL;
340 if (type.IsUnresolvedTypes()) {
341 std::string descriptor(type.GetDescriptor());
342 for (size_t i = primitive_count_; i < entries_.size(); i++) {
343 cur_entry = entries_[i];
344 if (cur_entry->IsUnresolvedAndUninitializedReference() &&
345 down_cast<UnresolvedUninitializedRefType*>(cur_entry)->GetAllocationPc() == allocation_pc &&
346 (cur_entry->GetDescriptor() == descriptor)) {
347 return *cur_entry;
348 }
349 }
350 entry = new UnresolvedUninitializedRefType(descriptor, allocation_pc, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700351 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800352 mirror::Class* klass = type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800353 for (size_t i = primitive_count_; i < entries_.size(); i++) {
354 cur_entry = entries_[i];
Ian Rogers776ac1f2012-04-13 23:36:36 -0700355 if (cur_entry->IsUninitializedReference() &&
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800356 down_cast<UninitialisedReferenceType*>(cur_entry)
357 ->GetAllocationPc() == allocation_pc &&
Ian Rogers776ac1f2012-04-13 23:36:36 -0700358 cur_entry->GetClass() == klass) {
359 return *cur_entry;
360 }
361 }
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700362 std::string descriptor("");
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800363 entry = new UninitialisedReferenceType(klass, descriptor, allocation_pc, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700364 }
365 entries_.push_back(entry);
366 return *entry;
367}
Ian Rogers776ac1f2012-04-13 23:36:36 -0700368const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
369 RegType* entry;
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700370
Ian Rogers776ac1f2012-04-13 23:36:36 -0700371 if (uninit_type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800372 std::string descriptor(uninit_type.GetDescriptor());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800373 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700374 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800375 if (cur_entry->IsUnresolvedReference() &&
376 cur_entry->GetDescriptor() == descriptor) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700377 return *cur_entry;
378 }
379 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800380 entry = new UnresolvedReferenceType(descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700381 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800382 mirror::Class* klass = uninit_type.GetClass();
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700383 if(uninit_type.IsUninitializedThisReference() && !klass->IsFinal()) {
384 // For uninitialized this reference look for reference types that are not precise.
385 for (size_t i = primitive_count_; i < entries_.size(); i++) {
386 RegType* cur_entry = entries_[i];
387 if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
388 return *cur_entry;
389 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700390 }
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700391 std::string descriptor("");
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700392 entry = new ReferenceType(klass, descriptor, entries_.size());
393 } else {
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700394 std::string descriptor;
395 if (klass->IsFinal()) {
396 if (klass->IsInstantiable()) {
397 for (size_t i = primitive_count_; i < entries_.size(); i++) {
398 RegType* cur_entry = entries_[i];
399 if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
400 return *cur_entry;
401 }
402 }
403 // Precise type was not found , create one !
404 entry = new PreciseReferenceType(klass, descriptor, entries_.size());
405 } else {
406 return Conflict();
407 }
408 } else {
409 // Not a final class, create an imprecise reference. Look up if we have it in the cache first.
410 for (size_t i = primitive_count_; i < entries_.size(); i++) {
411 RegType* cur_entry = entries_[i];
412 if (cur_entry->IsReference() && !(cur_entry->IsPrecise()) &&
413 cur_entry->GetClass() == klass) {
414 return *cur_entry;
415 }
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700416 }
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700417 entry = new ReferenceType(klass, descriptor, entries_.size());
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700418 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700419 }
Sameer Abu Asal9f57a862013-04-19 10:08:00 -0700420 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700421 entries_.push_back(entry);
422 return *entry;
423}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800424const RegType& RegTypeCache::ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
425 return FromCat1Const(std::numeric_limits<jbyte>::min(), false);
426}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800427const RegType& RegTypeCache::ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
428 return FromCat1Const(std::numeric_limits<jshort>::min(), false);
429}
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800430const RegType& RegTypeCache::IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
431 return FromCat1Const(std::numeric_limits<jint>::max(), false);
432}
Ian Rogersad0b3a32012-04-16 14:50:24 -0700433const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700434 RegType* entry;
435 if (type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800436 std::string descriptor(type.GetDescriptor());
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800437 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700438 RegType* cur_entry = entries_[i];
439 if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
440 cur_entry->GetDescriptor() == descriptor) {
441 return *cur_entry;
442 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700443 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800444 entry = new UnresolvedUninitialisedThisRefType(descriptor, entries_.size());
Ian Rogersad0b3a32012-04-16 14:50:24 -0700445 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800446 mirror::Class* klass = type.GetClass();
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800447 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700448 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800449 if (cur_entry->IsUninitializedThisReference() &&
450 cur_entry->GetClass() == klass) {
Ian Rogersad0b3a32012-04-16 14:50:24 -0700451 return *cur_entry;
452 }
453 }
Sameer Abu Asal02c42232013-04-30 12:09:45 -0700454 std::string descriptor("");
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800455 entry = new UninitialisedThisReferenceType(klass, descriptor, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700456 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700457 entries_.push_back(entry);
458 return *entry;
459}
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800460const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800461 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700462 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800463 if (cur_entry->IsConstant() && cur_entry->IsPreciseConstant() == precise &&
464 (down_cast<ConstantType*>(cur_entry))->ConstantValue() == value) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700465 return *cur_entry;
466 }
467 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800468 RegType* entry;
469 if (precise) {
470 entry = new PreciseConstType(value, entries_.size());
471 } else {
472 entry = new ImpreciseConstType(value, entries_.size());
473 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800474 entries_.push_back(entry);
475 return *entry;
476}
477
478const RegType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800479 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800480 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800481 if (cur_entry->IsConstantLo() && (cur_entry->IsPrecise() == precise) &&
482 (down_cast<ConstantType*>(cur_entry))->ConstantValueLo() == value) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800483 return *cur_entry;
484 }
485 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800486 RegType* entry;
487 if (precise) {
488 entry = new PreciseConstLoType(value, entries_.size());
489 } else {
490 entry = new ImpreciseConstLoType(value, entries_.size());
491 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800492 entries_.push_back(entry);
493 return *entry;
494}
495
496const RegType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800497 for (size_t i = primitive_count_; i < entries_.size(); i++) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800498 RegType* cur_entry = entries_[i];
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800499 if (cur_entry->IsConstantHi() && (cur_entry->IsPrecise() == precise) &&
500 (down_cast<ConstantType*>(cur_entry))->ConstantValueHi() == value) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800501 return *cur_entry;
502 }
503 }
Sameer Abu Asal51a5fb72013-02-19 14:25:01 -0800504 RegType* entry;
505 if (precise) {
506 entry = new PreciseConstHiType(value, entries_.size());
507 } else {
508 entry = new ImpreciseConstHiType(value, entries_.size());
509 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700510 entries_.push_back(entry);
511 return *entry;
512}
513
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800514const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::ClassLoader* loader) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700515 CHECK(array.IsArrayTypes());
516 if (array.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800517 std::string descriptor(array.GetDescriptor());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700518 std::string component(descriptor.substr(1, descriptor.size() - 1));
Ian Rogersb4903572012-10-11 11:52:56 -0700519 return FromDescriptor(loader, component.c_str(), false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700520 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800521 mirror::Class* klass = array.GetClass()->GetComponentType();
Ian Rogersb4903572012-10-11 11:52:56 -0700522 return FromClass(klass, klass->IsFinal());
523 }
524}
525
526void RegTypeCache::Dump(std::ostream& os) {
Ian Rogersb4903572012-10-11 11:52:56 -0700527 for (size_t i = 0; i < entries_.size(); i++) {
528 RegType* cur_entry = entries_[i];
529 if (cur_entry != NULL) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800530 os << i << ": " << cur_entry->Dump() << "\n";
Ian Rogersb4903572012-10-11 11:52:56 -0700531 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700532 }
533}
534
Elliott Hughesa21039c2012-06-21 12:09:25 -0700535} // namespace verifier
536} // namespace art