blob: 37086c9acc6ac155891598c320cb2373d4d2e993 [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 Rogers365c1022012-06-22 15:05:28 -070060const RegType& RegTypeCache::FromDescriptor(ClassLoader* loader, const char* descriptor) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070061 return From(RegTypeFromDescriptor(descriptor), loader, descriptor);
62}
63
Ian Rogers365c1022012-06-22 15:05:28 -070064const RegType& RegTypeCache::From(RegType::Type type, ClassLoader* loader, const char* descriptor) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070065 if (type <= RegType::kRegTypeLastFixedLocation) {
66 // entries should be sized greater than primitive types
67 DCHECK_GT(entries_.size(), static_cast<size_t>(type));
68 RegType* entry = entries_[type];
69 if (entry == NULL) {
70 Class* klass = NULL;
71 if (strlen(descriptor) != 0) {
72 klass = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor);
73 }
74 entry = new RegType(type, klass, 0, type);
75 entries_[type] = entry;
76 }
77 return *entry;
78 } else {
79 DCHECK(type == RegType::kRegTypeReference);
80 ClassHelper kh;
81 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
82 RegType* cur_entry = entries_[i];
83 // check resolved and unresolved references, ignore uninitialized references
84 if (cur_entry->IsReference()) {
85 kh.ChangeClass(cur_entry->GetClass());
86 if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
87 return *cur_entry;
88 }
89 } else if (cur_entry->IsUnresolvedReference() &&
90 cur_entry->GetDescriptor()->Equals(descriptor)) {
91 return *cur_entry;
92 }
93 }
94 Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, loader);
95 if (klass != NULL) {
96 // Able to resolve so create resolved register type
97 RegType* entry = new RegType(type, klass, 0, entries_.size());
98 entries_.push_back(entry);
99 return *entry;
100 } else {
101 // TODO: we assume unresolved, but we may be able to do better by validating whether the
102 // descriptor string is valid
103 // Unable to resolve so create unresolved register type
104 DCHECK(Thread::Current()->IsExceptionPending());
105 Thread::Current()->ClearException();
106 if (IsValidDescriptor(descriptor)) {
107 String* string_descriptor =
108 Runtime::Current()->GetInternTable()->InternStrong(descriptor);
109 RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, string_descriptor, 0,
110 entries_.size());
111 entries_.push_back(entry);
112 return *entry;
113 } else {
114 // The descriptor is broken return the unknown type as there's nothing sensible that
115 // could be done at runtime
Ian Rogersad0b3a32012-04-16 14:50:24 -0700116 return Conflict();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700117 }
118 }
119 }
120}
121
122const RegType& RegTypeCache::FromClass(Class* klass) {
123 if (klass->IsPrimitive()) {
124 RegType::Type type = RegTypeFromPrimitiveType(klass->GetPrimitiveType());
125 // entries should be sized greater than primitive types
126 DCHECK_GT(entries_.size(), static_cast<size_t>(type));
127 RegType* entry = entries_[type];
128 if (entry == NULL) {
129 entry = new RegType(type, klass, 0, type);
130 entries_[type] = entry;
131 }
132 return *entry;
133 } else {
134 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
135 RegType* cur_entry = entries_[i];
136 if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
137 return *cur_entry;
138 }
139 }
140 RegType* entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
141 entries_.push_back(entry);
142 return *entry;
143 }
144}
145
Ian Rogers529781d2012-07-23 17:24:29 -0700146const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left, const RegType& right) {
147 std::set<uint16_t> types;
148 if (left.IsUnresolvedMergedReference()) {
149 types = left.GetMergedTypes(this);
150 } else {
151 types.insert(left.GetId());
152 }
153 if (right.IsUnresolvedMergedReference()) {
154 std::set<uint16_t> right_types = right.GetMergedTypes(this);
155 types.insert(right_types.begin(), right_types.end());
156 } else {
157 types.insert(right.GetId());
158 }
159 // Check if entry already exists.
160 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
161 RegType* cur_entry = entries_[i];
162 if (cur_entry->IsUnresolvedMergedReference()) {
163 std::set<uint16_t> cur_entry_types = cur_entry->GetMergedTypes(this);
164 if (cur_entry_types == types) {
165 return *cur_entry;
166 }
167 }
168 }
169 // Create entry.
170 uint32_t merged_ids = static_cast<uint32_t>(left.GetId()) << 16 |
171 static_cast<uint32_t>(right.GetId());
172 RegType* entry = new RegType(RegType::kRegTypeUnresolvedMergedReference, NULL, merged_ids,
173 entries_.size());
174 entries_.push_back(entry);
175#ifndef DEBUG
176 std::set<uint16_t> check_types = entry->GetMergedTypes(this);
177 CHECK(check_types == types);
178#endif
179 return *entry;
180}
181
182const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
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->IsUnresolvedSuperClass()) {
187 uint16_t unresolved_super_child_id = cur_entry->GetUnresolvedSuperClassChildId();
188 if (unresolved_super_child_id == child.GetId()) {
189 return *cur_entry;
190 }
191 }
192 }
193 // Create entry.
194 RegType* entry = new RegType(RegType::kRegTypeUnresolvedSuperClass, NULL, child.GetId(),
195 entries_.size());
196 entries_.push_back(entry);
197 return *entry;
198}
199
Ian Rogers776ac1f2012-04-13 23:36:36 -0700200const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
201 RegType* entry;
202 if (type.IsUnresolvedTypes()) {
203 String* descriptor = type.GetDescriptor();
204 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
205 RegType* cur_entry = entries_[i];
206 if (cur_entry->IsUnresolvedAndUninitializedReference() &&
207 cur_entry->GetAllocationPc() == allocation_pc &&
208 cur_entry->GetDescriptor() == descriptor) {
209 return *cur_entry;
210 }
211 }
212 entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedReference,
213 descriptor, allocation_pc, entries_.size());
214 } else {
215 Class* klass = type.GetClass();
216 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
217 RegType* cur_entry = entries_[i];
218 if (cur_entry->IsUninitializedReference() &&
219 cur_entry->GetAllocationPc() == allocation_pc &&
220 cur_entry->GetClass() == klass) {
221 return *cur_entry;
222 }
223 }
224 entry = new RegType(RegType::kRegTypeUninitializedReference,
225 klass, allocation_pc, entries_.size());
226 }
227 entries_.push_back(entry);
228 return *entry;
229}
230
231const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
232 RegType* entry;
233 if (uninit_type.IsUnresolvedTypes()) {
234 String* descriptor = uninit_type.GetDescriptor();
235 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
236 RegType* cur_entry = entries_[i];
237 if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
238 return *cur_entry;
239 }
240 }
241 entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
242 } else {
243 Class* klass = uninit_type.GetClass();
244 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
245 RegType* cur_entry = entries_[i];
246 if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
247 return *cur_entry;
248 }
249 }
250 entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
251 }
252 entries_.push_back(entry);
253 return *entry;
254}
255
Ian Rogersad0b3a32012-04-16 14:50:24 -0700256const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
257 // TODO: implement descriptor version.
258 RegType* entry;
259 if (type.IsUnresolvedTypes()) {
260 String* descriptor = type.GetDescriptor();
261 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
262 RegType* cur_entry = entries_[i];
263 if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
264 cur_entry->GetDescriptor() == descriptor) {
265 return *cur_entry;
266 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700267 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700268 entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedThisReference, descriptor, 0,
269 entries_.size());
270 } else {
271 Class* klass = type.GetClass();
272 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
273 RegType* cur_entry = entries_[i];
274 if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
275 return *cur_entry;
276 }
277 }
278 entry = new RegType(RegType::kRegTypeUninitializedThisReference, klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700279 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700280 entries_.push_back(entry);
281 return *entry;
282}
283
284const RegType& RegTypeCache::FromType(RegType::Type type) {
285 CHECK(type < RegType::kRegTypeReference);
286 switch (type) {
287 case RegType::kRegTypeBoolean: return From(type, NULL, "Z");
288 case RegType::kRegTypeByte: return From(type, NULL, "B");
289 case RegType::kRegTypeShort: return From(type, NULL, "S");
290 case RegType::kRegTypeChar: return From(type, NULL, "C");
291 case RegType::kRegTypeInteger: return From(type, NULL, "I");
292 case RegType::kRegTypeFloat: return From(type, NULL, "F");
293 case RegType::kRegTypeLongLo:
294 case RegType::kRegTypeLongHi: return From(type, NULL, "J");
295 case RegType::kRegTypeDoubleLo:
296 case RegType::kRegTypeDoubleHi: return From(type, NULL, "D");
297 default: return From(type, NULL, "");
298 }
299}
300
301const RegType& RegTypeCache::FromCat1Const(int32_t value) {
302 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
303 RegType* cur_entry = entries_[i];
304 if (cur_entry->IsConstant() && cur_entry->ConstantValue() == value) {
305 return *cur_entry;
306 }
307 }
308 RegType* entry = new RegType(RegType::kRegTypeConst, NULL, value, entries_.size());
309 entries_.push_back(entry);
310 return *entry;
311}
312
Ian Rogers365c1022012-06-22 15:05:28 -0700313const RegType& RegTypeCache::GetComponentType(const RegType& array, ClassLoader* loader) {
Ian Rogers776ac1f2012-04-13 23:36:36 -0700314 CHECK(array.IsArrayTypes());
315 if (array.IsUnresolvedTypes()) {
316 std::string descriptor(array.GetDescriptor()->ToModifiedUtf8());
317 std::string component(descriptor.substr(1, descriptor.size() - 1));
318 return FromDescriptor(loader, component.c_str());
319 } else {
320 return FromClass(array.GetClass()->GetComponentType());
321 }
322}
323
Elliott Hughesa21039c2012-06-21 12:09:25 -0700324} // namespace verifier
325} // namespace art