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_INL_H_ 18 #define ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_INL_H_ 19 20 #include "entrypoint_utils.h" 21 22 #include "class_linker-inl.h" 23 #include "common_throws.h" 24 #include "dex_file.h" 25 #include "indirect_reference_table.h" 26 #include "invoke_type.h" 27 #include "jni_internal.h" 28 #include "mirror/art_method.h" 29 #include "mirror/array.h" 30 #include "mirror/class-inl.h" 31 #include "mirror/object-inl.h" 32 #include "mirror/throwable.h" 33 #include "handle_scope-inl.h" 34 #include "thread.h" 35 36 namespace art { 37 38 // TODO: Fix no thread safety analysis when GCC can handle template specialization. 39 template <const bool kAccessCheck> 40 static inline mirror::Class* CheckObjectAlloc(uint32_t type_idx, 41 mirror::ArtMethod* method, 42 Thread* self, bool* slow_path) { 43 mirror::Class* klass = method->GetDexCacheResolvedType<false>(type_idx); 44 if (UNLIKELY(klass == NULL)) { 45 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); 46 *slow_path = true; 47 if (klass == NULL) { 48 DCHECK(self->IsExceptionPending()); 49 return nullptr; // Failure 50 } else { 51 DCHECK(!self->IsExceptionPending()); 52 } 53 } 54 if (kAccessCheck) { 55 if (UNLIKELY(!klass->IsInstantiable())) { 56 ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 57 self->ThrowNewException(throw_location, "Ljava/lang/InstantiationError;", 58 PrettyDescriptor(klass).c_str()); 59 *slow_path = true; 60 return nullptr; // Failure 61 } 62 mirror::Class* referrer = method->GetDeclaringClass(); 63 if (UNLIKELY(!referrer->CanAccess(klass))) { 64 ThrowIllegalAccessErrorClass(referrer, klass); 65 *slow_path = true; 66 return nullptr; // Failure 67 } 68 } 69 if (UNLIKELY(!klass->IsInitialized())) { 70 StackHandleScope<1> hs(self); 71 Handle<mirror::Class> h_klass(hs.NewHandle(klass)); 72 // EnsureInitialized (the class initializer) might cause a GC. 73 // may cause us to suspend meaning that another thread may try to 74 // change the allocator while we are stuck in the entrypoints of 75 // an old allocator. Also, the class initialization may fail. To 76 // handle these cases we mark the slow path boolean as true so 77 // that the caller knows to check the allocator type to see if it 78 // has changed and to null-check the return value in case the 79 // initialization fails. 80 *slow_path = true; 81 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(h_klass, true, true)) { 82 DCHECK(self->IsExceptionPending()); 83 return nullptr; // Failure 84 } else { 85 DCHECK(!self->IsExceptionPending()); 86 } 87 return h_klass.Get(); 88 } 89 return klass; 90 } 91 92 // TODO: Fix no thread safety analysis when annotalysis is smarter. 93 static inline mirror::Class* CheckClassInitializedForObjectAlloc(mirror::Class* klass, 94 Thread* self, 95 bool* slow_path) { 96 if (UNLIKELY(!klass->IsInitialized())) { 97 StackHandleScope<1> hs(self); 98 Handle<mirror::Class> h_class(hs.NewHandle(klass)); 99 // EnsureInitialized (the class initializer) might cause a GC. 100 // may cause us to suspend meaning that another thread may try to 101 // change the allocator while we are stuck in the entrypoints of 102 // an old allocator. Also, the class initialization may fail. To 103 // handle these cases we mark the slow path boolean as true so 104 // that the caller knows to check the allocator type to see if it 105 // has changed and to null-check the return value in case the 106 // initialization fails. 107 *slow_path = true; 108 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(h_class, true, true)) { 109 DCHECK(self->IsExceptionPending()); 110 return nullptr; // Failure 111 } 112 return h_class.Get(); 113 } 114 return klass; 115 } 116 117 // Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it 118 // cannot be resolved, throw an error. If it can, use it to create an instance. 119 // When verification/compiler hasn't been able to verify access, optionally perform an access 120 // check. 121 // TODO: Fix NO_THREAD_SAFETY_ANALYSIS when GCC is smarter. 122 template <bool kAccessCheck, bool kInstrumented> 123 static inline mirror::Object* AllocObjectFromCode(uint32_t type_idx, 124 mirror::ArtMethod* method, 125 Thread* self, 126 gc::AllocatorType allocator_type) { 127 bool slow_path = false; 128 mirror::Class* klass = CheckObjectAlloc<kAccessCheck>(type_idx, method, self, &slow_path); 129 if (UNLIKELY(slow_path)) { 130 if (klass == nullptr) { 131 return nullptr; 132 } 133 return klass->Alloc<kInstrumented>(self, Runtime::Current()->GetHeap()->GetCurrentAllocator()); 134 } 135 DCHECK(klass != nullptr); 136 return klass->Alloc<kInstrumented>(self, allocator_type); 137 } 138 139 // Given the context of a calling Method and a resolved class, create an instance. 140 // TODO: Fix NO_THREAD_SAFETY_ANALYSIS when GCC is smarter. 141 template <bool kInstrumented> 142 static inline mirror::Object* AllocObjectFromCodeResolved(mirror::Class* klass, 143 mirror::ArtMethod* method, 144 Thread* self, 145 gc::AllocatorType allocator_type) { 146 DCHECK(klass != nullptr); 147 bool slow_path = false; 148 klass = CheckClassInitializedForObjectAlloc(klass, self, &slow_path); 149 if (UNLIKELY(slow_path)) { 150 if (klass == nullptr) { 151 return nullptr; 152 } 153 gc::Heap* heap = Runtime::Current()->GetHeap(); 154 // Pass in false since the object can not be finalizable. 155 return klass->Alloc<kInstrumented, false>(self, heap->GetCurrentAllocator()); 156 } 157 // Pass in false since the object can not be finalizable. 158 return klass->Alloc<kInstrumented, false>(self, allocator_type); 159 } 160 161 // Given the context of a calling Method and an initialized class, create an instance. 162 // TODO: Fix NO_THREAD_SAFETY_ANALYSIS when GCC is smarter. 163 template <bool kInstrumented> 164 static inline mirror::Object* AllocObjectFromCodeInitialized(mirror::Class* klass, 165 mirror::ArtMethod* method, 166 Thread* self, 167 gc::AllocatorType allocator_type) { 168 DCHECK(klass != nullptr); 169 // Pass in false since the object can not be finalizable. 170 return klass->Alloc<kInstrumented, false>(self, allocator_type); 171 } 172 173 174 // TODO: Fix no thread safety analysis when GCC can handle template specialization. 175 template <bool kAccessCheck> 176 static inline mirror::Class* CheckArrayAlloc(uint32_t type_idx, 177 mirror::ArtMethod* method, 178 int32_t component_count, 179 bool* slow_path) { 180 if (UNLIKELY(component_count < 0)) { 181 ThrowNegativeArraySizeException(component_count); 182 *slow_path = true; 183 return nullptr; // Failure 184 } 185 mirror::Class* klass = method->GetDexCacheResolvedType<false>(type_idx); 186 if (UNLIKELY(klass == nullptr)) { // Not in dex cache so try to resolve 187 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); 188 *slow_path = true; 189 if (klass == nullptr) { // Error 190 DCHECK(Thread::Current()->IsExceptionPending()); 191 return nullptr; // Failure 192 } 193 CHECK(klass->IsArrayClass()) << PrettyClass(klass); 194 } 195 if (kAccessCheck) { 196 mirror::Class* referrer = method->GetDeclaringClass(); 197 if (UNLIKELY(!referrer->CanAccess(klass))) { 198 ThrowIllegalAccessErrorClass(referrer, klass); 199 *slow_path = true; 200 return nullptr; // Failure 201 } 202 } 203 return klass; 204 } 205 206 // Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If 207 // it cannot be resolved, throw an error. If it can, use it to create an array. 208 // When verification/compiler hasn't been able to verify access, optionally perform an access 209 // check. 210 // TODO: Fix no thread safety analysis when GCC can handle template specialization. 211 template <bool kAccessCheck, bool kInstrumented> 212 static inline mirror::Array* AllocArrayFromCode(uint32_t type_idx, 213 mirror::ArtMethod* method, 214 int32_t component_count, 215 Thread* self, 216 gc::AllocatorType allocator_type) { 217 bool slow_path = false; 218 mirror::Class* klass = CheckArrayAlloc<kAccessCheck>(type_idx, method, component_count, 219 &slow_path); 220 if (UNLIKELY(slow_path)) { 221 if (klass == nullptr) { 222 return nullptr; 223 } 224 gc::Heap* heap = Runtime::Current()->GetHeap(); 225 return mirror::Array::Alloc<kInstrumented>(self, klass, component_count, 226 klass->GetComponentSize(), 227 heap->GetCurrentAllocator()); 228 } 229 return mirror::Array::Alloc<kInstrumented>(self, klass, component_count, 230 klass->GetComponentSize(), allocator_type); 231 } 232 233 template <bool kAccessCheck, bool kInstrumented> 234 static inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* klass, 235 mirror::ArtMethod* method, 236 int32_t component_count, 237 Thread* self, 238 gc::AllocatorType allocator_type) { 239 DCHECK(klass != nullptr); 240 if (UNLIKELY(component_count < 0)) { 241 ThrowNegativeArraySizeException(component_count); 242 return nullptr; // Failure 243 } 244 if (kAccessCheck) { 245 mirror::Class* referrer = method->GetDeclaringClass(); 246 if (UNLIKELY(!referrer->CanAccess(klass))) { 247 ThrowIllegalAccessErrorClass(referrer, klass); 248 return nullptr; // Failure 249 } 250 } 251 // No need to retry a slow-path allocation as the above code won't cause a GC or thread 252 // suspension. 253 return mirror::Array::Alloc<kInstrumented>(self, klass, component_count, 254 klass->GetComponentSize(), allocator_type); 255 } 256 257 template<FindFieldType type, bool access_check> 258 static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer, 259 Thread* self, size_t expected_size) { 260 bool is_primitive; 261 bool is_set; 262 bool is_static; 263 switch (type) { 264 case InstanceObjectRead: is_primitive = false; is_set = false; is_static = false; break; 265 case InstanceObjectWrite: is_primitive = false; is_set = true; is_static = false; break; 266 case InstancePrimitiveRead: is_primitive = true; is_set = false; is_static = false; break; 267 case InstancePrimitiveWrite: is_primitive = true; is_set = true; is_static = false; break; 268 case StaticObjectRead: is_primitive = false; is_set = false; is_static = true; break; 269 case StaticObjectWrite: is_primitive = false; is_set = true; is_static = true; break; 270 case StaticPrimitiveRead: is_primitive = true; is_set = false; is_static = true; break; 271 case StaticPrimitiveWrite: // Keep GCC happy by having a default handler, fall-through. 272 default: is_primitive = true; is_set = true; is_static = true; break; 273 } 274 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 275 mirror::ArtField* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static); 276 if (UNLIKELY(resolved_field == nullptr)) { 277 DCHECK(self->IsExceptionPending()); // Throw exception and unwind. 278 return nullptr; // Failure. 279 } 280 mirror::Class* fields_class = resolved_field->GetDeclaringClass(); 281 if (access_check) { 282 if (UNLIKELY(resolved_field->IsStatic() != is_static)) { 283 ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer); 284 return nullptr; 285 } 286 mirror::Class* referring_class = referrer->GetDeclaringClass(); 287 if (UNLIKELY(!referring_class->CheckResolvedFieldAccess(fields_class, resolved_field, 288 field_idx))) { 289 DCHECK(self->IsExceptionPending()); // Throw exception and unwind. 290 return nullptr; // Failure. 291 } 292 if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) { 293 ThrowIllegalAccessErrorFinalField(referrer, resolved_field); 294 return nullptr; // Failure. 295 } else { 296 if (UNLIKELY(resolved_field->IsPrimitiveType() != is_primitive || 297 resolved_field->FieldSize() != expected_size)) { 298 ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 299 DCHECK(throw_location.GetMethod() == referrer); 300 self->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;", 301 "Attempted read of %zd-bit %s on field '%s'", 302 expected_size * (32 / sizeof(int32_t)), 303 is_primitive ? "primitive" : "non-primitive", 304 PrettyField(resolved_field, true).c_str()); 305 return nullptr; // Failure. 306 } 307 } 308 } 309 if (!is_static) { 310 // instance fields must be being accessed on an initialized class 311 return resolved_field; 312 } else { 313 // If the class is initialized we're done. 314 if (LIKELY(fields_class->IsInitialized())) { 315 return resolved_field; 316 } else { 317 StackHandleScope<1> hs(self); 318 Handle<mirror::Class> h_class(hs.NewHandle(fields_class)); 319 if (LIKELY(class_linker->EnsureInitialized(h_class, true, true))) { 320 // Otherwise let's ensure the class is initialized before resolving the field. 321 return resolved_field; 322 } 323 DCHECK(self->IsExceptionPending()); // Throw exception and unwind 324 return nullptr; // Failure. 325 } 326 } 327 } 328 329 // Explicit template declarations of FindFieldFromCode for all field access types. 330 #define EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, _access_check) \ 331 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE \ 332 mirror::ArtField* FindFieldFromCode<_type, _access_check>(uint32_t field_idx, \ 333 mirror::ArtMethod* referrer, \ 334 Thread* self, size_t expected_size) \ 335 336 #define EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(_type) \ 337 EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, false); \ 338 EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, true) 339 340 EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstanceObjectRead); 341 EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstanceObjectWrite); 342 EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstancePrimitiveRead); 343 EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstancePrimitiveWrite); 344 EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticObjectRead); 345 EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticObjectWrite); 346 EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticPrimitiveRead); 347 EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticPrimitiveWrite); 348 349 #undef EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL 350 #undef EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL 351 352 template<InvokeType type, bool access_check> 353 static inline mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx, 354 mirror::Object** this_object, 355 mirror::ArtMethod** referrer, Thread* self) { 356 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); 357 mirror::ArtMethod* resolved_method = class_linker->GetResolvedMethod(method_idx, *referrer, type); 358 if (resolved_method == nullptr) { 359 StackHandleScope<1> hs(self); 360 mirror::Object* null_this = nullptr; 361 HandleWrapper<mirror::Object> h_this( 362 hs.NewHandleWrapper(type == kStatic ? &null_this : this_object)); 363 resolved_method = class_linker->ResolveMethod(self, method_idx, referrer, type); 364 } 365 if (UNLIKELY(resolved_method == nullptr)) { 366 DCHECK(self->IsExceptionPending()); // Throw exception and unwind. 367 return nullptr; // Failure. 368 } else if (UNLIKELY(*this_object == nullptr && type != kStatic)) { 369 // Maintain interpreter-like semantics where NullPointerException is thrown 370 // after potential NoSuchMethodError from class linker. 371 ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 372 DCHECK_EQ(*referrer, throw_location.GetMethod()); 373 ThrowNullPointerExceptionForMethodAccess(throw_location, method_idx, type); 374 return nullptr; // Failure. 375 } else if (access_check) { 376 // Incompatible class change should have been handled in resolve method. 377 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) { 378 ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method, 379 *referrer); 380 return nullptr; // Failure. 381 } 382 mirror::Class* methods_class = resolved_method->GetDeclaringClass(); 383 mirror::Class* referring_class = (*referrer)->GetDeclaringClass(); 384 bool can_access_resolved_method = 385 referring_class->CheckResolvedMethodAccess<type>(methods_class, resolved_method, 386 method_idx); 387 if (UNLIKELY(!can_access_resolved_method)) { 388 DCHECK(self->IsExceptionPending()); // Throw exception and unwind. 389 return nullptr; // Failure. 390 } 391 } 392 switch (type) { 393 case kStatic: 394 case kDirect: 395 return resolved_method; 396 case kVirtual: { 397 mirror::Class* klass = (*this_object)->GetClass(); 398 uint16_t vtable_index = resolved_method->GetMethodIndex(); 399 if (access_check && 400 (!klass->HasVTable() || 401 vtable_index >= static_cast<uint32_t>(klass->GetVTableLength()))) { 402 // Behavior to agree with that of the verifier. 403 ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), 404 resolved_method->GetName(), resolved_method->GetSignature()); 405 return nullptr; // Failure. 406 } 407 DCHECK(klass->HasVTable()) << PrettyClass(klass); 408 return klass->GetVTableEntry(vtable_index); 409 } 410 case kSuper: { 411 mirror::Class* super_class = (*referrer)->GetDeclaringClass()->GetSuperClass(); 412 uint16_t vtable_index = resolved_method->GetMethodIndex(); 413 if (access_check) { 414 // Check existence of super class. 415 if (super_class == nullptr || !super_class->HasVTable() || 416 vtable_index >= static_cast<uint32_t>(super_class->GetVTableLength())) { 417 // Behavior to agree with that of the verifier. 418 ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), 419 resolved_method->GetName(), resolved_method->GetSignature()); 420 return nullptr; // Failure. 421 } 422 } else { 423 // Super class must exist. 424 DCHECK(super_class != nullptr); 425 } 426 DCHECK(super_class->HasVTable()); 427 return super_class->GetVTableEntry(vtable_index); 428 } 429 case kInterface: { 430 uint32_t imt_index = resolved_method->GetDexMethodIndex() % mirror::Class::kImtSize; 431 mirror::ArtMethod* imt_method = (*this_object)->GetClass()->GetEmbeddedImTableEntry(imt_index); 432 if (!imt_method->IsImtConflictMethod()) { 433 return imt_method; 434 } else { 435 mirror::ArtMethod* interface_method = 436 (*this_object)->GetClass()->FindVirtualMethodForInterface(resolved_method); 437 if (UNLIKELY(interface_method == nullptr)) { 438 ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, 439 *this_object, *referrer); 440 return nullptr; // Failure. 441 } 442 return interface_method; 443 } 444 } 445 default: 446 LOG(FATAL) << "Unknown invoke type " << type; 447 return nullptr; // Failure. 448 } 449 } 450 451 // Explicit template declarations of FindMethodFromCode for all invoke types. 452 #define EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, _access_check) \ 453 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE \ 454 mirror::ArtMethod* FindMethodFromCode<_type, _access_check>(uint32_t method_idx, \ 455 mirror::Object** this_object, \ 456 mirror::ArtMethod** referrer, \ 457 Thread* self) 458 #define EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(_type) \ 459 EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, false); \ 460 EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, true) 461 462 EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kStatic); 463 EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kDirect); 464 EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kVirtual); 465 EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kSuper); 466 EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kInterface); 467 468 #undef EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL 469 #undef EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL 470 471 // Fast path field resolution that can't initialize classes or throw exceptions. 472 static inline mirror::ArtField* FindFieldFast(uint32_t field_idx, 473 mirror::ArtMethod* referrer, 474 FindFieldType type, size_t expected_size) { 475 mirror::ArtField* resolved_field = 476 referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx); 477 if (UNLIKELY(resolved_field == nullptr)) { 478 return nullptr; 479 } 480 // Check for incompatible class change. 481 bool is_primitive; 482 bool is_set; 483 bool is_static; 484 switch (type) { 485 case InstanceObjectRead: is_primitive = false; is_set = false; is_static = false; break; 486 case InstanceObjectWrite: is_primitive = false; is_set = true; is_static = false; break; 487 case InstancePrimitiveRead: is_primitive = true; is_set = false; is_static = false; break; 488 case InstancePrimitiveWrite: is_primitive = true; is_set = true; is_static = false; break; 489 case StaticObjectRead: is_primitive = false; is_set = false; is_static = true; break; 490 case StaticObjectWrite: is_primitive = false; is_set = true; is_static = true; break; 491 case StaticPrimitiveRead: is_primitive = true; is_set = false; is_static = true; break; 492 case StaticPrimitiveWrite: is_primitive = true; is_set = true; is_static = true; break; 493 default: 494 LOG(FATAL) << "UNREACHABLE"; // Assignment below to avoid GCC warnings. 495 is_primitive = true; 496 is_set = true; 497 is_static = true; 498 break; 499 } 500 if (UNLIKELY(resolved_field->IsStatic() != is_static)) { 501 // Incompatible class change. 502 return nullptr; 503 } 504 mirror::Class* fields_class = resolved_field->GetDeclaringClass(); 505 if (is_static) { 506 // Check class is initialized else fail so that we can contend to initialize the class with 507 // other threads that may be racing to do this. 508 if (UNLIKELY(!fields_class->IsInitialized())) { 509 return nullptr; 510 } 511 } 512 mirror::Class* referring_class = referrer->GetDeclaringClass(); 513 if (UNLIKELY(!referring_class->CanAccess(fields_class) || 514 !referring_class->CanAccessMember(fields_class, 515 resolved_field->GetAccessFlags()) || 516 (is_set && resolved_field->IsFinal() && (fields_class != referring_class)))) { 517 // Illegal access. 518 return nullptr; 519 } 520 if (UNLIKELY(resolved_field->IsPrimitiveType() != is_primitive || 521 resolved_field->FieldSize() != expected_size)) { 522 return nullptr; 523 } 524 return resolved_field; 525 } 526 527 // Fast path method resolution that can't throw exceptions. 528 static inline mirror::ArtMethod* FindMethodFast(uint32_t method_idx, 529 mirror::Object* this_object, 530 mirror::ArtMethod* referrer, 531 bool access_check, InvokeType type) { 532 bool is_direct = type == kStatic || type == kDirect; 533 if (UNLIKELY(this_object == NULL && !is_direct)) { 534 return NULL; 535 } 536 mirror::ArtMethod* resolved_method = 537 referrer->GetDeclaringClass()->GetDexCache()->GetResolvedMethod(method_idx); 538 if (UNLIKELY(resolved_method == NULL)) { 539 return NULL; 540 } 541 if (access_check) { 542 // Check for incompatible class change errors and access. 543 bool icce = resolved_method->CheckIncompatibleClassChange(type); 544 if (UNLIKELY(icce)) { 545 return NULL; 546 } 547 mirror::Class* methods_class = resolved_method->GetDeclaringClass(); 548 mirror::Class* referring_class = referrer->GetDeclaringClass(); 549 if (UNLIKELY(!referring_class->CanAccess(methods_class) || 550 !referring_class->CanAccessMember(methods_class, 551 resolved_method->GetAccessFlags()))) { 552 // Potential illegal access, may need to refine the method's class. 553 return NULL; 554 } 555 } 556 if (type == kInterface) { // Most common form of slow path dispatch. 557 return this_object->GetClass()->FindVirtualMethodForInterface(resolved_method); 558 } else if (is_direct) { 559 return resolved_method; 560 } else if (type == kSuper) { 561 return referrer->GetDeclaringClass()->GetSuperClass() 562 ->GetVTableEntry(resolved_method->GetMethodIndex()); 563 } else { 564 DCHECK(type == kVirtual); 565 return this_object->GetClass()->GetVTableEntry(resolved_method->GetMethodIndex()); 566 } 567 } 568 569 static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx, 570 mirror::ArtMethod* referrer, 571 Thread* self, bool can_run_clinit, 572 bool verify_access) { 573 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 574 mirror::Class* klass = class_linker->ResolveType(type_idx, referrer); 575 if (UNLIKELY(klass == nullptr)) { 576 CHECK(self->IsExceptionPending()); 577 return nullptr; // Failure - Indicate to caller to deliver exception 578 } 579 // Perform access check if necessary. 580 mirror::Class* referring_class = referrer->GetDeclaringClass(); 581 if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) { 582 ThrowIllegalAccessErrorClass(referring_class, klass); 583 return nullptr; // Failure - Indicate to caller to deliver exception 584 } 585 // If we're just implementing const-class, we shouldn't call <clinit>. 586 if (!can_run_clinit) { 587 return klass; 588 } 589 // If we are the <clinit> of this class, just return our storage. 590 // 591 // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished 592 // running. 593 if (klass == referring_class && referrer->IsConstructor() && referrer->IsStatic()) { 594 return klass; 595 } 596 StackHandleScope<1> hs(self); 597 Handle<mirror::Class> h_class(hs.NewHandle(klass)); 598 if (!class_linker->EnsureInitialized(h_class, true, true)) { 599 CHECK(self->IsExceptionPending()); 600 return nullptr; // Failure - Indicate to caller to deliver exception 601 } 602 return h_class.Get(); 603 } 604 605 static inline mirror::String* ResolveStringFromCode(mirror::ArtMethod* referrer, 606 uint32_t string_idx) { 607 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 608 return class_linker->ResolveString(string_idx, referrer); 609 } 610 611 static inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self) { 612 // Save any pending exception over monitor exit call. 613 mirror::Throwable* saved_exception = NULL; 614 ThrowLocation saved_throw_location; 615 bool is_exception_reported = self->IsExceptionReportedToInstrumentation(); 616 if (UNLIKELY(self->IsExceptionPending())) { 617 saved_exception = self->GetException(&saved_throw_location); 618 self->ClearException(); 619 } 620 // Decode locked object and unlock, before popping local references. 621 self->DecodeJObject(locked)->MonitorExit(self); 622 if (UNLIKELY(self->IsExceptionPending())) { 623 LOG(FATAL) << "Synchronized JNI code returning with an exception:\n" 624 << saved_exception->Dump() 625 << "\nEncountered second exception during implicit MonitorExit:\n" 626 << self->GetException(NULL)->Dump(); 627 } 628 // Restore pending exception. 629 if (saved_exception != NULL) { 630 self->SetException(saved_throw_location, saved_exception); 631 self->SetExceptionReportedToInstrumentation(is_exception_reported); 632 } 633 } 634 635 static inline void CheckSuspend(Thread* thread) { 636 for (;;) { 637 if (thread->ReadFlag(kCheckpointRequest)) { 638 thread->RunCheckpointFunction(); 639 } else if (thread->ReadFlag(kSuspendRequest)) { 640 thread->FullSuspendCheck(); 641 } else { 642 break; 643 } 644 } 645 } 646 647 template <typename INT_TYPE, typename FLOAT_TYPE> 648 static inline INT_TYPE art_float_to_integral(FLOAT_TYPE f) { 649 const INT_TYPE kMaxInt = static_cast<INT_TYPE>(std::numeric_limits<INT_TYPE>::max()); 650 const INT_TYPE kMinInt = static_cast<INT_TYPE>(std::numeric_limits<INT_TYPE>::min()); 651 const FLOAT_TYPE kMaxIntAsFloat = static_cast<FLOAT_TYPE>(kMaxInt); 652 const FLOAT_TYPE kMinIntAsFloat = static_cast<FLOAT_TYPE>(kMinInt); 653 if (LIKELY(f > kMinIntAsFloat)) { 654 if (LIKELY(f < kMaxIntAsFloat)) { 655 return static_cast<INT_TYPE>(f); 656 } else { 657 return kMaxInt; 658 } 659 } else { 660 return (f != f) ? 0 : kMinInt; // f != f implies NaN 661 } 662 } 663 664 } // namespace art 665 666 #endif // ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_INL_H_ 667