blob: 6ca54dea9a7a94aea004c5b07a66e137ae755e67 [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 Rogers2dd0e2c2013-01-24 12:42:14 -080019#include "mirror/class-inl.h"
20#include "mirror/object-inl.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070021#include "object_utils.h"
22
23namespace art {
24namespace verifier {
25
26static RegType::Type RegTypeFromPrimitiveType(Primitive::Type prim_type) {
27 switch (prim_type) {
28 case Primitive::kPrimBoolean: return RegType::kRegTypeBoolean;
29 case Primitive::kPrimByte: return RegType::kRegTypeByte;
30 case Primitive::kPrimShort: return RegType::kRegTypeShort;
31 case Primitive::kPrimChar: return RegType::kRegTypeChar;
32 case Primitive::kPrimInt: return RegType::kRegTypeInteger;
33 case Primitive::kPrimLong: return RegType::kRegTypeLongLo;
34 case Primitive::kPrimFloat: return RegType::kRegTypeFloat;
35 case Primitive::kPrimDouble: return RegType::kRegTypeDoubleLo;
36 case Primitive::kPrimVoid:
Ian Rogersad0b3a32012-04-16 14:50:24 -070037 default: return RegType::kRegTypeConflict;
Ian Rogers776ac1f2012-04-13 23:36:36 -070038 }
39}
40
41static RegType::Type RegTypeFromDescriptor(const std::string& descriptor) {
42 if (descriptor.length() == 1) {
43 switch (descriptor[0]) {
44 case 'Z': return RegType::kRegTypeBoolean;
45 case 'B': return RegType::kRegTypeByte;
46 case 'S': return RegType::kRegTypeShort;
47 case 'C': return RegType::kRegTypeChar;
48 case 'I': return RegType::kRegTypeInteger;
49 case 'J': return RegType::kRegTypeLongLo;
50 case 'F': return RegType::kRegTypeFloat;
51 case 'D': return RegType::kRegTypeDoubleLo;
52 case 'V':
Ian Rogersad0b3a32012-04-16 14:50:24 -070053 default: return RegType::kRegTypeConflict;
Ian Rogers776ac1f2012-04-13 23:36:36 -070054 }
55 } else if (descriptor[0] == 'L' || descriptor[0] == '[') {
56 return RegType::kRegTypeReference;
57 } else {
Ian Rogersad0b3a32012-04-16 14:50:24 -070058 return RegType::kRegTypeConflict;
Ian Rogers776ac1f2012-04-13 23:36:36 -070059 }
60}
61
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080062const RegType& RegTypeCache::FromDescriptor(mirror::ClassLoader* loader, const char* descriptor,
Ian Rogersb4903572012-10-11 11:52:56 -070063 bool precise) {
64 return From(RegTypeFromDescriptor(descriptor), loader, descriptor, precise);
Ian Rogers776ac1f2012-04-13 23:36:36 -070065}
66
Ian Rogersb4903572012-10-11 11:52:56 -070067static bool MatchingPrecisionForClass(RegType* entry, bool precise)
68 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
69 return (entry->IsPreciseReference() == precise) || (entry->GetClass()->IsFinal() && !precise);
70}
71
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080072const RegType& RegTypeCache::From(RegType::Type type, mirror::ClassLoader* loader,
73 const char* descriptor, bool precise) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070074 if (type <= RegType::kRegTypeLastFixedLocation) {
75 // entries should be sized greater than primitive types
76 DCHECK_GT(entries_.size(), static_cast<size_t>(type));
77 RegType* entry = entries_[type];
78 if (entry == NULL) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080079 mirror::Class* c = NULL;
Ian Rogers776ac1f2012-04-13 23:36:36 -070080 if (strlen(descriptor) != 0) {
Elliott Hughes80537bb2013-01-04 16:37:26 -080081 c = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor);
Ian Rogers776ac1f2012-04-13 23:36:36 -070082 }
Elliott Hughes80537bb2013-01-04 16:37:26 -080083 entry = new RegType(type, c, 0, type);
Ian Rogers776ac1f2012-04-13 23:36:36 -070084 entries_[type] = entry;
85 }
86 return *entry;
87 } else {
Ian Rogersb4903572012-10-11 11:52:56 -070088 DCHECK(type == RegType::kRegTypeReference || type == RegType::kRegTypePreciseReference);
Ian Rogers776ac1f2012-04-13 23:36:36 -070089 ClassHelper kh;
90 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
91 RegType* cur_entry = entries_[i];
92 // check resolved and unresolved references, ignore uninitialized references
Ian Rogersb4903572012-10-11 11:52:56 -070093 if (cur_entry->HasClass()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070094 kh.ChangeClass(cur_entry->GetClass());
Ian Rogersb4903572012-10-11 11:52:56 -070095 if (MatchingPrecisionForClass(cur_entry, precise) &&
96 (strcmp(descriptor, kh.GetDescriptor()) == 0)) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070097 return *cur_entry;
98 }
99 } else if (cur_entry->IsUnresolvedReference() &&
Elliott Hughes80537bb2013-01-04 16:37:26 -0800100 cur_entry->GetDescriptor() == descriptor) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700101 return *cur_entry;
102 }
103 }
Elliott Hughes80537bb2013-01-04 16:37:26 -0800104 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800105 mirror::Class* c;
Elliott Hughes80537bb2013-01-04 16:37:26 -0800106 if (can_load_classes_) {
107 c = class_linker->FindClass(descriptor, loader);
108 } else {
109 c = class_linker->LookupClass(descriptor, loader);
110 }
111 if (c != NULL) {
Ian Rogersb4903572012-10-11 11:52:56 -0700112 // Able to resolve so create resolved register type that is precise if we
113 // know the type is final.
Elliott Hughes80537bb2013-01-04 16:37:26 -0800114 RegType* entry = new RegType(c->IsFinal() ? RegType::kRegTypePreciseReference
115 : RegType::kRegTypeReference,
116 c, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700117 entries_.push_back(entry);
118 return *entry;
119 } else {
120 // TODO: we assume unresolved, but we may be able to do better by validating whether the
121 // descriptor string is valid
122 // Unable to resolve so create unresolved register type
Elliott Hughes80537bb2013-01-04 16:37:26 -0800123 if (can_load_classes_) {
124 DCHECK(Thread::Current()->IsExceptionPending());
125 Thread::Current()->ClearException();
126 } else {
127 DCHECK(!Thread::Current()->IsExceptionPending());
128 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700129 if (IsValidDescriptor(descriptor)) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800130 RegType* entry =
131 new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700132 entries_.push_back(entry);
133 return *entry;
134 } else {
135 // The descriptor is broken return the unknown type as there's nothing sensible that
136 // could be done at runtime
Ian Rogersad0b3a32012-04-16 14:50:24 -0700137 return Conflict();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700138 }
139 }
140 }
141}
142
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800143const RegType& RegTypeCache::FromClass(mirror::Class* klass, bool precise) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700144 if (klass->IsPrimitive()) {
145 RegType::Type type = RegTypeFromPrimitiveType(klass->GetPrimitiveType());
146 // entries should be sized greater than primitive types
147 DCHECK_GT(entries_.size(), static_cast<size_t>(type));
148 RegType* entry = entries_[type];
149 if (entry == NULL) {
150 entry = new RegType(type, klass, 0, type);
151 entries_[type] = entry;
152 }
153 return *entry;
154 } else {
155 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
156 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700157 if ((cur_entry->HasClass()) &&
158 MatchingPrecisionForClass(cur_entry, precise) && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700159 return *cur_entry;
160 }
161 }
Ian Rogersb4903572012-10-11 11:52:56 -0700162 RegType* entry = new RegType(precise ? RegType::kRegTypePreciseReference
163 : RegType::kRegTypeReference,
164 klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700165 entries_.push_back(entry);
166 return *entry;
167 }
168}
169
Ian Rogers529781d2012-07-23 17:24:29 -0700170const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left, const RegType& right) {
171 std::set<uint16_t> types;
172 if (left.IsUnresolvedMergedReference()) {
173 types = left.GetMergedTypes(this);
174 } else {
175 types.insert(left.GetId());
176 }
177 if (right.IsUnresolvedMergedReference()) {
178 std::set<uint16_t> right_types = right.GetMergedTypes(this);
179 types.insert(right_types.begin(), right_types.end());
180 } else {
181 types.insert(right.GetId());
182 }
183 // Check if entry already exists.
184 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
185 RegType* cur_entry = entries_[i];
186 if (cur_entry->IsUnresolvedMergedReference()) {
187 std::set<uint16_t> cur_entry_types = cur_entry->GetMergedTypes(this);
188 if (cur_entry_types == types) {
189 return *cur_entry;
190 }
191 }
192 }
193 // Create entry.
194 uint32_t merged_ids = static_cast<uint32_t>(left.GetId()) << 16 |
195 static_cast<uint32_t>(right.GetId());
196 RegType* entry = new RegType(RegType::kRegTypeUnresolvedMergedReference, NULL, merged_ids,
197 entries_.size());
198 entries_.push_back(entry);
199#ifndef DEBUG
200 std::set<uint16_t> check_types = entry->GetMergedTypes(this);
201 CHECK(check_types == types);
202#endif
203 return *entry;
204}
205
206const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
207 // Check if entry already exists.
208 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
209 RegType* cur_entry = entries_[i];
210 if (cur_entry->IsUnresolvedSuperClass()) {
211 uint16_t unresolved_super_child_id = cur_entry->GetUnresolvedSuperClassChildId();
212 if (unresolved_super_child_id == child.GetId()) {
213 return *cur_entry;
214 }
215 }
216 }
217 // Create entry.
218 RegType* entry = new RegType(RegType::kRegTypeUnresolvedSuperClass, NULL, child.GetId(),
219 entries_.size());
220 entries_.push_back(entry);
221 return *entry;
222}
223
Ian Rogers776ac1f2012-04-13 23:36:36 -0700224const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
225 RegType* entry;
226 if (type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800227 std::string descriptor(type.GetDescriptor());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700228 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
229 RegType* cur_entry = entries_[i];
230 if (cur_entry->IsUnresolvedAndUninitializedReference() &&
231 cur_entry->GetAllocationPc() == allocation_pc &&
232 cur_entry->GetDescriptor() == descriptor) {
233 return *cur_entry;
234 }
235 }
236 entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedReference,
237 descriptor, allocation_pc, entries_.size());
238 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800239 mirror::Class* klass = type.GetClass();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700240 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
241 RegType* cur_entry = entries_[i];
242 if (cur_entry->IsUninitializedReference() &&
243 cur_entry->GetAllocationPc() == allocation_pc &&
244 cur_entry->GetClass() == klass) {
245 return *cur_entry;
246 }
247 }
248 entry = new RegType(RegType::kRegTypeUninitializedReference,
249 klass, allocation_pc, entries_.size());
250 }
251 entries_.push_back(entry);
252 return *entry;
253}
254
255const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
256 RegType* entry;
257 if (uninit_type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800258 std::string descriptor(uninit_type.GetDescriptor());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700259 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
260 RegType* cur_entry = entries_[i];
261 if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
262 return *cur_entry;
263 }
264 }
265 entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
266 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800267 mirror::Class* klass = uninit_type.GetClass();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700268 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
269 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700270 if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700271 return *cur_entry;
272 }
273 }
Ian Rogersb4903572012-10-11 11:52:56 -0700274 entry = new RegType(RegType::kRegTypePreciseReference, klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700275 }
276 entries_.push_back(entry);
277 return *entry;
278}
279
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800280const RegType& RegTypeCache::ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
281 return FromCat1Const(std::numeric_limits<jbyte>::min(), false);
282}
283
284const RegType& RegTypeCache::ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
285 return FromCat1Const(std::numeric_limits<jshort>::min(), false);
286}
287
288const RegType& RegTypeCache::IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
289 return FromCat1Const(std::numeric_limits<jint>::max(), false);
290}
291
Ian Rogersad0b3a32012-04-16 14:50:24 -0700292const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
293 // TODO: implement descriptor version.
294 RegType* entry;
295 if (type.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800296 std::string descriptor(type.GetDescriptor());
Ian Rogersad0b3a32012-04-16 14:50:24 -0700297 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
298 RegType* cur_entry = entries_[i];
299 if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
300 cur_entry->GetDescriptor() == descriptor) {
301 return *cur_entry;
302 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700303 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700304 entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedThisReference, descriptor, 0,
305 entries_.size());
306 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800307 mirror::Class* klass = type.GetClass();
Ian Rogersad0b3a32012-04-16 14:50:24 -0700308 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
309 RegType* cur_entry = entries_[i];
310 if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
311 return *cur_entry;
312 }
313 }
314 entry = new RegType(RegType::kRegTypeUninitializedThisReference, klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700315 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700316 entries_.push_back(entry);
317 return *entry;
318}
319
320const RegType& RegTypeCache::FromType(RegType::Type type) {
321 CHECK(type < RegType::kRegTypeReference);
322 switch (type) {
Ian Rogersb4903572012-10-11 11:52:56 -0700323 case RegType::kRegTypeBoolean: return From(type, NULL, "Z", true);
324 case RegType::kRegTypeByte: return From(type, NULL, "B", true);
325 case RegType::kRegTypeShort: return From(type, NULL, "S", true);
326 case RegType::kRegTypeChar: return From(type, NULL, "C", true);
327 case RegType::kRegTypeInteger: return From(type, NULL, "I", true);
328 case RegType::kRegTypeFloat: return From(type, NULL, "F", true);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700329 case RegType::kRegTypeLongLo:
Ian Rogersb4903572012-10-11 11:52:56 -0700330 case RegType::kRegTypeLongHi: return From(type, NULL, "J", true);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700331 case RegType::kRegTypeDoubleLo:
Ian Rogersb4903572012-10-11 11:52:56 -0700332 case RegType::kRegTypeDoubleHi: return From(type, NULL, "D", true);
333 default: return From(type, NULL, "", true);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700334 }
335}
336
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800337const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800338 RegType::Type wanted_type =
339 precise ? RegType::kRegTypePreciseConst : RegType::kRegTypeImpreciseConst;
Ian Rogers776ac1f2012-04-13 23:36:36 -0700340 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
341 RegType* cur_entry = entries_[i];
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800342 if (cur_entry->GetType() == wanted_type && cur_entry->ConstantValue() == value) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700343 return *cur_entry;
344 }
345 }
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800346 RegType* entry = new RegType(wanted_type, NULL, value, entries_.size());
347 entries_.push_back(entry);
348 return *entry;
349}
350
351const RegType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800352 RegType::Type wanted_type =
353 precise ? RegType::kRegTypePreciseConstLo : RegType::kRegTypeImpreciseConstLo;
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800354 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
355 RegType* cur_entry = entries_[i];
356 if (cur_entry->GetType() == wanted_type && cur_entry->ConstantValueLo() == value) {
357 return *cur_entry;
358 }
359 }
360 RegType* entry = new RegType(wanted_type, NULL, value, entries_.size());
361 entries_.push_back(entry);
362 return *entry;
363}
364
365const RegType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800366 RegType::Type wanted_type =
367 precise ? RegType::kRegTypePreciseConstHi : RegType::kRegTypeImpreciseConstHi;
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800368 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
369 RegType* cur_entry = entries_[i];
370 if (cur_entry->GetType() == wanted_type && cur_entry->ConstantValueHi() == value) {
371 return *cur_entry;
372 }
373 }
374 RegType* entry = new RegType(wanted_type, NULL, value, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700375 entries_.push_back(entry);
376 return *entry;
377}
378
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800379const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::ClassLoader* loader) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700380 CHECK(array.IsArrayTypes());
381 if (array.IsUnresolvedTypes()) {
Elliott Hughes80537bb2013-01-04 16:37:26 -0800382 std::string descriptor(array.GetDescriptor());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700383 std::string component(descriptor.substr(1, descriptor.size() - 1));
Ian Rogersb4903572012-10-11 11:52:56 -0700384 return FromDescriptor(loader, component.c_str(), false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700385 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800386 mirror::Class* klass = array.GetClass()->GetComponentType();
Ian Rogersb4903572012-10-11 11:52:56 -0700387 return FromClass(klass, klass->IsFinal());
388 }
389}
390
391void RegTypeCache::Dump(std::ostream& os) {
Ian Rogersb4903572012-10-11 11:52:56 -0700392 for (size_t i = 0; i < entries_.size(); i++) {
393 RegType* cur_entry = entries_[i];
394 if (cur_entry != NULL) {
Ian Rogers2bcb4a42012-11-08 10:39:18 -0800395 os << i << ": " << cur_entry->Dump() << "\n";
Ian Rogersb4903572012-10-11 11:52:56 -0700396 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700397 }
398}
399
Elliott Hughesa21039c2012-06-21 12:09:25 -0700400} // namespace verifier
401} // namespace art