blob: 847cde90afba11fd1765f3a57debfd3e6daf44c1 [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
19#include "object_utils.h"
20
21namespace art {
22namespace verifier {
23
24static RegType::Type RegTypeFromPrimitiveType(Primitive::Type prim_type) {
25 switch (prim_type) {
26 case Primitive::kPrimBoolean: return RegType::kRegTypeBoolean;
27 case Primitive::kPrimByte: return RegType::kRegTypeByte;
28 case Primitive::kPrimShort: return RegType::kRegTypeShort;
29 case Primitive::kPrimChar: return RegType::kRegTypeChar;
30 case Primitive::kPrimInt: return RegType::kRegTypeInteger;
31 case Primitive::kPrimLong: return RegType::kRegTypeLongLo;
32 case Primitive::kPrimFloat: return RegType::kRegTypeFloat;
33 case Primitive::kPrimDouble: return RegType::kRegTypeDoubleLo;
34 case Primitive::kPrimVoid:
Ian Rogersad0b3a32012-04-16 14:50:24 -070035 default: return RegType::kRegTypeConflict;
Ian Rogers776ac1f2012-04-13 23:36:36 -070036 }
37}
38
39static RegType::Type RegTypeFromDescriptor(const std::string& descriptor) {
40 if (descriptor.length() == 1) {
41 switch (descriptor[0]) {
42 case 'Z': return RegType::kRegTypeBoolean;
43 case 'B': return RegType::kRegTypeByte;
44 case 'S': return RegType::kRegTypeShort;
45 case 'C': return RegType::kRegTypeChar;
46 case 'I': return RegType::kRegTypeInteger;
47 case 'J': return RegType::kRegTypeLongLo;
48 case 'F': return RegType::kRegTypeFloat;
49 case 'D': return RegType::kRegTypeDoubleLo;
50 case 'V':
Ian Rogersad0b3a32012-04-16 14:50:24 -070051 default: return RegType::kRegTypeConflict;
Ian Rogers776ac1f2012-04-13 23:36:36 -070052 }
53 } else if (descriptor[0] == 'L' || descriptor[0] == '[') {
54 return RegType::kRegTypeReference;
55 } else {
Ian Rogersad0b3a32012-04-16 14:50:24 -070056 return RegType::kRegTypeConflict;
Ian Rogers776ac1f2012-04-13 23:36:36 -070057 }
58}
59
Ian Rogersb4903572012-10-11 11:52:56 -070060const RegType& RegTypeCache::FromDescriptor(ClassLoader* loader, const char* descriptor,
61 bool precise) {
62 return From(RegTypeFromDescriptor(descriptor), loader, descriptor, precise);
Ian Rogers776ac1f2012-04-13 23:36:36 -070063}
64
Ian Rogersb4903572012-10-11 11:52:56 -070065static bool MatchingPrecisionForClass(RegType* entry, bool precise)
66 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
67 return (entry->IsPreciseReference() == precise) || (entry->GetClass()->IsFinal() && !precise);
68}
69
70const RegType& RegTypeCache::From(RegType::Type type, ClassLoader* loader, const char* descriptor,
71 bool precise) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070072 if (type <= RegType::kRegTypeLastFixedLocation) {
73 // entries should be sized greater than primitive types
74 DCHECK_GT(entries_.size(), static_cast<size_t>(type));
75 RegType* entry = entries_[type];
76 if (entry == NULL) {
77 Class* klass = NULL;
78 if (strlen(descriptor) != 0) {
79 klass = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor);
80 }
81 entry = new RegType(type, klass, 0, type);
82 entries_[type] = entry;
83 }
84 return *entry;
85 } else {
Ian Rogersb4903572012-10-11 11:52:56 -070086 DCHECK(type == RegType::kRegTypeReference || type == RegType::kRegTypePreciseReference);
Ian Rogers776ac1f2012-04-13 23:36:36 -070087 ClassHelper kh;
88 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
89 RegType* cur_entry = entries_[i];
90 // check resolved and unresolved references, ignore uninitialized references
Ian Rogersb4903572012-10-11 11:52:56 -070091 if (cur_entry->HasClass()) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070092 kh.ChangeClass(cur_entry->GetClass());
Ian Rogersb4903572012-10-11 11:52:56 -070093 if (MatchingPrecisionForClass(cur_entry, precise) &&
94 (strcmp(descriptor, kh.GetDescriptor()) == 0)) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070095 return *cur_entry;
96 }
97 } else if (cur_entry->IsUnresolvedReference() &&
98 cur_entry->GetDescriptor()->Equals(descriptor)) {
99 return *cur_entry;
100 }
101 }
102 Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, loader);
103 if (klass != NULL) {
Ian Rogersb4903572012-10-11 11:52:56 -0700104 // Able to resolve so create resolved register type that is precise if we
105 // know the type is final.
106 RegType* entry = new RegType(klass->IsFinal() ? RegType::kRegTypePreciseReference
107 : RegType::kRegTypeReference,
108 klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700109 entries_.push_back(entry);
110 return *entry;
111 } else {
112 // TODO: we assume unresolved, but we may be able to do better by validating whether the
113 // descriptor string is valid
114 // Unable to resolve so create unresolved register type
115 DCHECK(Thread::Current()->IsExceptionPending());
116 Thread::Current()->ClearException();
117 if (IsValidDescriptor(descriptor)) {
118 String* string_descriptor =
119 Runtime::Current()->GetInternTable()->InternStrong(descriptor);
120 RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, string_descriptor, 0,
121 entries_.size());
122 entries_.push_back(entry);
123 return *entry;
124 } else {
125 // The descriptor is broken return the unknown type as there's nothing sensible that
126 // could be done at runtime
Ian Rogersad0b3a32012-04-16 14:50:24 -0700127 return Conflict();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700128 }
129 }
130 }
131}
132
Ian Rogersb4903572012-10-11 11:52:56 -0700133const RegType& RegTypeCache::FromClass(Class* klass, bool precise) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700134 if (klass->IsPrimitive()) {
135 RegType::Type type = RegTypeFromPrimitiveType(klass->GetPrimitiveType());
136 // entries should be sized greater than primitive types
137 DCHECK_GT(entries_.size(), static_cast<size_t>(type));
138 RegType* entry = entries_[type];
139 if (entry == NULL) {
140 entry = new RegType(type, klass, 0, type);
141 entries_[type] = entry;
142 }
143 return *entry;
144 } else {
145 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
146 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700147 if ((cur_entry->HasClass()) &&
148 MatchingPrecisionForClass(cur_entry, precise) && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700149 return *cur_entry;
150 }
151 }
Ian Rogersb4903572012-10-11 11:52:56 -0700152 RegType* entry = new RegType(precise ? RegType::kRegTypePreciseReference
153 : RegType::kRegTypeReference,
154 klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700155 entries_.push_back(entry);
156 return *entry;
157 }
158}
159
Ian Rogers529781d2012-07-23 17:24:29 -0700160const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left, const RegType& right) {
161 std::set<uint16_t> types;
162 if (left.IsUnresolvedMergedReference()) {
163 types = left.GetMergedTypes(this);
164 } else {
165 types.insert(left.GetId());
166 }
167 if (right.IsUnresolvedMergedReference()) {
168 std::set<uint16_t> right_types = right.GetMergedTypes(this);
169 types.insert(right_types.begin(), right_types.end());
170 } else {
171 types.insert(right.GetId());
172 }
173 // Check if entry already exists.
174 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
175 RegType* cur_entry = entries_[i];
176 if (cur_entry->IsUnresolvedMergedReference()) {
177 std::set<uint16_t> cur_entry_types = cur_entry->GetMergedTypes(this);
178 if (cur_entry_types == types) {
179 return *cur_entry;
180 }
181 }
182 }
183 // Create entry.
184 uint32_t merged_ids = static_cast<uint32_t>(left.GetId()) << 16 |
185 static_cast<uint32_t>(right.GetId());
186 RegType* entry = new RegType(RegType::kRegTypeUnresolvedMergedReference, NULL, merged_ids,
187 entries_.size());
188 entries_.push_back(entry);
189#ifndef DEBUG
190 std::set<uint16_t> check_types = entry->GetMergedTypes(this);
191 CHECK(check_types == types);
192#endif
193 return *entry;
194}
195
196const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
197 // Check if entry already exists.
198 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
199 RegType* cur_entry = entries_[i];
200 if (cur_entry->IsUnresolvedSuperClass()) {
201 uint16_t unresolved_super_child_id = cur_entry->GetUnresolvedSuperClassChildId();
202 if (unresolved_super_child_id == child.GetId()) {
203 return *cur_entry;
204 }
205 }
206 }
207 // Create entry.
208 RegType* entry = new RegType(RegType::kRegTypeUnresolvedSuperClass, NULL, child.GetId(),
209 entries_.size());
210 entries_.push_back(entry);
211 return *entry;
212}
213
Ian Rogers776ac1f2012-04-13 23:36:36 -0700214const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
215 RegType* entry;
216 if (type.IsUnresolvedTypes()) {
217 String* descriptor = type.GetDescriptor();
218 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
219 RegType* cur_entry = entries_[i];
220 if (cur_entry->IsUnresolvedAndUninitializedReference() &&
221 cur_entry->GetAllocationPc() == allocation_pc &&
222 cur_entry->GetDescriptor() == descriptor) {
223 return *cur_entry;
224 }
225 }
226 entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedReference,
227 descriptor, allocation_pc, entries_.size());
228 } else {
229 Class* klass = type.GetClass();
230 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
231 RegType* cur_entry = entries_[i];
232 if (cur_entry->IsUninitializedReference() &&
233 cur_entry->GetAllocationPc() == allocation_pc &&
234 cur_entry->GetClass() == klass) {
235 return *cur_entry;
236 }
237 }
238 entry = new RegType(RegType::kRegTypeUninitializedReference,
239 klass, allocation_pc, entries_.size());
240 }
241 entries_.push_back(entry);
242 return *entry;
243}
244
245const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
246 RegType* entry;
247 if (uninit_type.IsUnresolvedTypes()) {
248 String* descriptor = uninit_type.GetDescriptor();
249 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
250 RegType* cur_entry = entries_[i];
251 if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
252 return *cur_entry;
253 }
254 }
255 entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
256 } else {
257 Class* klass = uninit_type.GetClass();
258 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
259 RegType* cur_entry = entries_[i];
Ian Rogersb4903572012-10-11 11:52:56 -0700260 if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700261 return *cur_entry;
262 }
263 }
Ian Rogersb4903572012-10-11 11:52:56 -0700264 entry = new RegType(RegType::kRegTypePreciseReference, klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700265 }
266 entries_.push_back(entry);
267 return *entry;
268}
269
Ian Rogersad0b3a32012-04-16 14:50:24 -0700270const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
271 // TODO: implement descriptor version.
272 RegType* entry;
273 if (type.IsUnresolvedTypes()) {
274 String* descriptor = type.GetDescriptor();
275 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
276 RegType* cur_entry = entries_[i];
277 if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
278 cur_entry->GetDescriptor() == descriptor) {
279 return *cur_entry;
280 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700281 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700282 entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedThisReference, descriptor, 0,
283 entries_.size());
284 } else {
285 Class* klass = type.GetClass();
286 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
287 RegType* cur_entry = entries_[i];
288 if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
289 return *cur_entry;
290 }
291 }
292 entry = new RegType(RegType::kRegTypeUninitializedThisReference, klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700293 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700294 entries_.push_back(entry);
295 return *entry;
296}
297
298const RegType& RegTypeCache::FromType(RegType::Type type) {
299 CHECK(type < RegType::kRegTypeReference);
300 switch (type) {
Ian Rogersb4903572012-10-11 11:52:56 -0700301 case RegType::kRegTypeBoolean: return From(type, NULL, "Z", true);
302 case RegType::kRegTypeByte: return From(type, NULL, "B", true);
303 case RegType::kRegTypeShort: return From(type, NULL, "S", true);
304 case RegType::kRegTypeChar: return From(type, NULL, "C", true);
305 case RegType::kRegTypeInteger: return From(type, NULL, "I", true);
306 case RegType::kRegTypeFloat: return From(type, NULL, "F", true);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700307 case RegType::kRegTypeLongLo:
Ian Rogersb4903572012-10-11 11:52:56 -0700308 case RegType::kRegTypeLongHi: return From(type, NULL, "J", true);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700309 case RegType::kRegTypeDoubleLo:
Ian Rogersb4903572012-10-11 11:52:56 -0700310 case RegType::kRegTypeDoubleHi: return From(type, NULL, "D", true);
311 default: return From(type, NULL, "", true);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700312 }
313}
314
315const RegType& RegTypeCache::FromCat1Const(int32_t value) {
316 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
317 RegType* cur_entry = entries_[i];
318 if (cur_entry->IsConstant() && cur_entry->ConstantValue() == value) {
319 return *cur_entry;
320 }
321 }
322 RegType* entry = new RegType(RegType::kRegTypeConst, NULL, value, entries_.size());
323 entries_.push_back(entry);
324 return *entry;
325}
326
Ian Rogers365c1022012-06-22 15:05:28 -0700327const RegType& RegTypeCache::GetComponentType(const RegType& array, ClassLoader* loader) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700328 CHECK(array.IsArrayTypes());
329 if (array.IsUnresolvedTypes()) {
330 std::string descriptor(array.GetDescriptor()->ToModifiedUtf8());
331 std::string component(descriptor.substr(1, descriptor.size() - 1));
Ian Rogersb4903572012-10-11 11:52:56 -0700332 return FromDescriptor(loader, component.c_str(), false);
Ian Rogers776ac1f2012-04-13 23:36:36 -0700333 } else {
Ian Rogersb4903572012-10-11 11:52:56 -0700334 Class* klass = array.GetClass()->GetComponentType();
335 return FromClass(klass, klass->IsFinal());
336 }
337}
338
339void RegTypeCache::Dump(std::ostream& os) {
340 os << "Register Types:\n";
341 for (size_t i = 0; i < entries_.size(); i++) {
342 RegType* cur_entry = entries_[i];
343 if (cur_entry != NULL) {
344 os << "\t" << i << ": " << cur_entry->Dump() << "\n";
345 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700346 }
347}
348
Elliott Hughesa21039c2012-06-21 12:09:25 -0700349} // namespace verifier
350} // namespace art