blob: 7ee196021362d4fc67bf0e459dc159f2604f8edd [file] [log] [blame]
Shih-wei Liao2d831012011-09-28 22:06:53 -07001/*
Elliott Hughes0f3c5532012-03-30 14:51:51 -07002 * Copyright (C) 2012 The Android Open Source Project
Shih-wei Liao2d831012011-09-28 22:06:53 -07003 *
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 "runtime_support.h"
18
TDYa1275bb86012012-04-11 05:57:28 -070019#include "ScopedLocalRef.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070020#include "well_known_classes.h"
TDYa1275bb86012012-04-11 05:57:28 -070021
jeffhao41005dd2012-05-09 17:58:52 -070022double art_l2d(int64_t l) {
Elliott Hughes74847412012-06-20 18:10:21 -070023 return static_cast<double>(l);
jeffhao41005dd2012-05-09 17:58:52 -070024}
25
26float art_l2f(int64_t l) {
Elliott Hughes74847412012-06-20 18:10:21 -070027 return static_cast<float>(l);
jeffhao41005dd2012-05-09 17:58:52 -070028}
Shih-wei Liao2d831012011-09-28 22:06:53 -070029
Ian Rogers776ac1f2012-04-13 23:36:36 -070030/*
31 * Float/double conversion requires clamping to min and max of integer form. If
32 * target doesn't support this normally, use these.
33 */
jeffhao41005dd2012-05-09 17:58:52 -070034int64_t art_d2l(double d) {
Elliott Hughes74847412012-06-20 18:10:21 -070035 static const double kMaxLong = static_cast<double>(static_cast<int64_t>(0x7fffffffffffffffULL));
36 static const double kMinLong = static_cast<double>(static_cast<int64_t>(0x8000000000000000ULL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070037 if (d >= kMaxLong) {
Logan Chien008fa512012-06-22 08:09:57 -070038 return static_cast<int64_t>(0x7fffffffffffffffULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070039 } else if (d <= kMinLong) {
Logan Chien008fa512012-06-22 08:09:57 -070040 return static_cast<int64_t>(0x8000000000000000ULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070041 } else if (d != d) { // NaN case
42 return 0;
43 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070044 return static_cast<int64_t>(d);
Ian Rogers776ac1f2012-04-13 23:36:36 -070045 }
46}
47
jeffhao41005dd2012-05-09 17:58:52 -070048int64_t art_f2l(float f) {
Elliott Hughes74847412012-06-20 18:10:21 -070049 static const float kMaxLong = static_cast<float>(static_cast<int64_t>(0x7fffffffffffffffULL));
50 static const float kMinLong = static_cast<float>(static_cast<int64_t>(0x8000000000000000ULL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070051 if (f >= kMaxLong) {
Logan Chien008fa512012-06-22 08:09:57 -070052 return static_cast<int64_t>(0x7fffffffffffffffULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070053 } else if (f <= kMinLong) {
Logan Chien008fa512012-06-22 08:09:57 -070054 return static_cast<int64_t>(0x8000000000000000ULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070055 } else if (f != f) { // NaN case
56 return 0;
57 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070058 return static_cast<int64_t>(f);
Ian Rogers776ac1f2012-04-13 23:36:36 -070059 }
60}
61
jeffhao41005dd2012-05-09 17:58:52 -070062int32_t art_d2i(double d) {
Logan Chien008fa512012-06-22 08:09:57 -070063 static const double kMaxInt = static_cast<double>(static_cast<int32_t>(0x7fffffffUL));
64 static const double kMinInt = static_cast<double>(static_cast<int32_t>(0x80000000UL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070065 if (d >= kMaxInt) {
Logan Chien008fa512012-06-22 08:09:57 -070066 return static_cast<int32_t>(0x7fffffffUL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070067 } else if (d <= kMinInt) {
Logan Chien008fa512012-06-22 08:09:57 -070068 return static_cast<int32_t>(0x80000000UL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070069 } else if (d != d) { // NaN case
70 return 0;
71 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070072 return static_cast<int32_t>(d);
Ian Rogers776ac1f2012-04-13 23:36:36 -070073 }
74}
75
jeffhao41005dd2012-05-09 17:58:52 -070076int32_t art_f2i(float f) {
Logan Chien008fa512012-06-22 08:09:57 -070077 static const float kMaxInt = static_cast<float>(static_cast<int32_t>(0x7fffffffUL));
78 static const float kMinInt = static_cast<float>(static_cast<int32_t>(0x80000000UL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070079 if (f >= kMaxInt) {
Logan Chien008fa512012-06-22 08:09:57 -070080 return static_cast<int32_t>(0x7fffffffUL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070081 } else if (f <= kMinInt) {
Logan Chien008fa512012-06-22 08:09:57 -070082 return static_cast<int32_t>(0x80000000UL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070083 } else if (f != f) { // NaN case
84 return 0;
85 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070086 return static_cast<int32_t>(f);
Ian Rogers776ac1f2012-04-13 23:36:36 -070087 }
88}
89
jeffhao41005dd2012-05-09 17:58:52 -070090namespace art {
91
Ian Rogers57b86d42012-03-27 16:05:41 -070092// Helper function to allocate array for FILLED_NEW_ARRAY.
Mathieu Chartier66f19252012-09-18 08:57:04 -070093Array* CheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count,
Ian Rogers57b86d42012-03-27 16:05:41 -070094 Thread* self, bool access_check) {
95 if (UNLIKELY(component_count < 0)) {
96 self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
97 return NULL; // Failure
Elliott Hughes6c8867d2011-10-03 16:34:05 -070098 }
Ian Rogers57b86d42012-03-27 16:05:41 -070099 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
100 if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve
101 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
102 if (klass == NULL) { // Error
Ian Rogers50b35e22012-10-04 10:09:15 -0700103 DCHECK(self->IsExceptionPending());
Ian Rogers57b86d42012-03-27 16:05:41 -0700104 return NULL; // Failure
Ian Rogers19846512012-02-24 11:42:47 -0800105 }
Ian Rogersea2a11d2011-10-11 16:48:51 -0700106 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700107 if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
108 if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700109 self->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
110 "Bad filled array request for type %s",
111 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800112 } else {
Ian Rogers50b35e22012-10-04 10:09:15 -0700113 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
114 "Found type %s; filled-new-array not implemented for anything but \'int\'",
115 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800116 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700117 return NULL; // Failure
Ian Rogersad25ac52011-10-04 19:13:33 -0700118 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700119 if (access_check) {
120 Class* referrer = method->GetDeclaringClass();
121 if (UNLIKELY(!referrer->CanAccess(klass))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700122 ThrowIllegalAccessErrorClass(referrer, klass);
Ian Rogers57b86d42012-03-27 16:05:41 -0700123 return NULL; // Failure
124 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800125 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700126 DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
Ian Rogers50b35e22012-10-04 10:09:15 -0700127 return Array::Alloc(self, klass, component_count);
Ian Rogers57b86d42012-03-27 16:05:41 -0700128 }
129}
130
Mathieu Chartier66f19252012-09-18 08:57:04 -0700131Field* FindFieldFromCode(uint32_t field_idx, const AbstractMethod* referrer, Thread* self,
Ian Rogers08f753d2012-08-24 14:35:25 -0700132 FindFieldType type, size_t expected_size) {
133 bool is_primitive;
134 bool is_set;
135 bool is_static;
136 switch (type) {
137 case InstanceObjectRead: is_primitive = false; is_set = false; is_static = false; break;
138 case InstanceObjectWrite: is_primitive = false; is_set = true; is_static = false; break;
139 case InstancePrimitiveRead: is_primitive = true; is_set = false; is_static = false; break;
140 case InstancePrimitiveWrite: is_primitive = true; is_set = true; is_static = false; break;
141 case StaticObjectRead: is_primitive = false; is_set = false; is_static = true; break;
142 case StaticObjectWrite: is_primitive = false; is_set = true; is_static = true; break;
143 case StaticPrimitiveRead: is_primitive = true; is_set = false; is_static = true; break;
144 case StaticPrimitiveWrite: // Keep GCC happy by having a default handler, fall-through.
145 default: is_primitive = true; is_set = true; is_static = true; break;
146 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700147 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
148 Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
149 if (UNLIKELY(resolved_field == NULL)) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700150 DCHECK(self->IsExceptionPending()); // Throw exception and unwind.
151 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700152 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700153 if (resolved_field->IsStatic() != is_static) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700154 ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700155 return NULL;
156 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700157 Class* fields_class = resolved_field->GetDeclaringClass();
158 Class* referring_class = referrer->GetDeclaringClass();
Ian Rogerse2645d32012-04-11 14:42:42 -0700159 if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
160 !referring_class->CanAccessMember(fields_class,
161 resolved_field->GetAccessFlags()))) {
162 // The referring class can't access the resolved field, this may occur as a result of a
163 // protected field being made public by a sub-class. Resort to the dex file to determine
164 // the correct class for the access check.
Ian Rogers4445a7e2012-10-05 17:19:13 -0700165 const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
Ian Rogerse2645d32012-04-11 14:42:42 -0700166 fields_class = class_linker->ResolveType(dex_file,
167 dex_file.GetFieldId(field_idx).class_idx_,
168 referring_class);
169 if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700170 ThrowIllegalAccessErrorClass(referring_class, fields_class);
Ian Rogerse2645d32012-04-11 14:42:42 -0700171 return NULL; // failure
172 } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
173 resolved_field->GetAccessFlags()))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700174 ThrowIllegalAccessErrorField(referring_class, resolved_field);
Ian Rogerse2645d32012-04-11 14:42:42 -0700175 return NULL; // failure
176 }
177 }
178 if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700179 ThrowIllegalAccessErrorFinalField(referrer, resolved_field);
Ian Rogers57b86d42012-03-27 16:05:41 -0700180 return NULL; // failure
181 } else {
182 FieldHelper fh(resolved_field);
183 if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
184 fh.FieldSize() != expected_size)) {
185 self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
186 "Attempted read of %zd-bit %s on field '%s'",
187 expected_size * (32 / sizeof(int32_t)),
188 is_primitive ? "primitive" : "non-primitive",
189 PrettyField(resolved_field, true).c_str());
190 return NULL; // failure
191 } else if (!is_static) {
192 // instance fields must be being accessed on an initialized class
193 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800194 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700195 // If the class is already initializing, we must be inside <clinit>, or
196 // we'd still be waiting for the lock.
197 if (fields_class->IsInitializing()) {
198 return resolved_field;
Ian Rogers0045a292012-03-31 21:08:41 -0700199 } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700200 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800201 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700202 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
203 return NULL; // failure
Ian Rogers60db5ab2012-02-20 17:02:00 -0800204 }
205 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700206 }
207 }
208}
209
210// Slow path method resolution
Mathieu Chartier66f19252012-09-18 08:57:04 -0700211AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, const AbstractMethod* referrer,
Ian Rogers57b86d42012-03-27 16:05:41 -0700212 Thread* self, bool access_check, InvokeType type) {
213 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
214 bool is_direct = type == kStatic || type == kDirect;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700215 AbstractMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type);
Ian Rogers57b86d42012-03-27 16:05:41 -0700216 if (UNLIKELY(resolved_method == NULL)) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700217 DCHECK(self->IsExceptionPending()); // Throw exception and unwind.
218 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700219 } else {
220 if (!access_check) {
221 if (is_direct) {
222 return resolved_method;
223 } else if (type == kInterface) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700224 AbstractMethod* interface_method =
Ian Rogers57b86d42012-03-27 16:05:41 -0700225 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
226 if (UNLIKELY(interface_method == NULL)) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700227 ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
228 referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700229 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700230 } else {
231 return interface_method;
232 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800233 } else {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700234 ObjectArray<AbstractMethod>* vtable;
Ian Rogers57b86d42012-03-27 16:05:41 -0700235 uint16_t vtable_index = resolved_method->GetMethodIndex();
236 if (type == kSuper) {
237 vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
238 } else {
239 vtable = this_object->GetClass()->GetVTable();
240 }
241 // TODO: eliminate bounds check?
242 return vtable->Get(vtable_index);
243 }
244 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700245 // Incompatible class change should have been handled in resolve method.
246 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
Ian Rogers2fc14272012-08-30 10:56:57 -0700247 ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method,
248 referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700249 return NULL; // Failure.
250 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700251 Class* methods_class = resolved_method->GetDeclaringClass();
252 Class* referring_class = referrer->GetDeclaringClass();
253 if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
254 !referring_class->CanAccessMember(methods_class,
255 resolved_method->GetAccessFlags()))) {
256 // The referring class can't access the resolved method, this may occur as a result of a
257 // protected method being made public by implementing an interface that re-declares the
258 // method public. Resort to the dex file to determine the correct class for the access check
Ian Rogers4445a7e2012-10-05 17:19:13 -0700259 const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
Ian Rogers57b86d42012-03-27 16:05:41 -0700260 methods_class = class_linker->ResolveType(dex_file,
261 dex_file.GetMethodId(method_idx).class_idx_,
262 referring_class);
263 if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700264 ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
265 referrer, resolved_method, type);
Ian Rogers08f753d2012-08-24 14:35:25 -0700266 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700267 } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
268 resolved_method->GetAccessFlags()))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700269 ThrowIllegalAccessErrorMethod(referring_class, resolved_method);
Ian Rogers08f753d2012-08-24 14:35:25 -0700270 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700271 }
272 }
273 if (is_direct) {
274 return resolved_method;
275 } else if (type == kInterface) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700276 AbstractMethod* interface_method =
Ian Rogers57b86d42012-03-27 16:05:41 -0700277 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
278 if (UNLIKELY(interface_method == NULL)) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700279 ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
280 referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700281 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700282 } else {
283 return interface_method;
284 }
285 } else {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700286 ObjectArray<AbstractMethod>* vtable;
Ian Rogers57b86d42012-03-27 16:05:41 -0700287 uint16_t vtable_index = resolved_method->GetMethodIndex();
288 if (type == kSuper) {
289 Class* super_class = referring_class->GetSuperClass();
290 if (LIKELY(super_class != NULL)) {
291 vtable = referring_class->GetSuperClass()->GetVTable();
292 } else {
293 vtable = NULL;
294 }
295 } else {
296 vtable = this_object->GetClass()->GetVTable();
297 }
298 if (LIKELY(vtable != NULL &&
299 vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
300 return vtable->GetWithoutChecks(vtable_index);
301 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700302 // Behavior to agree with that of the verifier.
303 MethodHelper mh(resolved_method);
304 ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(),
Ian Rogers2fc14272012-08-30 10:56:57 -0700305 mh.GetSignature(), referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700306 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700307 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800308 }
309 }
310 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800311}
312
Mathieu Chartier66f19252012-09-18 08:57:04 -0700313Class* ResolveVerifyAndClinit(uint32_t type_idx, const AbstractMethod* referrer, Thread* self,
Ian Rogers57b86d42012-03-27 16:05:41 -0700314 bool can_run_clinit, bool verify_access) {
315 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
316 Class* klass = class_linker->ResolveType(type_idx, referrer);
317 if (UNLIKELY(klass == NULL)) {
jeffhao441d9122012-03-21 17:29:10 -0700318 CHECK(self->IsExceptionPending());
Ian Rogers57b86d42012-03-27 16:05:41 -0700319 return NULL; // Failure - Indicate to caller to deliver exception
jeffhao441d9122012-03-21 17:29:10 -0700320 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700321 // Perform access check if necessary.
322 Class* referring_class = referrer->GetDeclaringClass();
323 if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700324 ThrowIllegalAccessErrorClass(referring_class, klass);
Ian Rogers57b86d42012-03-27 16:05:41 -0700325 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogers14b1b242011-10-11 18:54:34 -0700326 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700327 // If we're just implementing const-class, we shouldn't call <clinit>.
328 if (!can_run_clinit) {
329 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700330 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700331 // If we are the <clinit> of this class, just return our storage.
332 //
333 // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
334 // running.
335 if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) {
336 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700337 }
Ian Rogers0045a292012-03-31 21:08:41 -0700338 if (!class_linker->EnsureInitialized(klass, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700339 CHECK(self->IsExceptionPending());
340 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700341 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700342 referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
343 return klass;
Shih-wei Liao2d831012011-09-28 22:06:53 -0700344}
345
Shih-wei Liao2d831012011-09-28 22:06:53 -0700346} // namespace art