diff options
Diffstat (limited to 'runtime/entrypoints')
14 files changed, 4 insertions, 1528 deletions
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc index 3b47f245f7..28e19d414d 100644 --- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc +++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc @@ -15,6 +15,7 @@ */ #include "class_linker.h" +#include "dex_file-inl.h" #include "interpreter/interpreter.h" #include "mirror/art_method-inl.h" #include "mirror/object-inl.h" @@ -47,13 +48,9 @@ extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, const DexFile:: } } uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_; - if (kUsePortableCompiler) { - InvokeWithShadowFrame(self, shadow_frame, arg_offset, result); - } else { - method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset), - (shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t), - result, method->GetShorty()); - } + method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset), + (shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t), + result, method->GetShorty()); } } // namespace art diff --git a/runtime/entrypoints/portable/portable_alloc_entrypoints.cc b/runtime/entrypoints/portable/portable_alloc_entrypoints.cc deleted file mode 100644 index de95f7dfbc..0000000000 --- a/runtime/entrypoints/portable/portable_alloc_entrypoints.cc +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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/object-inl.h" - -namespace art { - -static constexpr gc::AllocatorType kPortableAllocatorType = - gc::kUseRosAlloc ? gc::kAllocatorTypeRosAlloc : gc::kAllocatorTypeDlMalloc; - -extern "C" mirror::Object* art_portable_alloc_object_from_code(uint32_t type_idx, - mirror::ArtMethod* referrer, - Thread* thread) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return AllocObjectFromCode<false, true>(type_idx, referrer, thread, kPortableAllocatorType); -} - -extern "C" mirror::Object* art_portable_alloc_object_from_code_with_access_check(uint32_t type_idx, - mirror::ArtMethod* referrer, - Thread* thread) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return AllocObjectFromCode<true, true>(type_idx, referrer, thread, kPortableAllocatorType); -} - -extern "C" mirror::Object* art_portable_alloc_array_from_code(uint32_t type_idx, - mirror::ArtMethod* referrer, - uint32_t length, - Thread* self) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return AllocArrayFromCode<false, true>(type_idx, referrer, length, self, - kPortableAllocatorType); -} - -extern "C" mirror::Object* art_portable_alloc_array_from_code_with_access_check(uint32_t type_idx, - mirror::ArtMethod* referrer, - uint32_t length, - Thread* self) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return AllocArrayFromCode<true, true>(type_idx, referrer, length, self, - kPortableAllocatorType); -} - -extern "C" mirror::Object* art_portable_check_and_alloc_array_from_code(uint32_t type_idx, - mirror::ArtMethod* referrer, - uint32_t length, - Thread* thread) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return CheckAndAllocArrayFromCodeInstrumented(type_idx, referrer, length, thread, false, - kPortableAllocatorType); -} - -extern "C" mirror::Object* art_portable_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx, - mirror::ArtMethod* referrer, - uint32_t length, - Thread* thread) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return CheckAndAllocArrayFromCodeInstrumented(type_idx, referrer, length, thread, true, - kPortableAllocatorType); -} - -} // namespace art diff --git a/runtime/entrypoints/portable/portable_cast_entrypoints.cc b/runtime/entrypoints/portable/portable_cast_entrypoints.cc deleted file mode 100644 index 151b1785c9..0000000000 --- a/runtime/entrypoints/portable/portable_cast_entrypoints.cc +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 "common_throws.h" -#include "entrypoints/entrypoint_utils-inl.h" -#include "mirror/object-inl.h" - -namespace art { - -extern "C" int32_t art_portable_is_assignable_from_code(mirror::Class* dest_type, - mirror::Class* src_type) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(dest_type != NULL); - DCHECK(src_type != NULL); - return dest_type->IsAssignableFrom(src_type) ? 1 : 0; -} - -extern "C" void art_portable_check_cast_from_code(mirror::Class* dest_type, - mirror::Class* src_type) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(dest_type->IsClass()) << PrettyClass(dest_type); - DCHECK(src_type->IsClass()) << PrettyClass(src_type); - if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) { - ThrowClassCastException(dest_type, src_type); - } -} - -extern "C" void art_portable_check_put_array_element_from_code(mirror::Object* element, - mirror::Object* array) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (element == NULL) { - return; - } - DCHECK(array != NULL); - mirror::Class* array_class = array->GetClass(); - DCHECK(array_class != NULL); - mirror::Class* component_type = array_class->GetComponentType(); - mirror::Class* element_class = element->GetClass(); - if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) { - ThrowArrayStoreException(element_class, array_class); - } -} - -} // namespace art diff --git a/runtime/entrypoints/portable/portable_dexcache_entrypoints.cc b/runtime/entrypoints/portable/portable_dexcache_entrypoints.cc deleted file mode 100644 index 9364c46abf..0000000000 --- a/runtime/entrypoints/portable/portable_dexcache_entrypoints.cc +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 "gc/accounting/card_table-inl.h" -#include "mirror/art_method-inl.h" -#include "mirror/object-inl.h" - -namespace art { - -extern "C" mirror::Object* art_portable_initialize_static_storage_from_code(uint32_t type_idx, - mirror::ArtMethod* referrer, - Thread* thread) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ResolveVerifyAndClinit(type_idx, referrer, thread, true, false); -} - -extern "C" mirror::Object* art_portable_initialize_type_from_code(uint32_t type_idx, - mirror::ArtMethod* referrer, - Thread* thread) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ResolveVerifyAndClinit(type_idx, referrer, thread, false, false); -} - -extern "C" mirror::Object* art_portable_initialize_type_and_verify_access_from_code(uint32_t type_idx, - mirror::ArtMethod* referrer, - Thread* thread) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // Called when caller isn't guaranteed to have access to a type and the dex cache may be - // unpopulated - return ResolveVerifyAndClinit(type_idx, referrer, thread, false, true); -} - -extern "C" mirror::Object* art_portable_resolve_string_from_code(mirror::ArtMethod* referrer, - uint32_t string_idx) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ResolveStringFromCode(referrer, string_idx); -} - -} // namespace art diff --git a/runtime/entrypoints/portable/portable_entrypoints.h b/runtime/entrypoints/portable/portable_entrypoints.h deleted file mode 100644 index 6f77e1c42b..0000000000 --- a/runtime/entrypoints/portable/portable_entrypoints.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#ifndef ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ENTRYPOINTS_H_ -#define ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ENTRYPOINTS_H_ - -#include "dex_file-inl.h" -#include "runtime.h" - -namespace art { -namespace mirror { - class ArtMethod; - class Object; -} // namespace mirror -class Thread; - -#define PORTABLE_ENTRYPOINT_OFFSET(ptr_size, x) \ - Thread::PortableEntryPointOffset<ptr_size>(OFFSETOF_MEMBER(PortableEntryPoints, x)) - -// Pointers to functions that are called by code generated by compiler's adhering to the portable -// compiler ABI. -struct PACKED(4) PortableEntryPoints { - // Invocation - void (*pPortableImtConflictTrampoline)(mirror::ArtMethod*); - void (*pPortableResolutionTrampoline)(mirror::ArtMethod*); - void (*pPortableToInterpreterBridge)(mirror::ArtMethod*); -}; - -} // namespace art - -#endif // ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ENTRYPOINTS_H_ diff --git a/runtime/entrypoints/portable/portable_field_entrypoints.cc b/runtime/entrypoints/portable/portable_field_entrypoints.cc deleted file mode 100644 index 371aca4b2d..0000000000 --- a/runtime/entrypoints/portable/portable_field_entrypoints.cc +++ /dev/null @@ -1,245 +0,0 @@ -/* - * 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_field-inl.h" -#include "mirror/art_method-inl.h" -#include "mirror/object-inl.h" - -namespace art { - -extern "C" int32_t art_portable_set32_static_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer, - int32_t new_value) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, - referrer, - StaticPrimitiveWrite, - sizeof(uint32_t)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->Set32<false>(field->GetDeclaringClass(), new_value); - return 0; - } - field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, Thread::Current(), - sizeof(uint32_t)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->Set32<false>(field->GetDeclaringClass(), new_value); - return 0; - } - return -1; -} - -extern "C" int32_t art_portable_set64_static_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer, - int64_t new_value) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint64_t)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->Set64<false>(field->GetDeclaringClass(), new_value); - return 0; - } - field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, Thread::Current(), - sizeof(uint64_t)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->Set64<false>(field->GetDeclaringClass(), new_value); - return 0; - } - return -1; -} - -extern "C" int32_t art_portable_set_obj_static_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer, - mirror::Object* new_value) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, - sizeof(mirror::HeapReference<mirror::Object>)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->SetObj<false>(field->GetDeclaringClass(), new_value); - return 0; - } - field = FindFieldFromCode<StaticObjectWrite, true>(field_idx, referrer, Thread::Current(), - sizeof(mirror::HeapReference<mirror::Object>)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->SetObj<false>(field->GetDeclaringClass(), new_value); - return 0; - } - return -1; -} - -extern "C" int32_t art_portable_get32_static_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint32_t)); - if (LIKELY(field != NULL)) { - return field->Get32(field->GetDeclaringClass()); - } - field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, Thread::Current(), - sizeof(uint32_t)); - if (LIKELY(field != NULL)) { - return field->Get32(field->GetDeclaringClass()); - } - return 0; -} - -extern "C" int64_t art_portable_get64_static_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint64_t)); - if (LIKELY(field != NULL)) { - return field->Get64(field->GetDeclaringClass()); - } - field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, Thread::Current(), - sizeof(uint64_t)); - if (LIKELY(field != NULL)) { - return field->Get64(field->GetDeclaringClass()); - } - return 0; -} - -extern "C" mirror::Object* art_portable_get_obj_static_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead, - sizeof(mirror::HeapReference<mirror::Object>)); - if (LIKELY(field != NULL)) { - return field->GetObj(field->GetDeclaringClass()); - } - field = FindFieldFromCode<StaticObjectRead, true>(field_idx, referrer, Thread::Current(), - sizeof(mirror::HeapReference<mirror::Object>)); - if (LIKELY(field != NULL)) { - return field->GetObj(field->GetDeclaringClass()); - } - return 0; -} - -extern "C" int32_t art_portable_set32_instance_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer, - mirror::Object* obj, uint32_t new_value) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint32_t)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->Set32<false>(obj, new_value); - return 0; - } - field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, Thread::Current(), - sizeof(uint32_t)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->Set32<false>(obj, new_value); - return 0; - } - return -1; -} - -extern "C" int32_t art_portable_set64_instance_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer, - mirror::Object* obj, int64_t new_value) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint64_t)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->Set64<false>(obj, new_value); - return 0; - } - field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, Thread::Current(), - sizeof(uint64_t)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->Set64<false>(obj, new_value); - return 0; - } - return -1; -} - -extern "C" int32_t art_portable_set_obj_instance_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer, - mirror::Object* obj, - mirror::Object* new_value) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, - sizeof(mirror::HeapReference<mirror::Object>)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->SetObj<false>(obj, new_value); - return 0; - } - field = FindFieldFromCode<InstanceObjectWrite, true>(field_idx, referrer, Thread::Current(), - sizeof(mirror::HeapReference<mirror::Object>)); - if (LIKELY(field != NULL)) { - // Compiled code can't use transactional mode. - field->SetObj<false>(obj, new_value); - return 0; - } - return -1; -} - -extern "C" int32_t art_portable_get32_instance_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer, - mirror::Object* obj) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint32_t)); - if (LIKELY(field != NULL)) { - return field->Get32(obj); - } - field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, Thread::Current(), - sizeof(uint32_t)); - if (LIKELY(field != NULL)) { - return field->Get32(obj); - } - return 0; -} - -extern "C" int64_t art_portable_get64_instance_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer, - mirror::Object* obj) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint64_t)); - if (LIKELY(field != NULL)) { - return field->Get64(obj); - } - field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, Thread::Current(), - sizeof(uint64_t)); - if (LIKELY(field != NULL)) { - return field->Get64(obj); - } - return 0; -} - -extern "C" mirror::Object* art_portable_get_obj_instance_from_code(uint32_t field_idx, - mirror::ArtMethod* referrer, - mirror::Object* obj) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, - sizeof(mirror::HeapReference<mirror::Object>)); - if (LIKELY(field != NULL)) { - return field->GetObj(obj); - } - field = FindFieldFromCode<InstanceObjectRead, true>(field_idx, referrer, Thread::Current(), - sizeof(mirror::HeapReference<mirror::Object>)); - if (LIKELY(field != NULL)) { - return field->GetObj(obj); - } - return 0; -} - -} // namespace art diff --git a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc deleted file mode 100644 index afe769e5ec..0000000000 --- a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 "dex_instruction.h" -#include "entrypoints/entrypoint_utils.h" -#include "mirror/art_method-inl.h" - -namespace art { - -extern "C" void art_portable_fill_array_data_from_code(mirror::ArtMethod* method, - uint32_t dex_pc, - mirror::Array* array, - uint32_t payload_offset) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - UNUSED(dex_pc); - const DexFile::CodeItem* code_item = method->GetCodeItem(); - const Instruction::ArrayDataPayload* payload = - reinterpret_cast<const Instruction::ArrayDataPayload*>(code_item->insns_ + payload_offset); - FillArrayData(array, payload); -} - -} // namespace art diff --git a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc deleted file mode 100644 index 6f9c083c80..0000000000 --- a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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 diff --git a/runtime/entrypoints/portable/portable_jni_entrypoints.cc b/runtime/entrypoints/portable/portable_jni_entrypoints.cc deleted file mode 100644 index 0d0f21b795..0000000000 --- a/runtime/entrypoints/portable/portable_jni_entrypoints.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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/object-inl.h" -#include "thread-inl.h" - -namespace art { - -// Called on entry to JNI, transition out of Runnable and release share of mutator_lock_. -extern "C" uint32_t art_portable_jni_method_start(Thread* self) - UNLOCK_FUNCTION(Locks::mutator_lock_) { - JNIEnvExt* env = self->GetJniEnv(); - uint32_t saved_local_ref_cookie = env->local_ref_cookie; - env->local_ref_cookie = env->locals.GetSegmentState(); - self->TransitionFromRunnableToSuspended(kNative); - return saved_local_ref_cookie; -} - -extern "C" uint32_t art_portable_jni_method_start_synchronized(jobject to_lock, Thread* self) - UNLOCK_FUNCTION(Locks::mutator_lock_) NO_THREAD_SAFETY_ANALYSIS { - self->DecodeJObject(to_lock)->MonitorEnter(self); - return art_portable_jni_method_start(self); -} - -static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - JNIEnvExt* env = self->GetJniEnv(); - env->locals.SetSegmentState(env->local_ref_cookie); - env->local_ref_cookie = saved_local_ref_cookie; -} - -extern "C" void art_portable_jni_method_end(uint32_t saved_local_ref_cookie, Thread* self) - SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { - self->TransitionFromSuspendedToRunnable(); - PopLocalReferences(saved_local_ref_cookie, self); -} - - -extern "C" void art_portable_jni_method_end_synchronized(uint32_t saved_local_ref_cookie, - jobject locked, - Thread* self) - SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { - self->TransitionFromSuspendedToRunnable(); - UnlockJniSynchronizedMethod(locked, self); // Must decode before pop. - PopLocalReferences(saved_local_ref_cookie, self); -} - -extern "C" mirror::Object* art_portable_jni_method_end_with_reference(jobject result, - uint32_t saved_local_ref_cookie, - Thread* self) - SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { - self->TransitionFromSuspendedToRunnable(); - mirror::Object* o = self->DecodeJObject(result); // Must decode before pop. - PopLocalReferences(saved_local_ref_cookie, self); - // Process result. - if (UNLIKELY(self->GetJniEnv()->check_jni)) { - if (self->IsExceptionPending()) { - return NULL; - } - CheckReferenceResult(o, self); - } - return o; -} - -extern "C" mirror::Object* art_portable_jni_method_end_with_reference_synchronized(jobject result, - uint32_t saved_local_ref_cookie, - jobject locked, - Thread* self) - SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { - self->TransitionFromSuspendedToRunnable(); - UnlockJniSynchronizedMethod(locked, self); // Must decode before pop. - mirror::Object* o = self->DecodeJObject(result); - PopLocalReferences(saved_local_ref_cookie, self); - // Process result. - if (UNLIKELY(self->GetJniEnv()->check_jni)) { - if (self->IsExceptionPending()) { - return NULL; - } - CheckReferenceResult(o, self); - } - return o; -} - -} // namespace art diff --git a/runtime/entrypoints/portable/portable_lock_entrypoints.cc b/runtime/entrypoints/portable/portable_lock_entrypoints.cc deleted file mode 100644 index fcd3e9d49e..0000000000 --- a/runtime/entrypoints/portable/portable_lock_entrypoints.cc +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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/object-inl.h" - -namespace art { - -extern "C" void art_portable_lock_object_from_code(mirror::Object* obj, Thread* thread) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) - NO_THREAD_SAFETY_ANALYSIS /* EXCLUSIVE_LOCK_FUNCTION(Monitor::monitor_lock_) */ { - DCHECK(obj != nullptr); // Assumed to have been checked before entry. - obj->MonitorEnter(thread); // May block. - DCHECK(thread->HoldsLock(obj)); - // Only possible exception is NPE and is handled before entry. - DCHECK(!thread->IsExceptionPending()); -} - -extern "C" void art_portable_unlock_object_from_code(mirror::Object* obj, Thread* thread) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) - NO_THREAD_SAFETY_ANALYSIS /* UNLOCK_FUNCTION(Monitor::monitor_lock_) */ { - DCHECK(obj != nullptr); // Assumed to have been checked before entry. - // MonitorExit may throw exception. - obj->MonitorExit(thread); -} - -} // namespace art diff --git a/runtime/entrypoints/portable/portable_thread_entrypoints.cc b/runtime/entrypoints/portable/portable_thread_entrypoints.cc deleted file mode 100644 index 95ac66cbec..0000000000 --- a/runtime/entrypoints/portable/portable_thread_entrypoints.cc +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 "mirror/art_method-inl.h" -#include "verifier/dex_gc_map.h" -#include "stack.h" -#include "thread-inl.h" - -namespace art { - -class ShadowFrameCopyVisitor : public StackVisitor { - public: - explicit ShadowFrameCopyVisitor(Thread* self) : StackVisitor(self, NULL), prev_frame_(NULL), - top_frame_(NULL) {} - - bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (IsShadowFrame()) { - ShadowFrame* cur_frame = GetCurrentShadowFrame(); - size_t num_regs = cur_frame->NumberOfVRegs(); - mirror::ArtMethod* method = cur_frame->GetMethod(); - uint32_t dex_pc = cur_frame->GetDexPC(); - ShadowFrame* new_frame = ShadowFrame::Create(num_regs, NULL, method, dex_pc); - - const uint8_t* gc_map = method->GetNativeGcMap(sizeof(void*)); - verifier::DexPcToReferenceMap dex_gc_map(gc_map); - const uint8_t* reg_bitmap = dex_gc_map.FindBitMap(dex_pc); - for (size_t reg = 0; reg < num_regs; ++reg) { - if (TestBitmap(reg, reg_bitmap)) { - new_frame->SetVRegReference(reg, cur_frame->GetVRegReference(reg)); - } else { - new_frame->SetVReg(reg, cur_frame->GetVReg(reg)); - } - } - - if (prev_frame_ != NULL) { - prev_frame_->SetLink(new_frame); - } else { - top_frame_ = new_frame; - } - prev_frame_ = new_frame; - } - return true; - } - - ShadowFrame* GetShadowFrameCopy() { - return top_frame_; - } - - private: - static bool TestBitmap(int reg, const uint8_t* reg_vector) { - return ((reg_vector[reg / 8] >> (reg % 8)) & 0x01) != 0; - } - - ShadowFrame* prev_frame_; - ShadowFrame* top_frame_; -}; - -extern "C" void art_portable_test_suspend_from_code(Thread* self) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - self->CheckSuspend(); - if (Runtime::Current()->GetInstrumentation()->ShouldPortableCodeDeoptimize()) { - // Save out the shadow frame to the heap - ShadowFrameCopyVisitor visitor(self); - visitor.WalkStack(true); - self->SetDeoptimizationShadowFrame(visitor.GetShadowFrameCopy()); - self->SetDeoptimizationReturnValue(JValue()); - self->SetException(ThrowLocation(), Thread::GetDeoptimizationException()); - } -} - -extern "C" ShadowFrame* art_portable_push_shadow_frame_from_code(Thread* thread, - ShadowFrame* new_shadow_frame, - mirror::ArtMethod* method, - uint32_t num_vregs) { - ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame); - new_shadow_frame->SetMethod(method); - new_shadow_frame->SetNumberOfVRegs(num_vregs); - return old_frame; -} - -} // namespace art diff --git a/runtime/entrypoints/portable/portable_throw_entrypoints.cc b/runtime/entrypoints/portable/portable_throw_entrypoints.cc deleted file mode 100644 index 431735803d..0000000000 --- a/runtime/entrypoints/portable/portable_throw_entrypoints.cc +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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 "dex_instruction.h" -#include "entrypoints/entrypoint_utils-inl.h" -#include "mirror/art_method-inl.h" -#include "mirror/object-inl.h" - -namespace art { - -extern "C" void art_portable_throw_div_zero_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ThrowArithmeticExceptionDivideByZero(); -} - -extern "C" void art_portable_throw_array_bounds_from_code(int32_t index, int32_t length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ThrowArrayIndexOutOfBoundsException(index, length); -} - -extern "C" void art_portable_throw_no_such_method_from_code(int32_t method_idx) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ThrowNoSuchMethodError(method_idx); -} - -extern "C" void art_portable_throw_null_pointer_exception_from_code(uint32_t dex_pc) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // TODO: remove dex_pc argument from caller. - UNUSED(dex_pc); - Thread* self = Thread::Current(); - ThrowLocation throw_location = self->GetCurrentLocationForThrow(); - ThrowNullPointerExceptionFromDexPC(throw_location); -} - -extern "C" void art_portable_throw_stack_overflow_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ThrowStackOverflowError(Thread::Current()); -} - -extern "C" void art_portable_throw_exception_from_code(mirror::Throwable* exception) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Thread* self = Thread::Current(); - ThrowLocation throw_location = self->GetCurrentLocationForThrow(); - if (exception == NULL) { - ThrowNullPointerException(NULL, "throw with null exception"); - } else { - self->SetException(throw_location, exception); - } -} - -extern "C" void* art_portable_get_and_clear_exception(Thread* self) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(self->IsExceptionPending()); - // TODO: make this inline. - mirror::Throwable* exception = self->GetException(NULL); - self->ClearException(); - return exception; -} - -extern "C" int32_t art_portable_find_catch_block_from_code(mirror::ArtMethod* current_method, - uint32_t ti_offset) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Thread* self = Thread::Current(); // TODO: make an argument. - ThrowLocation throw_location; - mirror::Throwable* exception = self->GetException(&throw_location); - // Check for special deoptimization exception. - if (UNLIKELY(reinterpret_cast<intptr_t>(exception) == -1)) { - return -1; - } - mirror::Class* exception_type = exception->GetClass(); - StackHandleScope<1> hs(self); - const DexFile::CodeItem* code_item = current_method->GetCodeItem(); - DCHECK_LT(ti_offset, code_item->tries_size_); - const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset); - - int iter_index = 0; - int result = -1; - uint32_t catch_dex_pc = -1; - // Iterate over the catch handlers associated with dex_pc - for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) { - uint16_t iter_type_idx = it.GetHandlerTypeIndex(); - // Catch all case - if (iter_type_idx == DexFile::kDexNoIndex16) { - catch_dex_pc = it.GetHandlerAddress(); - result = iter_index; - break; - } - // Does this catch exception type apply? - mirror::Class* iter_exception_type = - current_method->GetDexCacheResolvedType(iter_type_idx); - if (UNLIKELY(iter_exception_type == NULL)) { - // TODO: check, the verifier (class linker?) should take care of resolving all exception - // classes early. - LOG(WARNING) << "Unresolved exception class when finding catch block: " - << current_method->GetTypeDescriptorFromTypeIdx(iter_type_idx); - } else if (iter_exception_type->IsAssignableFrom(exception_type)) { - catch_dex_pc = it.GetHandlerAddress(); - result = iter_index; - break; - } - ++iter_index; - } - if (result != -1) { - // Handler found. - Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent( - self, throw_location, current_method, catch_dex_pc, exception); - // If the catch block has no move-exception then clear the exception for it. - const Instruction* first_catch_instr = Instruction::At( - ¤t_method->GetCodeItem()->insns_[catch_dex_pc]); - if (first_catch_instr->Opcode() != Instruction::MOVE_EXCEPTION) { - self->ClearException(); - } - } - return result; -} - -} // namespace art diff --git a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc deleted file mode 100644 index 2a2771f31c..0000000000 --- a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#ifndef ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ARGUMENT_VISITOR_H_ -#define ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ARGUMENT_VISITOR_H_ - -#include "dex_instruction-inl.h" -#include "entrypoints/entrypoint_utils-inl.h" -#include "entrypoints/runtime_asm_entrypoints.h" -#include "interpreter/interpreter.h" -#include "mirror/art_method-inl.h" -#include "mirror/object-inl.h" -#include "scoped_thread_state_change.h" - -namespace art { - -class ShortyHelper { - public: - ShortyHelper(const char* shorty, uint32_t shorty_len, bool is_static) - : shorty_(shorty), shorty_len_(shorty_len), is_static_(is_static) { - } - - const char* GetShorty() const { - return shorty_; - } - - uint32_t GetShortyLength() const { - return shorty_len_; - } - - size_t NumArgs() const { - // "1 +" because the first in Args is the receiver. - // "- 1" because we don't count the return type. - return (is_static_ ? 0 : 1) + GetShortyLength() - 1; - } - - // Get the primitive type associated with the given parameter. - Primitive::Type GetParamPrimitiveType(size_t param) const { - CHECK_LT(param, NumArgs()); - if (is_static_) { - param++; // 0th argument must skip return value at start of the shorty. - } else if (param == 0) { - return Primitive::kPrimNot; - } - return Primitive::GetType(shorty_[param]); - } - - // Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods. - bool IsParamALongOrDouble(size_t param) const { - Primitive::Type type = GetParamPrimitiveType(param); - return type == Primitive::kPrimLong || type == Primitive::kPrimDouble; - } - - // Is the specified parameter a reference, where parameter 0 is 'this' for instance methods. - bool IsParamAReference(size_t param) const { - return GetParamPrimitiveType(param) == Primitive::kPrimNot; - } - - private: - const char* const shorty_; - const uint32_t shorty_len_; - const bool is_static_; - - DISALLOW_COPY_AND_ASSIGN(ShortyHelper); -}; - -// Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame. -class PortableArgumentVisitor { - public: -// Offset to first (not the Method*) argument in a Runtime::kRefAndArgs callee save frame. -// Size of Runtime::kRefAndArgs callee save frame. -// Size of Method* and register parameters in out stack arguments. -#if defined(__arm__) -#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 8 -#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 48 -#define PORTABLE_STACK_ARG_SKIP 0 -#elif defined(__mips__) -#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4 -#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 64 -#define PORTABLE_STACK_ARG_SKIP 16 -#elif defined(__i386__) -// For x86 there are no register arguments and the stack pointer will point directly to the called -// method argument passed by the caller. -#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0 -#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0 -#define PORTABLE_STACK_ARG_SKIP 4 -#elif defined(__x86_64__) -// TODO: implement and check these. -#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 16 -#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 96 -#define PORTABLE_STACK_ARG_SKIP 0 -#else -// TODO: portable should be disabled for aarch64 for now. -// #error "Unsupported architecture" -#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0 -#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0 -#define PORTABLE_STACK_ARG_SKIP 0 -#endif - - PortableArgumentVisitor(ShortyHelper& caller_mh, mirror::ArtMethod** sp) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : - caller_mh_(caller_mh), - args_in_regs_(ComputeArgsInRegs(caller_mh)), - num_params_(caller_mh.NumArgs()), - reg_args_(reinterpret_cast<uint8_t*>(sp) + PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET), - stack_args_(reinterpret_cast<uint8_t*>(sp) + PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE - + PORTABLE_STACK_ARG_SKIP), - cur_args_(reg_args_), - cur_arg_index_(0), - param_index_(0) { - } - - virtual ~PortableArgumentVisitor() {} - - virtual void Visit() = 0; - - bool IsParamAReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return caller_mh_.IsParamAReference(param_index_); - } - - bool IsParamALongOrDouble() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return caller_mh_.IsParamALongOrDouble(param_index_); - } - - Primitive::Type GetParamPrimitiveType() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return caller_mh_.GetParamPrimitiveType(param_index_); - } - - uint8_t* GetParamAddress() const { - return cur_args_ + (cur_arg_index_ * sizeof(void*)); - } - - void VisitArguments() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - for (cur_arg_index_ = 0; cur_arg_index_ < args_in_regs_ && param_index_ < num_params_; ) { -#if (defined(__arm__) || defined(__mips__)) - if (IsParamALongOrDouble() && cur_arg_index_ == 2) { - break; - } -#endif - Visit(); - cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1); - param_index_++; - } - cur_args_ = stack_args_; - cur_arg_index_ = 0; - while (param_index_ < num_params_) { -#if (defined(__arm__) || defined(__mips__)) - if (IsParamALongOrDouble() && cur_arg_index_ % 2 != 0) { - cur_arg_index_++; - } -#endif - Visit(); - cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1); - param_index_++; - } - } - - private: - static size_t ComputeArgsInRegs(ShortyHelper& mh) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { -#if (defined(__i386__)) - UNUSED(mh); - return 0; -#else - size_t args_in_regs = 0; - size_t num_params = mh.NumArgs(); - for (size_t i = 0; i < num_params; i++) { - args_in_regs = args_in_regs + (mh.IsParamALongOrDouble(i) ? 2 : 1); - if (args_in_regs > 3) { - args_in_regs = 3; - break; - } - } - return args_in_regs; -#endif - } - ShortyHelper& caller_mh_; - const size_t args_in_regs_; - const size_t num_params_; - uint8_t* const reg_args_; - uint8_t* const stack_args_; - uint8_t* cur_args_; - size_t cur_arg_index_; - size_t param_index_; -}; - -// Visits arguments on the stack placing them into the shadow frame. -class BuildPortableShadowFrameVisitor : public PortableArgumentVisitor { - public: - BuildPortableShadowFrameVisitor(ShortyHelper& caller_mh, mirror::ArtMethod** sp, - ShadowFrame& sf, size_t first_arg_reg) : - PortableArgumentVisitor(caller_mh, sp), sf_(sf), cur_reg_(first_arg_reg) { } - virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Primitive::Type type = GetParamPrimitiveType(); - switch (type) { - case Primitive::kPrimLong: // Fall-through. - case Primitive::kPrimDouble: - sf_.SetVRegLong(cur_reg_, *reinterpret_cast<jlong*>(GetParamAddress())); - ++cur_reg_; - break; - case Primitive::kPrimNot: - sf_.SetVRegReference(cur_reg_, *reinterpret_cast<mirror::Object**>(GetParamAddress())); - break; - case Primitive::kPrimBoolean: // Fall-through. - case Primitive::kPrimByte: // Fall-through. - case Primitive::kPrimChar: // Fall-through. - case Primitive::kPrimShort: // Fall-through. - case Primitive::kPrimInt: // Fall-through. - case Primitive::kPrimFloat: - sf_.SetVReg(cur_reg_, *reinterpret_cast<jint*>(GetParamAddress())); - break; - case Primitive::kPrimVoid: - LOG(FATAL) << "UNREACHABLE"; - UNREACHABLE(); - } - ++cur_reg_; - } - - private: - ShadowFrame& sf_; - size_t cur_reg_; - - DISALLOW_COPY_AND_ASSIGN(BuildPortableShadowFrameVisitor); -}; - -extern "C" uint64_t artPortableToInterpreterBridge(mirror::ArtMethod* method, Thread* self, - mirror::ArtMethod** sp) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // Ensure we don't get thread suspension until the object arguments are safely in the shadow - // frame. - // FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs); - - if (method->IsAbstract()) { - ThrowAbstractMethodError(method); - return 0; - } else { - const char* old_cause = self->StartAssertNoThreadSuspension("Building interpreter shadow frame"); - StackHandleScope<2> hs(self); - uint32_t shorty_len; - const char* shorty = method->GetShorty(&shorty_len); - ShortyHelper mh(shorty, shorty_len, method->IsStatic()); - const DexFile::CodeItem* code_item = method->GetCodeItem(); - uint16_t num_regs = code_item->registers_size_; - void* memory = alloca(ShadowFrame::ComputeSize(num_regs)); - ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, NULL, // No last shadow coming from quick. - method, 0, memory)); - size_t first_arg_reg = code_item->registers_size_ - code_item->ins_size_; - BuildPortableShadowFrameVisitor shadow_frame_builder(mh, sp, - *shadow_frame, first_arg_reg); - shadow_frame_builder.VisitArguments(); - // Push a transition back into managed code onto the linked list in thread. - ManagedStack fragment; - self->PushManagedStackFragment(&fragment); - self->PushShadowFrame(shadow_frame); - self->EndAssertNoThreadSuspension(old_cause); - - if (method->IsStatic() && !method->GetDeclaringClass()->IsInitialized()) { - // Ensure static method's class is initialized. - Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass())); - if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) { - DCHECK(Thread::Current()->IsExceptionPending()); - self->PopManagedStackFragment(fragment); - return 0; - } - } - - JValue result = interpreter::EnterInterpreterFromEntryPoint(self, code_item, shadow_frame); - // Pop transition. - self->PopManagedStackFragment(fragment); - return result.GetJ(); - } -} - -// Visits arguments on the stack placing them into the args vector, Object* arguments are converted -// to jobjects. -class BuildPortableArgumentVisitor : public PortableArgumentVisitor { - public: - BuildPortableArgumentVisitor(ShortyHelper& caller_mh, mirror::ArtMethod** sp, - ScopedObjectAccessUnchecked& soa, std::vector<jvalue>& args) : - PortableArgumentVisitor(caller_mh, sp), soa_(soa), args_(args) {} - - virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - jvalue val; - Primitive::Type type = GetParamPrimitiveType(); - switch (type) { - case Primitive::kPrimNot: { - mirror::Object* obj = *reinterpret_cast<mirror::Object**>(GetParamAddress()); - val.l = soa_.AddLocalReference<jobject>(obj); - break; - } - case Primitive::kPrimLong: // Fall-through. - case Primitive::kPrimDouble: - val.j = *reinterpret_cast<jlong*>(GetParamAddress()); - break; - case Primitive::kPrimBoolean: // Fall-through. - case Primitive::kPrimByte: // Fall-through. - case Primitive::kPrimChar: // Fall-through. - case Primitive::kPrimShort: // Fall-through. - case Primitive::kPrimInt: // Fall-through. - case Primitive::kPrimFloat: - val.i = *reinterpret_cast<jint*>(GetParamAddress()); - break; - case Primitive::kPrimVoid: - LOG(FATAL) << "UNREACHABLE"; - UNREACHABLE(); - } - args_.push_back(val); - } - - private: - ScopedObjectAccessUnchecked& soa_; - std::vector<jvalue>& args_; - - DISALLOW_COPY_AND_ASSIGN(BuildPortableArgumentVisitor); -}; - -// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method -// which is responsible for recording callee save registers. We explicitly place into jobjects the -// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a -// field within the proxy object, which will box the primitive arguments and deal with error cases. -extern "C" uint64_t artPortableProxyInvokeHandler(mirror::ArtMethod* proxy_method, - mirror::Object* receiver, - Thread* self, mirror::ArtMethod** sp) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // Ensure we don't get thread suspension until the object arguments are safely in jobjects. - const char* old_cause = - self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments"); - self->VerifyStack(); - // Start new JNI local reference state. - JNIEnvExt* env = self->GetJniEnv(); - ScopedObjectAccessUnchecked soa(env); - ScopedJniEnvLocalRefState env_state(env); - // Create local ref. copies of proxy method and the receiver. - jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver); - - // Placing arguments into args vector and remove the receiver. - uint32_t shorty_len; - const char* shorty = proxy_method->GetShorty(&shorty_len); - ShortyHelper proxy_mh(shorty, shorty_len, false); - std::vector<jvalue> args; - BuildPortableArgumentVisitor local_ref_visitor(proxy_mh, sp, soa, args); - local_ref_visitor.VisitArguments(); - args.erase(args.begin()); - - // Convert proxy method into expected interface method. - mirror::ArtMethod* interface_method = proxy_method->FindOverriddenMethod(); - DCHECK(interface_method != NULL); - DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method); - jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method); - - // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code - // that performs allocations. - self->EndAssertNoThreadSuspension(old_cause); - JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(), - rcvr_jobj, interface_method_jobj, args); - return result.GetJ(); -} - -// Lazily resolve a method for portable. Called by stub code. -extern "C" const void* artPortableResolutionTrampoline(mirror::ArtMethod* called, - mirror::Object* receiver, - Thread* self, - mirror::ArtMethod** called_addr) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - uint32_t dex_pc; - mirror::ArtMethod* caller = self->GetCurrentMethod(&dex_pc); - - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - InvokeType invoke_type; - bool is_range; - if (called->IsRuntimeMethod()) { - const DexFile::CodeItem* code = caller->GetCodeItem(); - CHECK_LT(dex_pc, code->insns_size_in_code_units_); - const Instruction* instr = Instruction::At(&code->insns_[dex_pc]); - Instruction::Code instr_code = instr->Opcode(); - switch (instr_code) { - case Instruction::INVOKE_DIRECT: - invoke_type = kDirect; - is_range = false; - break; - case Instruction::INVOKE_DIRECT_RANGE: - invoke_type = kDirect; - is_range = true; - break; - case Instruction::INVOKE_STATIC: - invoke_type = kStatic; - is_range = false; - break; - case Instruction::INVOKE_STATIC_RANGE: - invoke_type = kStatic; - is_range = true; - break; - case Instruction::INVOKE_SUPER: - invoke_type = kSuper; - is_range = false; - break; - case Instruction::INVOKE_SUPER_RANGE: - invoke_type = kSuper; - is_range = true; - break; - case Instruction::INVOKE_VIRTUAL: - invoke_type = kVirtual; - is_range = false; - break; - case Instruction::INVOKE_VIRTUAL_RANGE: - invoke_type = kVirtual; - is_range = true; - break; - case Instruction::INVOKE_INTERFACE: - invoke_type = kInterface; - is_range = false; - break; - case Instruction::INVOKE_INTERFACE_RANGE: - invoke_type = kInterface; - is_range = true; - break; - default: - LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL); - // Avoid used uninitialized warnings. - invoke_type = kDirect; - is_range = true; - } - uint32_t dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c(); - called = class_linker->ResolveMethod(Thread::Current(), dex_method_idx, &caller, invoke_type); - // Incompatible class change should have been handled in resolve method. - CHECK(!called->CheckIncompatibleClassChange(invoke_type)); - // Refine called method based on receiver. - if (invoke_type == kVirtual) { - called = receiver->GetClass()->FindVirtualMethodForVirtual(called); - } else if (invoke_type == kInterface) { - called = receiver->GetClass()->FindVirtualMethodForInterface(called); - } - } else { - CHECK(called->IsStatic()) << PrettyMethod(called); - invoke_type = kStatic; - // Incompatible class change should have been handled in resolve method. - CHECK(!called->CheckIncompatibleClassChange(invoke_type)); - } - const void* code = nullptr; - if (LIKELY(!self->IsExceptionPending())) { - // Ensure that the called method's class is initialized. - StackHandleScope<1> hs(self); - Handle<mirror::Class> called_class(hs.NewHandle(called->GetDeclaringClass())); - class_linker->EnsureInitialized(self, called_class, true, true); - if (LIKELY(called_class->IsInitialized())) { - code = called->GetEntryPointFromPortableCompiledCode(); - // TODO: remove this after we solve the link issue. - if (code == nullptr) { - bool have_portable_code; - code = class_linker->GetPortableOatCodeFor(called, &have_portable_code); - } - } else if (called_class->IsInitializing()) { - if (invoke_type == kStatic) { - // Class is still initializing, go to oat and grab code (trampoline must be left in place - // until class is initialized to stop races between threads). - bool have_portable_code; - code = class_linker->GetPortableOatCodeFor(called, &have_portable_code); - } else { - // No trampoline for non-static methods. - code = called->GetEntryPointFromPortableCompiledCode(); - // TODO: remove this after we solve the link issue. - if (code == nullptr) { - bool have_portable_code; - code = class_linker->GetPortableOatCodeFor(called, &have_portable_code); - } - } - } else { - DCHECK(called_class->IsErroneous()); - } - } - if (LIKELY(code != nullptr)) { - // Expect class to at least be initializing. - DCHECK(called->GetDeclaringClass()->IsInitializing()); - // Don't want infinite recursion. - DCHECK(!class_linker->IsPortableResolutionStub(code)); - // Set up entry into main method - *called_addr = called; - } - return code; -} - -} // namespace art - -#endif // ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ARGUMENT_VISITOR_H_ diff --git a/runtime/entrypoints/runtime_asm_entrypoints.h b/runtime/entrypoints/runtime_asm_entrypoints.h index db36a73956..420e8db7c8 100644 --- a/runtime/entrypoints/runtime_asm_entrypoints.h +++ b/runtime/entrypoints/runtime_asm_entrypoints.h @@ -28,66 +28,30 @@ static inline const void* GetJniDlsymLookupStub() { return reinterpret_cast<const void*>(art_jni_dlsym_lookup_stub); } -// Return the address of portable stub code for handling IMT conflicts. -extern "C" void art_portable_imt_conflict_trampoline(mirror::ArtMethod*); -static inline const void* GetPortableImtConflictStub() { - return reinterpret_cast<const void*>(art_portable_imt_conflict_trampoline); -} - // Return the address of quick stub code for handling IMT conflicts. extern "C" void art_quick_imt_conflict_trampoline(mirror::ArtMethod*); static inline const void* GetQuickImtConflictStub() { return reinterpret_cast<const void*>(art_quick_imt_conflict_trampoline); } -// Return the address of portable stub code for bridging from portable code to the interpreter. -extern "C" void art_portable_to_interpreter_bridge(mirror::ArtMethod*); -static inline const void* GetPortableToInterpreterBridge() { - return reinterpret_cast<const void*>(art_portable_to_interpreter_bridge); -} - // Return the address of quick stub code for bridging from quick code to the interpreter. extern "C" void art_quick_to_interpreter_bridge(mirror::ArtMethod*); static inline const void* GetQuickToInterpreterBridge() { return reinterpret_cast<const void*>(art_quick_to_interpreter_bridge); } -// Return the address of portable stub code for bridging from portable code to quick. -static inline const void* GetPortableToQuickBridge() { - // TODO: portable to quick bridge. Bug: 8196384 - return GetPortableToInterpreterBridge(); -} - -// Return the address of quick stub code for bridging from quick code to portable. -static inline const void* GetQuickToPortableBridge() { - // TODO: quick to portable bridge. Bug: 8196384 - return GetQuickToInterpreterBridge(); -} - // Return the address of quick stub code for handling JNI calls. extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*); static inline const void* GetQuickGenericJniStub() { return reinterpret_cast<const void*>(art_quick_generic_jni_trampoline); } -// Return the address of portable stub code for handling transitions into the proxy invoke handler. -extern "C" void art_portable_proxy_invoke_handler(); -static inline const void* GetPortableProxyInvokeHandler() { - return reinterpret_cast<const void*>(art_portable_proxy_invoke_handler); -} - // Return the address of quick stub code for handling transitions into the proxy invoke handler. extern "C" void art_quick_proxy_invoke_handler(); static inline const void* GetQuickProxyInvokeHandler() { return reinterpret_cast<const void*>(art_quick_proxy_invoke_handler); } -// Return the address of portable stub code for resolving a method at first call. -extern "C" void art_portable_resolution_trampoline(mirror::ArtMethod*); -static inline const void* GetPortableResolutionStub() { - return reinterpret_cast<const void*>(art_portable_resolution_trampoline); -} - // Return the address of quick stub code for resolving a method at first call. extern "C" void art_quick_resolution_trampoline(mirror::ArtMethod*); static inline const void* GetQuickResolutionStub() { |