entrypoint_utils.h revision d4beb6bc2b42b176c6d04fdd91d6c758e542c7c2
1/* 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#ifndef ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_ 18#define ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_ 19 20#include "base/macros.h" 21#include "class_linker.h" 22#include "common_throws.h" 23#include "dex_file.h" 24#include "indirect_reference_table.h" 25#include "invoke_type.h" 26#include "jni_internal.h" 27#include "mirror/art_method.h" 28#include "mirror/array.h" 29#include "mirror/class-inl.h" 30#include "mirror/throwable.h" 31#include "object_utils.h" 32 33#include "thread.h" 34 35namespace art { 36 37namespace mirror { 38 class Class; 39 class ArtField; 40 class Object; 41} // namespace mirror 42 43static inline bool CheckObjectAlloc(uint32_t type_idx, mirror::ArtMethod* method, 44 Thread* self, 45 bool access_check, 46 mirror::Class** klass_ptr) 47 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 48 mirror::Class* klass = method->GetDexCacheResolvedTypes()->GetWithoutChecks(type_idx); 49 Runtime* runtime = Runtime::Current(); 50 if (UNLIKELY(klass == NULL)) { 51 klass = runtime->GetClassLinker()->ResolveType(type_idx, method); 52 if (klass == NULL) { 53 DCHECK(self->IsExceptionPending()); 54 return false; // Failure 55 } 56 } 57 if (access_check) { 58 if (UNLIKELY(!klass->IsInstantiable())) { 59 ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 60 self->ThrowNewException(throw_location, "Ljava/lang/InstantiationError;", 61 PrettyDescriptor(klass).c_str()); 62 return false; // Failure 63 } 64 mirror::Class* referrer = method->GetDeclaringClass(); 65 if (UNLIKELY(!referrer->CanAccess(klass))) { 66 ThrowIllegalAccessErrorClass(referrer, klass); 67 return false; // Failure 68 } 69 } 70 if (!klass->IsInitialized() && 71 !runtime->GetClassLinker()->EnsureInitialized(klass, true, true)) { 72 DCHECK(self->IsExceptionPending()); 73 return false; // Failure 74 } 75 *klass_ptr = klass; 76 return true; 77} 78 79// Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it 80// cannot be resolved, throw an error. If it can, use it to create an instance. 81// When verification/compiler hasn't been able to verify access, optionally perform an access 82// check. 83static inline mirror::Object* AllocObjectFromCode(uint32_t type_idx, mirror::ArtMethod* method, 84 Thread* self, 85 bool access_check) 86 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 87 mirror::Class* klass; 88 if (UNLIKELY(!CheckObjectAlloc(type_idx, method, self, access_check, &klass))) { 89 return NULL; 90 } 91 return klass->AllocObjectUninstrumented(self); 92} 93 94static inline mirror::Object* AllocObjectFromCodeInstrumented(uint32_t type_idx, mirror::ArtMethod* method, 95 Thread* self, 96 bool access_check) 97 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 98 mirror::Class* klass; 99 if (UNLIKELY(!CheckObjectAlloc(type_idx, method, self, access_check, &klass))) { 100 return NULL; 101 } 102 return klass->AllocObjectInstrumented(self); 103} 104 105static inline bool CheckArrayAlloc(uint32_t type_idx, mirror::ArtMethod* method, 106 int32_t component_count, 107 bool access_check, mirror::Class** klass_ptr) 108 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 109 if (UNLIKELY(component_count < 0)) { 110 ThrowNegativeArraySizeException(component_count); 111 return false; // Failure 112 } 113 mirror::Class* klass = method->GetDexCacheResolvedTypes()->GetWithoutChecks(type_idx); 114 if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve 115 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); 116 if (klass == NULL) { // Error 117 DCHECK(Thread::Current()->IsExceptionPending()); 118 return false; // Failure 119 } 120 CHECK(klass->IsArrayClass()) << PrettyClass(klass); 121 } 122 if (access_check) { 123 mirror::Class* referrer = method->GetDeclaringClass(); 124 if (UNLIKELY(!referrer->CanAccess(klass))) { 125 ThrowIllegalAccessErrorClass(referrer, klass); 126 return false; // Failure 127 } 128 } 129 *klass_ptr = klass; 130 return true; 131} 132 133// Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If 134// it cannot be resolved, throw an error. If it can, use it to create an array. 135// When verification/compiler hasn't been able to verify access, optionally perform an access 136// check. 137static inline mirror::Array* AllocArrayFromCode(uint32_t type_idx, mirror::ArtMethod* method, 138 int32_t component_count, 139 Thread* self, bool access_check) 140 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 141 mirror::Class* klass; 142 if (UNLIKELY(!CheckArrayAlloc(type_idx, method, component_count, access_check, &klass))) { 143 return NULL; 144 } 145 return mirror::Array::AllocUninstrumented(self, klass, component_count); 146} 147 148static inline mirror::Array* AllocArrayFromCodeInstrumented(uint32_t type_idx, mirror::ArtMethod* method, 149 int32_t component_count, 150 Thread* self, bool access_check) 151 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 152 mirror::Class* klass; 153 if (UNLIKELY(!CheckArrayAlloc(type_idx, method, component_count, access_check, &klass))) { 154 return NULL; 155 } 156 return mirror::Array::AllocInstrumented(self, klass, component_count); 157} 158 159extern mirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, mirror::ArtMethod* method, 160 int32_t component_count, 161 Thread* self, bool access_check) 162 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 163 164extern mirror::Array* CheckAndAllocArrayFromCodeInstrumented(uint32_t type_idx, mirror::ArtMethod* method, 165 int32_t component_count, 166 Thread* self, bool access_check) 167 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 168 169// Type of find field operation for fast and slow case. 170enum FindFieldType { 171 InstanceObjectRead, 172 InstanceObjectWrite, 173 InstancePrimitiveRead, 174 InstancePrimitiveWrite, 175 StaticObjectRead, 176 StaticObjectWrite, 177 StaticPrimitiveRead, 178 StaticPrimitiveWrite, 179}; 180 181template<FindFieldType type, bool access_check> 182static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirror::ArtMethod* referrer, 183 Thread* self, size_t expected_size) { 184 bool is_primitive; 185 bool is_set; 186 bool is_static; 187 switch (type) { 188 case InstanceObjectRead: is_primitive = false; is_set = false; is_static = false; break; 189 case InstanceObjectWrite: is_primitive = false; is_set = true; is_static = false; break; 190 case InstancePrimitiveRead: is_primitive = true; is_set = false; is_static = false; break; 191 case InstancePrimitiveWrite: is_primitive = true; is_set = true; is_static = false; break; 192 case StaticObjectRead: is_primitive = false; is_set = false; is_static = true; break; 193 case StaticObjectWrite: is_primitive = false; is_set = true; is_static = true; break; 194 case StaticPrimitiveRead: is_primitive = true; is_set = false; is_static = true; break; 195 case StaticPrimitiveWrite: // Keep GCC happy by having a default handler, fall-through. 196 default: is_primitive = true; is_set = true; is_static = true; break; 197 } 198 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 199 mirror::ArtField* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static); 200 if (UNLIKELY(resolved_field == nullptr)) { 201 DCHECK(self->IsExceptionPending()); // Throw exception and unwind. 202 return nullptr; // Failure. 203 } 204 mirror::Class* fields_class = resolved_field->GetDeclaringClass(); 205 if (access_check) { 206 if (UNLIKELY(resolved_field->IsStatic() != is_static)) { 207 ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer); 208 return nullptr; 209 } 210 mirror::Class* referring_class = referrer->GetDeclaringClass(); 211 if (UNLIKELY(!referring_class->CanAccess(fields_class) || 212 !referring_class->CanAccessMember(fields_class, 213 resolved_field->GetAccessFlags()))) { 214 // The referring class can't access the resolved field, this may occur as a result of a 215 // protected field being made public by a sub-class. Resort to the dex file to determine 216 // the correct class for the access check. 217 const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile(); 218 fields_class = class_linker->ResolveType(dex_file, 219 dex_file.GetFieldId(field_idx).class_idx_, 220 referring_class); 221 if (UNLIKELY(!referring_class->CanAccess(fields_class))) { 222 ThrowIllegalAccessErrorClass(referring_class, fields_class); 223 return nullptr; // failure 224 } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class, 225 resolved_field->GetAccessFlags()))) { 226 ThrowIllegalAccessErrorField(referring_class, resolved_field); 227 return nullptr; // failure 228 } 229 } 230 if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) { 231 ThrowIllegalAccessErrorFinalField(referrer, resolved_field); 232 return nullptr; // failure 233 } else { 234 FieldHelper fh(resolved_field); 235 if (UNLIKELY(fh.IsPrimitiveType() != is_primitive || 236 fh.FieldSize() != expected_size)) { 237 ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 238 DCHECK(throw_location.GetMethod() == referrer); 239 self->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;", 240 "Attempted read of %zd-bit %s on field '%s'", 241 expected_size * (32 / sizeof(int32_t)), 242 is_primitive ? "primitive" : "non-primitive", 243 PrettyField(resolved_field, true).c_str()); 244 return nullptr; // failure 245 } 246 } 247 } 248 if (!is_static) { 249 // instance fields must be being accessed on an initialized class 250 return resolved_field; 251 } else { 252 // If the class is initialized we're done. 253 if (LIKELY(fields_class->IsInitialized())) { 254 return resolved_field; 255 } else if (LIKELY(class_linker->EnsureInitialized(fields_class, true, true))) { 256 // Otherwise let's ensure the class is initialized before resolving the field. 257 return resolved_field; 258 } else { 259 DCHECK(self->IsExceptionPending()); // Throw exception and unwind 260 return nullptr; // failure 261 } 262 } 263} 264 265// Explicit template declarations of FindFieldFromCode for all field access types. 266#define EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, _access_check) \ 267template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE \ 268static mirror::ArtField* FindFieldFromCode<_type, _access_check>(uint32_t field_idx, \ 269 const mirror::ArtMethod* referrer, \ 270 Thread* self, size_t expected_size) \ 271 272#define EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(_type) \ 273 EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, false); \ 274 EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, true) 275 276EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstanceObjectRead); 277EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstanceObjectWrite); 278EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstancePrimitiveRead); 279EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstancePrimitiveWrite); 280EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticObjectRead); 281EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticObjectWrite); 282EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticPrimitiveRead); 283EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticPrimitiveWrite); 284 285#undef EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL 286#undef EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL 287 288template<InvokeType type, bool access_check> 289static inline mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object* this_object, 290 mirror::ArtMethod* referrer, Thread* self) { 291 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 292 mirror::ArtMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type); 293 if (UNLIKELY(resolved_method == nullptr)) { 294 DCHECK(self->IsExceptionPending()); // Throw exception and unwind. 295 return nullptr; // Failure. 296 } else if (UNLIKELY(this_object == nullptr && type != kStatic)) { 297 // Maintain interpreter-like semantics where NullPointerException is thrown 298 // after potential NoSuchMethodError from class linker. 299 ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 300 DCHECK(referrer == throw_location.GetMethod()); 301 ThrowNullPointerExceptionForMethodAccess(throw_location, method_idx, type); 302 return nullptr; // Failure. 303 } else if (access_check) { 304 // Incompatible class change should have been handled in resolve method. 305 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) { 306 ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method, 307 referrer); 308 return nullptr; // Failure. 309 } 310 mirror::Class* methods_class = resolved_method->GetDeclaringClass(); 311 mirror::Class* referring_class = referrer->GetDeclaringClass(); 312 if (UNLIKELY(!referring_class->CanAccess(methods_class) || 313 !referring_class->CanAccessMember(methods_class, 314 resolved_method->GetAccessFlags()))) { 315 // The referring class can't access the resolved method, this may occur as a result of a 316 // protected method being made public by implementing an interface that re-declares the 317 // method public. Resort to the dex file to determine the correct class for the access check 318 const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile(); 319 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 320 methods_class = class_linker->ResolveType(dex_file, 321 dex_file.GetMethodId(method_idx).class_idx_, 322 referring_class); 323 if (UNLIKELY(!referring_class->CanAccess(methods_class))) { 324 ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class, 325 referrer, resolved_method, type); 326 return nullptr; // Failure. 327 } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class, 328 resolved_method->GetAccessFlags()))) { 329 ThrowIllegalAccessErrorMethod(referring_class, resolved_method); 330 return nullptr; // Failure. 331 } 332 } 333 } 334 switch (type) { 335 case kStatic: 336 case kDirect: 337 return resolved_method; 338 case kVirtual: { 339 mirror::ObjectArray<mirror::ArtMethod>* vtable = this_object->GetClass()->GetVTable(); 340 uint16_t vtable_index = resolved_method->GetMethodIndex(); 341 if (access_check && 342 (vtable == nullptr || vtable_index >= static_cast<uint32_t>(vtable->GetLength()))) { 343 // Behavior to agree with that of the verifier. 344 MethodHelper mh(resolved_method); 345 ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(), 346 mh.GetSignature()); 347 return nullptr; // Failure. 348 } 349 DCHECK(vtable != nullptr); 350 return vtable->GetWithoutChecks(vtable_index); 351 } 352 case kSuper: { 353 mirror::Class* super_class = referrer->GetDeclaringClass()->GetSuperClass(); 354 uint16_t vtable_index = resolved_method->GetMethodIndex(); 355 mirror::ObjectArray<mirror::ArtMethod>* vtable; 356 if (access_check) { 357 // Check existence of super class. 358 vtable = (super_class != nullptr) ? super_class->GetVTable() : nullptr; 359 if (vtable == nullptr || vtable_index >= static_cast<uint32_t>(vtable->GetLength())) { 360 // Behavior to agree with that of the verifier. 361 MethodHelper mh(resolved_method); 362 ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(), 363 mh.GetSignature()); 364 return nullptr; // Failure. 365 } 366 } else { 367 // Super class must exist. 368 DCHECK(super_class != nullptr); 369 vtable = super_class->GetVTable(); 370 } 371 DCHECK(vtable != nullptr); 372 return vtable->GetWithoutChecks(vtable_index); 373 } 374 case kInterface: { 375 mirror::ArtMethod* interface_method = 376 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method); 377 if (UNLIKELY(interface_method == nullptr)) { 378 ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object, 379 referrer); 380 return nullptr; // Failure. 381 } else { 382 return interface_method; 383 } 384 } 385 default: 386 LOG(FATAL) << "Unknown invoke type " << type; 387 return nullptr; // Failure. 388 } 389} 390 391// Explicit template declarations of FindMethodFromCode for all invoke types. 392#define EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, _access_check) \ 393 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE \ 394 static mirror::ArtMethod* FindMethodFromCode<_type, _access_check>(uint32_t method_idx, \ 395 mirror::Object* this_object, \ 396 mirror::ArtMethod* referrer, \ 397 Thread* self) 398#define EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(_type) \ 399 EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, false); \ 400 EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, true) 401 402EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kStatic); 403EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kDirect); 404EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kVirtual); 405EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kSuper); 406EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kInterface); 407 408#undef EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL 409#undef EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL 410 411// Fast path field resolution that can't initialize classes or throw exceptions. 412static inline mirror::ArtField* FindFieldFast(uint32_t field_idx, 413 const mirror::ArtMethod* referrer, 414 FindFieldType type, size_t expected_size) 415 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 416 mirror::ArtField* resolved_field = 417 referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx); 418 if (UNLIKELY(resolved_field == NULL)) { 419 return NULL; 420 } 421 mirror::Class* fields_class = resolved_field->GetDeclaringClass(); 422 // Check class is initiliazed or initializing. 423 if (UNLIKELY(!fields_class->IsInitializing())) { 424 return NULL; 425 } 426 // Check for incompatible class change. 427 bool is_primitive; 428 bool is_set; 429 bool is_static; 430 switch (type) { 431 case InstanceObjectRead: is_primitive = false; is_set = false; is_static = false; break; 432 case InstanceObjectWrite: is_primitive = false; is_set = true; is_static = false; break; 433 case InstancePrimitiveRead: is_primitive = true; is_set = false; is_static = false; break; 434 case InstancePrimitiveWrite: is_primitive = true; is_set = true; is_static = false; break; 435 case StaticObjectRead: is_primitive = false; is_set = false; is_static = true; break; 436 case StaticObjectWrite: is_primitive = false; is_set = true; is_static = true; break; 437 case StaticPrimitiveRead: is_primitive = true; is_set = false; is_static = true; break; 438 case StaticPrimitiveWrite: is_primitive = true; is_set = true; is_static = true; break; 439 default: 440 LOG(FATAL) << "UNREACHABLE"; // Assignment below to avoid GCC warnings. 441 is_primitive = true; 442 is_set = true; 443 is_static = true; 444 break; 445 } 446 if (UNLIKELY(resolved_field->IsStatic() != is_static)) { 447 // Incompatible class change. 448 return NULL; 449 } 450 mirror::Class* referring_class = referrer->GetDeclaringClass(); 451 if (UNLIKELY(!referring_class->CanAccess(fields_class) || 452 !referring_class->CanAccessMember(fields_class, 453 resolved_field->GetAccessFlags()) || 454 (is_set && resolved_field->IsFinal() && (fields_class != referring_class)))) { 455 // Illegal access. 456 return NULL; 457 } 458 FieldHelper fh(resolved_field); 459 if (UNLIKELY(fh.IsPrimitiveType() != is_primitive || 460 fh.FieldSize() != expected_size)) { 461 return NULL; 462 } 463 return resolved_field; 464} 465 466// Fast path method resolution that can't throw exceptions. 467static inline mirror::ArtMethod* FindMethodFast(uint32_t method_idx, 468 mirror::Object* this_object, 469 const mirror::ArtMethod* referrer, 470 bool access_check, InvokeType type) 471 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 472 bool is_direct = type == kStatic || type == kDirect; 473 if (UNLIKELY(this_object == NULL && !is_direct)) { 474 return NULL; 475 } 476 mirror::ArtMethod* resolved_method = 477 referrer->GetDeclaringClass()->GetDexCache()->GetResolvedMethod(method_idx); 478 if (UNLIKELY(resolved_method == NULL)) { 479 return NULL; 480 } 481 if (access_check) { 482 // Check for incompatible class change errors and access. 483 bool icce = resolved_method->CheckIncompatibleClassChange(type); 484 if (UNLIKELY(icce)) { 485 return NULL; 486 } 487 mirror::Class* methods_class = resolved_method->GetDeclaringClass(); 488 mirror::Class* referring_class = referrer->GetDeclaringClass(); 489 if (UNLIKELY(!referring_class->CanAccess(methods_class) || 490 !referring_class->CanAccessMember(methods_class, 491 resolved_method->GetAccessFlags()))) { 492 // Potential illegal access, may need to refine the method's class. 493 return NULL; 494 } 495 } 496 if (type == kInterface) { // Most common form of slow path dispatch. 497 return this_object->GetClass()->FindVirtualMethodForInterface(resolved_method); 498 } else if (is_direct) { 499 return resolved_method; 500 } else if (type == kSuper) { 501 return referrer->GetDeclaringClass()->GetSuperClass()->GetVTable()-> 502 Get(resolved_method->GetMethodIndex()); 503 } else { 504 DCHECK(type == kVirtual); 505 return this_object->GetClass()->GetVTable()->Get(resolved_method->GetMethodIndex()); 506 } 507} 508 509static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx, 510 const mirror::ArtMethod* referrer, 511 Thread* self, bool can_run_clinit, 512 bool verify_access) 513 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 514 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 515 mirror::Class* klass = class_linker->ResolveType(type_idx, referrer); 516 if (UNLIKELY(klass == NULL)) { 517 CHECK(self->IsExceptionPending()); 518 return NULL; // Failure - Indicate to caller to deliver exception 519 } 520 // Perform access check if necessary. 521 mirror::Class* referring_class = referrer->GetDeclaringClass(); 522 if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) { 523 ThrowIllegalAccessErrorClass(referring_class, klass); 524 return NULL; // Failure - Indicate to caller to deliver exception 525 } 526 // If we're just implementing const-class, we shouldn't call <clinit>. 527 if (!can_run_clinit) { 528 return klass; 529 } 530 // If we are the <clinit> of this class, just return our storage. 531 // 532 // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished 533 // running. 534 if (klass == referring_class && referrer->IsConstructor() && referrer->IsStatic()) { 535 return klass; 536 } 537 if (!class_linker->EnsureInitialized(klass, true, true)) { 538 CHECK(self->IsExceptionPending()); 539 return NULL; // Failure - Indicate to caller to deliver exception 540 } 541 referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass); 542 return klass; 543} 544 545extern void ThrowStackOverflowError(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 546 547static inline mirror::String* ResolveStringFromCode(const mirror::ArtMethod* referrer, 548 uint32_t string_idx) 549 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 550 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 551 return class_linker->ResolveString(string_idx, referrer); 552} 553 554static inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self) 555 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 556 UNLOCK_FUNCTION(monitor_lock_) { 557 // Save any pending exception over monitor exit call. 558 mirror::Throwable* saved_exception = NULL; 559 ThrowLocation saved_throw_location; 560 if (UNLIKELY(self->IsExceptionPending())) { 561 saved_exception = self->GetException(&saved_throw_location); 562 self->ClearException(); 563 } 564 // Decode locked object and unlock, before popping local references. 565 self->DecodeJObject(locked)->MonitorExit(self); 566 if (UNLIKELY(self->IsExceptionPending())) { 567 LOG(FATAL) << "Synchronized JNI code returning with an exception:\n" 568 << saved_exception->Dump() 569 << "\nEncountered second exception during implicit MonitorExit:\n" 570 << self->GetException(NULL)->Dump(); 571 } 572 // Restore pending exception. 573 if (saved_exception != NULL) { 574 self->SetException(saved_throw_location, saved_exception); 575 } 576} 577 578static inline void CheckReferenceResult(mirror::Object* o, Thread* self) 579 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 580 if (o == NULL) { 581 return; 582 } 583 mirror::ArtMethod* m = self->GetCurrentMethod(NULL); 584 if (o == kInvalidIndirectRefObject) { 585 JniAbortF(NULL, "invalid reference returned from %s", PrettyMethod(m).c_str()); 586 } 587 // Make sure that the result is an instance of the type this method was expected to return. 588 mirror::Class* return_type = MethodHelper(m).GetReturnType(); 589 590 if (!o->InstanceOf(return_type)) { 591 JniAbortF(NULL, "attempt to return an instance of %s from %s", 592 PrettyTypeOf(o).c_str(), PrettyMethod(m).c_str()); 593 } 594} 595 596static inline void CheckSuspend(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 597 for (;;) { 598 if (thread->ReadFlag(kCheckpointRequest)) { 599 thread->RunCheckpointFunction(); 600 } else if (thread->ReadFlag(kSuspendRequest)) { 601 thread->FullSuspendCheck(); 602 } else { 603 break; 604 } 605 } 606} 607 608JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char* shorty, 609 jobject rcvr_jobj, jobject interface_art_method_jobj, 610 std::vector<jvalue>& args) 611 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 612 613// Entry point for deoptimization. 614extern "C" void art_quick_deoptimize(); 615static inline uintptr_t GetQuickDeoptimizationEntryPoint() { 616 return reinterpret_cast<uintptr_t>(art_quick_deoptimize); 617} 618 619// Return address of instrumentation stub. 620extern "C" void art_quick_instrumentation_entry(void*); 621static inline void* GetQuickInstrumentationEntryPoint() { 622 return reinterpret_cast<void*>(art_quick_instrumentation_entry); 623} 624 625// The return_pc of instrumentation exit stub. 626extern "C" void art_quick_instrumentation_exit(); 627static inline uintptr_t GetQuickInstrumentationExitPc() { 628 return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit); 629} 630 631extern "C" void art_portable_to_interpreter_bridge(mirror::ArtMethod*); 632static inline const void* GetPortableToInterpreterBridge() { 633 return reinterpret_cast<void*>(art_portable_to_interpreter_bridge); 634} 635 636extern "C" void art_quick_to_interpreter_bridge(mirror::ArtMethod*); 637static inline const void* GetQuickToInterpreterBridge() { 638 return reinterpret_cast<void*>(art_quick_to_interpreter_bridge); 639} 640 641// Return address of interpreter stub. 642static inline const void* GetCompiledCodeToInterpreterBridge() { 643#if defined(ART_USE_PORTABLE_COMPILER) 644 return GetPortableToInterpreterBridge(); 645#else 646 return GetQuickToInterpreterBridge(); 647#endif 648} 649 650 651static inline const void* GetPortableResolutionTrampoline(ClassLinker* class_linker) { 652 return class_linker->GetPortableResolutionTrampoline(); 653} 654 655static inline const void* GetQuickResolutionTrampoline(ClassLinker* class_linker) { 656 return class_linker->GetQuickResolutionTrampoline(); 657} 658 659// Return address of resolution trampoline stub for defined compiler. 660static inline const void* GetResolutionTrampoline(ClassLinker* class_linker) { 661#if defined(ART_USE_PORTABLE_COMPILER) 662 return GetPortableResolutionTrampoline(class_linker); 663#else 664 return GetQuickResolutionTrampoline(class_linker); 665#endif 666} 667 668extern "C" void art_portable_proxy_invoke_handler(); 669static inline const void* GetPortableProxyInvokeHandler() { 670 return reinterpret_cast<void*>(art_portable_proxy_invoke_handler); 671} 672 673extern "C" void art_quick_proxy_invoke_handler(); 674static inline const void* GetQuickProxyInvokeHandler() { 675 return reinterpret_cast<void*>(art_quick_proxy_invoke_handler); 676} 677 678static inline const void* GetProxyInvokeHandler() { 679#if defined(ART_USE_PORTABLE_COMPILER) 680 return GetPortableProxyInvokeHandler(); 681#else 682 return GetQuickProxyInvokeHandler(); 683#endif 684} 685 686extern "C" void* art_jni_dlsym_lookup_stub(JNIEnv*, jobject); 687static inline void* GetJniDlsymLookupStub() { 688 return reinterpret_cast<void*>(art_jni_dlsym_lookup_stub); 689} 690 691template <typename INT_TYPE, typename FLOAT_TYPE> 692static inline INT_TYPE art_float_to_integral(FLOAT_TYPE f) { 693 const INT_TYPE kMaxInt = static_cast<INT_TYPE>(std::numeric_limits<INT_TYPE>::max()); 694 const INT_TYPE kMinInt = static_cast<INT_TYPE>(std::numeric_limits<INT_TYPE>::min()); 695 const FLOAT_TYPE kMaxIntAsFloat = static_cast<FLOAT_TYPE>(kMaxInt); 696 const FLOAT_TYPE kMinIntAsFloat = static_cast<FLOAT_TYPE>(kMinInt); 697 if (LIKELY(f > kMinIntAsFloat)) { 698 if (LIKELY(f < kMaxIntAsFloat)) { 699 return static_cast<INT_TYPE>(f); 700 } else { 701 return kMaxInt; 702 } 703 } else { 704 return (f != f) ? 0 : kMinInt; // f != f implies NaN 705 } 706} 707 708} // namespace art 709 710#endif // ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_ 711