blob: 96a6c24b24a2db858a0a75881618562f53c59a3d [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
17#include "reg_type_cache.h"
18
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070019#include "dex_file-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "mirror/class-inl.h"
21#include "mirror/object-inl.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070022#include "object_utils.h"
23
24namespace art {
25namespace verifier {
26
27static RegType::Type RegTypeFromPrimitiveType(Primitive::Type prim_type) {
28 switch (prim_type) {
29 case Primitive::kPrimBoolean: return RegType::kRegTypeBoolean;
30 case Primitive::kPrimByte: return RegType::kRegTypeByte;
31 case Primitive::kPrimShort: return RegType::kRegTypeShort;
32 case Primitive::kPrimChar: return RegType::kRegTypeChar;
33 case Primitive::kPrimInt: return RegType::kRegTypeInteger;
34 case Primitive::kPrimLong: return RegType::kRegTypeLongLo;
35 case Primitive::kPrimFloat: return RegType::kRegTypeFloat;
36 case Primitive::kPrimDouble: return RegType::kRegTypeDoubleLo;
37 case Primitive::kPrimVoid:
Ian Rogersad0b3a32012-04-16 14:50:24 -070038 default: return RegType::kRegTypeConflict;
Ian Rogers776ac1f2012-04-13 23:36:36 -070039 }
40}
41
42static RegType::Type RegTypeFromDescriptor(const std::string& descriptor) {
43 if (descriptor.length() == 1) {
44 switch (descriptor[0]) {
45 case 'Z': return RegType::kRegTypeBoolean;
46 case 'B': return RegType::kRegTypeByte;
47 case 'S': return RegType::kRegTypeShort;
48 case 'C': return RegType::kRegTypeChar;
49 case 'I': return RegType::kRegTypeInteger;
50 case 'J': return RegType::kRegTypeLongLo;
51 case 'F': return RegType::kRegTypeFloat;
52 case 'D': return RegType::kRegTypeDoubleLo;
53 case 'V':
Ian Rogersad0b3a32012-04-16 14:50:24 -070054 default: return RegType::kRegTypeConflict;
Ian Rogers776ac1f2012-04-13 23:36:36 -070055 }
56 } else if (descriptor[0] == 'L' || descriptor[0] == '[') {
57 return RegType::kRegTypeReference;
58 } else {
Ian Rogersad0b3a32012-04-16 14:50:24 -070059 return RegType::kRegTypeConflict;
Ian Rogers776ac1f2012-04-13 23:36:36 -070060 }
61}
62
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080063const RegType& RegTypeCache::FromDescriptor(mirror::ClassLoader* loader, const char* descriptor,
Ian Rogersb4903572012-10-11 11:52:56 -070064 bool precise) {
65 return From(RegTypeFromDescriptor(descriptor), loader, descriptor, precise);
Ian Rogers776ac1f2012-04-13 23:36:36 -070066}
67
Ian Rogersb4903572012-10-11 11:52:56 -070068static bool MatchingPrecisionForClass(RegType* entry, bool precise)
69 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
70 return (entry->IsPreciseReference() == precise) || (entry->GetClass()->IsFinal() && !precise);
71}
72
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080073const RegType& RegTypeCache::From(RegType::Type type, mirror::ClassLoader* loader,
74 const char* descriptor, bool precise) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070075 if (type <= RegType::kRegTypeLastFixedLocation) {
76 // entries should be sized greater than primitive types
77 DCHECK_GT(entries_.size(), static_cast<size_t>(type));
78 RegType* entry = entries_[type];
79 if (entry == NULL) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080080 mirror::Class* c = NULL;
Ian Rogers776ac1f2012-04-13 23:36:36 -070081 if (strlen(descriptor) != 0) {
Elliott Hughes80537bb2013-01-04 16:37:26 -080082 c = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor);
Ian Rogers776ac1f2012-04-13 23:36:36 -070083 }
Elliott Hughes80537bb2013-01-04 16:37:26 -080084 entry = new RegType(type, c, 0, type);
Ian Rogers776ac1f2012-04-13 23:36:36 -070085 entries_[type] = entry;
86 }
87 return *entry;
88 } else {
Ian Rogersb4903572012-10-11 11:52:56 -070089 DCHECK(type == RegType::kRegTypeReference || type == RegType::kRegTypePreciseReference);
Ian Rogers776ac1f2012-04-13 23:36:36 -070090 ClassHelper kh;
91 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
92 RegType* cur_entry = entries_[i];
93 // check resolved and unresolved references, ignore uninitialized references
Ian Rogersb4903572012-10-11 11:52:56 -070094 if (cur_entry->HasClass()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070095 kh.ChangeClass(cur_entry->GetClass());
Ian Rogersb4903572012-10-11 11:52:56 -070096 if (MatchingPrecisionForClass(cur_entry, precise) &&
97 (strcmp(descriptor, kh.GetDescriptor()) == 0)) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070098 return *cur_entry;
99 }
100 } else if (cur_entry->IsUnresolvedReference() &&
Elliott Hughes80537bb2013-01-04 16:37:26 -0800101 cur_entry->GetDescriptor() == descriptor) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700102 return *cur_entry;
103 }
104 }
Elliott Hughes80537bb2013-01-04 16:37:26 -0800105 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800106 mirror::Class* c;
Elliott Hughes80537bb2013-01-04 16:37:26 -0800107 if (can_load_classes_) {
108 c = class_linker->FindClass(descriptor, loader);
109 } else {
110 c = class_linker->LookupClass(descriptor, loader);
111 }
112 if (c != NULL) {
Ian Rogersb4903572012-10-11 11:52:56 -0700113 // Able to resolve so create resolved register type that is precise if we
114 // know the type is final.
Elliott Hughes80537bb2013-01-04 16:37:26 -0800115 RegType* entry = new RegType(c->IsFinal() ? RegType::kRegTypePreciseReference
116 : RegType::kRegTypeReference,
117 c, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700118 entries_.push_back(entry);
119 return *entry;
120 } else {
121 // TODO: we assume unresolved, but we may be able to do better by validating whether the
122 // descriptor string is valid
123 // Unable to resolve so create unresolved register type
Elliott Hughes80537bb2013-01-04 16:37:26 -0800124 if (can_load_classes_) {
125 DCHECK(Thread::Current()->IsExceptionPending());
126 Thread::Current()->ClearException();
127 } else {
128 DCHECK(!Thread::Current()->IsExceptionPending());
129 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700130 if (IsValidDescriptor(descriptor)) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800131 RegType* entry =
132 new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700133 entries_.push_back(entry);
134 return *entry;
135 } else {
136 // The descriptor is broken return the unknown type as there's nothing sensible that
137 // could be done at runtime
Ian Rogersad0b3a32012-04-16 14:50:24 -0700138 return Conflict();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700139 }
140 }
141 }
142}
143
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800144const RegType& RegTypeCache::FromClass(mirror::Class* klass, bool precise) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700145 if (klass->IsPrimitive()) {
146 RegType::Type type = RegTypeFromPrimitiveType(klass->GetPrimitiveType());
147 // entries should be sized greater than primitive types
148 DCHECK_GT(entries_.size(), static_cast<size_t>(type));
149 RegType* entry = entries_[type];
150 if (entry == NULL) {
151 entry = new RegType(type, klass, 0, type);
152 entries_[type] = entry;
153 }
154 return *entry;
155 } else {
156 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
157 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700158 if ((cur_entry->HasClass()) &&
159 MatchingPrecisionForClass(cur_entry, precise) && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700160 return *cur_entry;
161 }
162 }
Ian Rogersb4903572012-10-11 11:52:56 -0700163 RegType* entry = new RegType(precise ? RegType::kRegTypePreciseReference
164 : RegType::kRegTypeReference,
165 klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700166 entries_.push_back(entry);
167 return *entry;
168 }
169}
170
Ian Rogers529781d2012-07-23 17:24:29 -0700171const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left, const RegType& right) {
172 std::set<uint16_t> types;
173 if (left.IsUnresolvedMergedReference()) {
174 types = left.GetMergedTypes(this);
175 } else {
176 types.insert(left.GetId());
177 }
178 if (right.IsUnresolvedMergedReference()) {
179 std::set<uint16_t> right_types = right.GetMergedTypes(this);
180 types.insert(right_types.begin(), right_types.end());
181 } else {
182 types.insert(right.GetId());
183 }
184 // Check if entry already exists.
185 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
186 RegType* cur_entry = entries_[i];
187 if (cur_entry->IsUnresolvedMergedReference()) {
188 std::set<uint16_t> cur_entry_types = cur_entry->GetMergedTypes(this);
189 if (cur_entry_types == types) {
190 return *cur_entry;
191 }
192 }
193 }
194 // Create entry.
195 uint32_t merged_ids = static_cast<uint32_t>(left.GetId()) << 16 |
196 static_cast<uint32_t>(right.GetId());
197 RegType* entry = new RegType(RegType::kRegTypeUnresolvedMergedReference, NULL, merged_ids,
198 entries_.size());
199 entries_.push_back(entry);
200#ifndef DEBUG
201 std::set<uint16_t> check_types = entry->GetMergedTypes(this);
202 CHECK(check_types == types);
203#endif
204 return *entry;
205}
206
207const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
208 // Check if entry already exists.
209 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
210 RegType* cur_entry = entries_[i];
211 if (cur_entry->IsUnresolvedSuperClass()) {
212 uint16_t unresolved_super_child_id = cur_entry->GetUnresolvedSuperClassChildId();
213 if (unresolved_super_child_id == child.GetId()) {
214 return *cur_entry;
215 }
216 }
217 }
218 // Create entry.
219 RegType* entry = new RegType(RegType::kRegTypeUnresolvedSuperClass, NULL, child.GetId(),
220 entries_.size());
221 entries_.push_back(entry);
222 return *entry;
223}
224
Ian Rogers776ac1f2012-04-13 23:36:36 -0700225const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
226 RegType* entry;
227 if (type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800228 std::string descriptor(type.GetDescriptor());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700229 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
230 RegType* cur_entry = entries_[i];
231 if (cur_entry->IsUnresolvedAndUninitializedReference() &&
232 cur_entry->GetAllocationPc() == allocation_pc &&
233 cur_entry->GetDescriptor() == descriptor) {
234 return *cur_entry;
235 }
236 }
237 entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedReference,
238 descriptor, allocation_pc, entries_.size());
239 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800240 mirror::Class* klass = type.GetClass();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700241 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
242 RegType* cur_entry = entries_[i];
243 if (cur_entry->IsUninitializedReference() &&
244 cur_entry->GetAllocationPc() == allocation_pc &&
245 cur_entry->GetClass() == klass) {
246 return *cur_entry;
247 }
248 }
249 entry = new RegType(RegType::kRegTypeUninitializedReference,
250 klass, allocation_pc, entries_.size());
251 }
252 entries_.push_back(entry);
253 return *entry;
254}
255
256const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
257 RegType* entry;
258 if (uninit_type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800259 std::string descriptor(uninit_type.GetDescriptor());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700260 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
261 RegType* cur_entry = entries_[i];
262 if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
263 return *cur_entry;
264 }
265 }
266 entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
267 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800268 mirror::Class* klass = uninit_type.GetClass();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700269 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
270 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700271 if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700272 return *cur_entry;
273 }
274 }
Ian Rogersb4903572012-10-11 11:52:56 -0700275 entry = new RegType(RegType::kRegTypePreciseReference, klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700276 }
277 entries_.push_back(entry);
278 return *entry;
279}
280
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800281const RegType& RegTypeCache::ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
282 return FromCat1Const(std::numeric_limits<jbyte>::min(), false);
283}
284
285const RegType& RegTypeCache::ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
286 return FromCat1Const(std::numeric_limits<jshort>::min(), false);
287}
288
289const RegType& RegTypeCache::IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
290 return FromCat1Const(std::numeric_limits<jint>::max(), false);
291}
292
Ian Rogersad0b3a32012-04-16 14:50:24 -0700293const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
294 // TODO: implement descriptor version.
295 RegType* entry;
296 if (type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800297 std::string descriptor(type.GetDescriptor());
Ian Rogersad0b3a32012-04-16 14:50:24 -0700298 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
299 RegType* cur_entry = entries_[i];
300 if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
301 cur_entry->GetDescriptor() == descriptor) {
302 return *cur_entry;
303 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700304 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700305 entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedThisReference, descriptor, 0,
306 entries_.size());
307 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800308 mirror::Class* klass = type.GetClass();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700309 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
310 RegType* cur_entry = entries_[i];
311 if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
312 return *cur_entry;
313 }
314 }
315 entry = new RegType(RegType::kRegTypeUninitializedThisReference, klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700316 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700317 entries_.push_back(entry);
318 return *entry;
319}
320
321const RegType& RegTypeCache::FromType(RegType::Type type) {
322 CHECK(type < RegType::kRegTypeReference);
323 switch (type) {
Ian Rogersb4903572012-10-11 11:52:56 -0700324 case RegType::kRegTypeBoolean: return From(type, NULL, "Z", true);
325 case RegType::kRegTypeByte: return From(type, NULL, "B", true);
326 case RegType::kRegTypeShort: return From(type, NULL, "S", true);
327 case RegType::kRegTypeChar: return From(type, NULL, "C", true);
328 case RegType::kRegTypeInteger: return From(type, NULL, "I", true);
329 case RegType::kRegTypeFloat: return From(type, NULL, "F", true);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700330 case RegType::kRegTypeLongLo:
Ian Rogersb4903572012-10-11 11:52:56 -0700331 case RegType::kRegTypeLongHi: return From(type, NULL, "J", true);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700332 case RegType::kRegTypeDoubleLo:
Ian Rogersb4903572012-10-11 11:52:56 -0700333 case RegType::kRegTypeDoubleHi: return From(type, NULL, "D", true);
334 default: return From(type, NULL, "", true);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700335 }
336}
337
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800338const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800339 RegType::Type wanted_type =
340 precise ? RegType::kRegTypePreciseConst : RegType::kRegTypeImpreciseConst;
Ian Rogers776ac1f2012-04-13 23:36:36 -0700341 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
342 RegType* cur_entry = entries_[i];
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800343 if (cur_entry->GetType() == wanted_type && cur_entry->ConstantValue() == value) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700344 return *cur_entry;
345 }
346 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800347 RegType* entry = new RegType(wanted_type, NULL, value, entries_.size());
348 entries_.push_back(entry);
349 return *entry;
350}
351
352const RegType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800353 RegType::Type wanted_type =
354 precise ? RegType::kRegTypePreciseConstLo : RegType::kRegTypeImpreciseConstLo;
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800355 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
356 RegType* cur_entry = entries_[i];
357 if (cur_entry->GetType() == wanted_type && cur_entry->ConstantValueLo() == value) {
358 return *cur_entry;
359 }
360 }
361 RegType* entry = new RegType(wanted_type, NULL, value, entries_.size());
362 entries_.push_back(entry);
363 return *entry;
364}
365
366const RegType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800367 RegType::Type wanted_type =
368 precise ? RegType::kRegTypePreciseConstHi : RegType::kRegTypeImpreciseConstHi;
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800369 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
370 RegType* cur_entry = entries_[i];
371 if (cur_entry->GetType() == wanted_type && cur_entry->ConstantValueHi() == value) {
372 return *cur_entry;
373 }
374 }
375 RegType* entry = new RegType(wanted_type, NULL, value, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700376 entries_.push_back(entry);
377 return *entry;
378}
379
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800380const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::ClassLoader* loader) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700381 CHECK(array.IsArrayTypes());
382 if (array.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800383 std::string descriptor(array.GetDescriptor());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700384 std::string component(descriptor.substr(1, descriptor.size() - 1));
Ian Rogersb4903572012-10-11 11:52:56 -0700385 return FromDescriptor(loader, component.c_str(), false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700386 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800387 mirror::Class* klass = array.GetClass()->GetComponentType();
Ian Rogersb4903572012-10-11 11:52:56 -0700388 return FromClass(klass, klass->IsFinal());
389 }
390}
391
392void RegTypeCache::Dump(std::ostream& os) {
Ian Rogersb4903572012-10-11 11:52:56 -0700393 for (size_t i = 0; i < entries_.size(); i++) {
394 RegType* cur_entry = entries_[i];
395 if (cur_entry != NULL) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800396 os << i << ": " << cur_entry->Dump() << "\n";
Ian Rogersb4903572012-10-11 11:52:56 -0700397 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700398 }
399}
400
Elliott Hughesa21039c2012-06-21 12:09:25 -0700401} // namespace verifier
402} // namespace art