| /* | |
| * Copyright (C) 2012 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include "entrypoints/entrypoint_utils-inl.h" | |
| #include "mirror/art_method-inl.h" | |
| #include "mirror/dex_cache-inl.h" | |
| #include "mirror/object-inl.h" | |
| namespace art { | |
| template<InvokeType type, bool access_check> | |
| mirror::ArtMethod* FindMethodHelper(uint32_t method_idx, mirror::Object* this_object, | |
| mirror::ArtMethod* caller_method, Thread* self) { | |
| mirror::ArtMethod* method = FindMethodFast(method_idx, this_object, caller_method, | |
| access_check, type); | |
| if (UNLIKELY(method == NULL)) { | |
| // Note: This can cause thread suspension. | |
| self->AssertThreadSuspensionIsAllowable(); | |
| method = FindMethodFromCode<type, access_check>(method_idx, &this_object, &caller_method, | |
| self); | |
| if (UNLIKELY(method == NULL)) { | |
| CHECK(self->IsExceptionPending()); | |
| return 0; // failure | |
| } | |
| } | |
| DCHECK(!self->IsExceptionPending()); | |
| const void* code = method->GetEntryPointFromPortableCompiledCode(); | |
| // When we return, the caller will branch to this address, so it had better not be 0! | |
| if (UNLIKELY(code == NULL)) { | |
| LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method) | |
| << " location: " << method->GetDexFile()->GetLocation(); | |
| } | |
| return method; | |
| } | |
| // Explicit template declarations of FindMethodHelper for all invoke types. | |
| #define EXPLICIT_FIND_METHOD_HELPER_TEMPLATE_DECL(_type, _access_check) \ | |
| template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) \ | |
| mirror::ArtMethod* FindMethodHelper<_type, _access_check>(uint32_t method_idx, \ | |
| mirror::Object* this_object, \ | |
| mirror::ArtMethod* caller_method, \ | |
| Thread* thread) | |
| #define EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(_type) \ | |
| EXPLICIT_FIND_METHOD_HELPER_TEMPLATE_DECL(_type, false); \ | |
| EXPLICIT_FIND_METHOD_HELPER_TEMPLATE_DECL(_type, true) | |
| EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(kStatic); | |
| EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(kDirect); | |
| EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(kVirtual); | |
| EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(kSuper); | |
| EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(kInterface); | |
| #undef EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL | |
| #undef EXPLICIT_FIND_METHOD_HELPER_TEMPLATE_DECL | |
| extern "C" mirror::Object* art_portable_find_static_method_from_code_with_access_check(uint32_t method_idx, | |
| mirror::Object* this_object, | |
| mirror::ArtMethod* referrer, | |
| Thread* thread) | |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | |
| return FindMethodHelper<kStatic, true>(method_idx, this_object, referrer, thread); | |
| } | |
| extern "C" mirror::Object* art_portable_find_direct_method_from_code_with_access_check(uint32_t method_idx, | |
| mirror::Object* this_object, | |
| mirror::ArtMethod* referrer, | |
| Thread* thread) | |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | |
| return FindMethodHelper<kDirect, true>(method_idx, this_object, referrer, thread); | |
| } | |
| extern "C" mirror::Object* art_portable_find_virtual_method_from_code_with_access_check(uint32_t method_idx, | |
| mirror::Object* this_object, | |
| mirror::ArtMethod* referrer, | |
| Thread* thread) | |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | |
| return FindMethodHelper<kVirtual, true>(method_idx, this_object, referrer, thread); | |
| } | |
| extern "C" mirror::Object* art_portable_find_super_method_from_code_with_access_check(uint32_t method_idx, | |
| mirror::Object* this_object, | |
| mirror::ArtMethod* referrer, | |
| Thread* thread) | |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | |
| return FindMethodHelper<kSuper, true>(method_idx, this_object, referrer, thread); | |
| } | |
| extern "C" mirror::Object* art_portable_find_interface_method_from_code_with_access_check(uint32_t method_idx, | |
| mirror::Object* this_object, | |
| mirror::ArtMethod* referrer, | |
| Thread* thread) | |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | |
| return FindMethodHelper<kInterface, true>(method_idx, this_object, referrer, thread); | |
| } | |
| extern "C" mirror::Object* art_portable_find_interface_method_from_code(uint32_t method_idx, | |
| mirror::Object* this_object, | |
| mirror::ArtMethod* referrer, | |
| Thread* thread) | |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | |
| return FindMethodHelper<kInterface, false>(method_idx, this_object, referrer, thread); | |
| } | |
| } // namespace art |