| /* |
| * 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.h" |
| #include "mirror/art_method-inl.h" |
| #include "mirror/dex_cache-inl.h" |
| #include "mirror/object-inl.h" |
| |
| namespace art { |
| |
| static mirror::ArtMethod* FindMethodHelper(uint32_t method_idx, |
| mirror::Object* this_object, |
| mirror::ArtMethod* caller_method, |
| bool access_check, |
| InvokeType type, |
| Thread* thread) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
| mirror::ArtMethod* method = FindMethodFast(method_idx, |
| this_object, |
| caller_method, |
| access_check, |
| type); |
| if (UNLIKELY(method == NULL)) { |
| method = FindMethodFromCode(method_idx, this_object, caller_method, |
| thread, access_check, type); |
| if (UNLIKELY(method == NULL)) { |
| CHECK(thread->IsExceptionPending()); |
| return 0; // failure |
| } |
| } |
| DCHECK(!thread->IsExceptionPending()); |
| const void* code = method->GetEntryPointFromCompiledCode(); |
| |
| // When we return, the caller will branch to this address, so it had better not be 0! |
| if (UNLIKELY(code == NULL)) { |
| MethodHelper mh(method); |
| LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method) |
| << " location: " << mh.GetDexFile().GetLocation(); |
| } |
| return method; |
| } |
| |
| 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(method_idx, this_object, referrer, true, kStatic, 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(method_idx, this_object, referrer, true, kDirect, 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(method_idx, this_object, referrer, true, kVirtual, 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(method_idx, this_object, referrer, true, kSuper, 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(method_idx, this_object, referrer, true, kInterface, 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(method_idx, this_object, referrer, false, kInterface, thread); |
| } |
| |
| } // namespace art |