blob: c860bd72ba83fc2bc0870094fa9b79039159b830 [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
60const RegType& RegTypeCache::FromDescriptor(const ClassLoader* loader,
61 const char* descriptor) {
62 return From(RegTypeFromDescriptor(descriptor), loader, descriptor);
63}
64
65const RegType& RegTypeCache::From(RegType::Type type, const ClassLoader* loader,
66 const char* descriptor) {
67 if (type <= RegType::kRegTypeLastFixedLocation) {
68 // entries should be sized greater than primitive types
69 DCHECK_GT(entries_.size(), static_cast<size_t>(type));
70 RegType* entry = entries_[type];
71 if (entry == NULL) {
72 Class* klass = NULL;
73 if (strlen(descriptor) != 0) {
74 klass = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor);
75 }
76 entry = new RegType(type, klass, 0, type);
77 entries_[type] = entry;
78 }
79 return *entry;
80 } else {
81 DCHECK(type == RegType::kRegTypeReference);
82 ClassHelper kh;
83 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
84 RegType* cur_entry = entries_[i];
85 // check resolved and unresolved references, ignore uninitialized references
86 if (cur_entry->IsReference()) {
87 kh.ChangeClass(cur_entry->GetClass());
88 if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
89 return *cur_entry;
90 }
91 } else if (cur_entry->IsUnresolvedReference() &&
92 cur_entry->GetDescriptor()->Equals(descriptor)) {
93 return *cur_entry;
94 }
95 }
96 Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, loader);
97 if (klass != NULL) {
98 // Able to resolve so create resolved register type
99 RegType* entry = new RegType(type, klass, 0, entries_.size());
100 entries_.push_back(entry);
101 return *entry;
102 } else {
103 // TODO: we assume unresolved, but we may be able to do better by validating whether the
104 // descriptor string is valid
105 // Unable to resolve so create unresolved register type
106 DCHECK(Thread::Current()->IsExceptionPending());
107 Thread::Current()->ClearException();
108 if (IsValidDescriptor(descriptor)) {
109 String* string_descriptor =
110 Runtime::Current()->GetInternTable()->InternStrong(descriptor);
111 RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, string_descriptor, 0,
112 entries_.size());
113 entries_.push_back(entry);
114 return *entry;
115 } else {
116 // The descriptor is broken return the unknown type as there's nothing sensible that
117 // could be done at runtime
Ian Rogersad0b3a32012-04-16 14:50:24 -0700118 return Conflict();
Ian Rogers776ac1f2012-04-13 23:36:36 -0700119 }
120 }
121 }
122}
123
124const RegType& RegTypeCache::FromClass(Class* klass) {
125 if (klass->IsPrimitive()) {
126 RegType::Type type = RegTypeFromPrimitiveType(klass->GetPrimitiveType());
127 // entries should be sized greater than primitive types
128 DCHECK_GT(entries_.size(), static_cast<size_t>(type));
129 RegType* entry = entries_[type];
130 if (entry == NULL) {
131 entry = new RegType(type, klass, 0, type);
132 entries_[type] = entry;
133 }
134 return *entry;
135 } else {
136 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
137 RegType* cur_entry = entries_[i];
138 if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
139 return *cur_entry;
140 }
141 }
142 RegType* entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
143 entries_.push_back(entry);
144 return *entry;
145 }
146}
147
148const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
149 RegType* entry;
150 if (type.IsUnresolvedTypes()) {
151 String* descriptor = type.GetDescriptor();
152 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
153 RegType* cur_entry = entries_[i];
154 if (cur_entry->IsUnresolvedAndUninitializedReference() &&
155 cur_entry->GetAllocationPc() == allocation_pc &&
156 cur_entry->GetDescriptor() == descriptor) {
157 return *cur_entry;
158 }
159 }
160 entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedReference,
161 descriptor, allocation_pc, entries_.size());
162 } else {
163 Class* klass = type.GetClass();
164 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
165 RegType* cur_entry = entries_[i];
166 if (cur_entry->IsUninitializedReference() &&
167 cur_entry->GetAllocationPc() == allocation_pc &&
168 cur_entry->GetClass() == klass) {
169 return *cur_entry;
170 }
171 }
172 entry = new RegType(RegType::kRegTypeUninitializedReference,
173 klass, allocation_pc, entries_.size());
174 }
175 entries_.push_back(entry);
176 return *entry;
177}
178
179const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
180 RegType* entry;
181 if (uninit_type.IsUnresolvedTypes()) {
182 String* descriptor = uninit_type.GetDescriptor();
183 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
184 RegType* cur_entry = entries_[i];
185 if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
186 return *cur_entry;
187 }
188 }
189 entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
190 } else {
191 Class* klass = uninit_type.GetClass();
192 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
193 RegType* cur_entry = entries_[i];
194 if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
195 return *cur_entry;
196 }
197 }
198 entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
199 }
200 entries_.push_back(entry);
201 return *entry;
202}
203
Ian Rogersad0b3a32012-04-16 14:50:24 -0700204const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
205 // TODO: implement descriptor version.
206 RegType* entry;
207 if (type.IsUnresolvedTypes()) {
208 String* descriptor = type.GetDescriptor();
209 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
210 RegType* cur_entry = entries_[i];
211 if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
212 cur_entry->GetDescriptor() == descriptor) {
213 return *cur_entry;
214 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700215 }
Ian Rogersad0b3a32012-04-16 14:50:24 -0700216 entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedThisReference, descriptor, 0,
217 entries_.size());
218 } else {
219 Class* klass = type.GetClass();
220 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
221 RegType* cur_entry = entries_[i];
222 if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
223 return *cur_entry;
224 }
225 }
226 entry = new RegType(RegType::kRegTypeUninitializedThisReference, klass, 0, entries_.size());
Ian Rogers776ac1f2012-04-13 23:36:36 -0700227 }
Ian Rogers776ac1f2012-04-13 23:36:36 -0700228 entries_.push_back(entry);
229 return *entry;
230}
231
232const RegType& RegTypeCache::FromType(RegType::Type type) {
233 CHECK(type < RegType::kRegTypeReference);
234 switch (type) {
235 case RegType::kRegTypeBoolean: return From(type, NULL, "Z");
236 case RegType::kRegTypeByte: return From(type, NULL, "B");
237 case RegType::kRegTypeShort: return From(type, NULL, "S");
238 case RegType::kRegTypeChar: return From(type, NULL, "C");
239 case RegType::kRegTypeInteger: return From(type, NULL, "I");
240 case RegType::kRegTypeFloat: return From(type, NULL, "F");
241 case RegType::kRegTypeLongLo:
242 case RegType::kRegTypeLongHi: return From(type, NULL, "J");
243 case RegType::kRegTypeDoubleLo:
244 case RegType::kRegTypeDoubleHi: return From(type, NULL, "D");
245 default: return From(type, NULL, "");
246 }
247}
248
249const RegType& RegTypeCache::FromCat1Const(int32_t value) {
250 for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
251 RegType* cur_entry = entries_[i];
252 if (cur_entry->IsConstant() && cur_entry->ConstantValue() == value) {
253 return *cur_entry;
254 }
255 }
256 RegType* entry = new RegType(RegType::kRegTypeConst, NULL, value, entries_.size());
257 entries_.push_back(entry);
258 return *entry;
259}
260
261const RegType& RegTypeCache::GetComponentType(const RegType& array, const ClassLoader* loader) {
262 CHECK(array.IsArrayTypes());
263 if (array.IsUnresolvedTypes()) {
264 std::string descriptor(array.GetDescriptor()->ToModifiedUtf8());
265 std::string component(descriptor.substr(1, descriptor.size() - 1));
266 return FromDescriptor(loader, component.c_str());
267 } else {
268 return FromClass(array.GetClass()->GetComponentType());
269 }
270}
271
Elliott Hughesa21039c2012-06-21 12:09:25 -0700272} // namespace verifier
273} // namespace art