diff options
author | 2013-04-24 18:41:58 -0700 | |
---|---|---|
committer | 2013-04-26 14:50:52 -0700 | |
commit | 79fe539587d4c09244172d0168eeed0ec9770466 (patch) | |
tree | 4fb8fbd03727a74acb4dfde7e969adf32ee32750 | |
parent | 09b55e1df3b0bcecee25882e45e882887cc8654f (diff) |
Removing remaining compiled stubs from image.
Abstract method error stub and jni dlsym lookup stubs are gone.
After this change, the image no longer needs to be executable.
Change-Id: Ic75d72bf7e76e3b8ecc596e82af68ab592dde15e
31 files changed, 224 insertions, 578 deletions
diff --git a/build/Android.common.mk b/build/Android.common.mk index 59426a4d1d..c8212ef242 100644 --- a/build/Android.common.mk +++ b/build/Android.common.mk @@ -222,9 +222,6 @@ LIBART_COMMON_SRC_FILES := \ src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc \ src/native/sun_misc_Unsafe.cc \ src/oat.cc \ - src/oat/runtime/arm/stub_arm.cc \ - src/oat/runtime/mips/stub_mips.cc \ - src/oat/runtime/x86/stub_x86.cc \ src/oat/utils/arm/assembler_arm.cc \ src/oat/utils/arm/managed_register_arm.cc \ src/oat/utils/assembler.cc \ diff --git a/src/class_linker.cc b/src/class_linker.cc index 9dee36a7b3..d262a5d5a7 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -1600,7 +1600,7 @@ static void LinkCode(SirtRef<mirror::AbstractMethod>& method, const OatFile::Oat Runtime* runtime = Runtime::Current(); if (method->IsAbstract()) { - method->SetCode(runtime->GetAbstractMethodErrorStubArray()->GetData()); + method->SetCode(GetAbstractMethodErrorStub()); return; } diff --git a/src/common_test.h b/src/common_test.h index 05b0e05a7b..6876274b7b 100644 --- a/src/common_test.h +++ b/src/common_test.h @@ -234,8 +234,7 @@ class CommonTest : public testing::Test { } else { const void* method_code; if (method->IsAbstract()) { - MakeExecutable(runtime_->GetAbstractMethodErrorStubArray()); - method_code = runtime_->GetAbstractMethodErrorStubArray()->GetData(); + method_code = GetAbstractMethodErrorStub(); } else { // No code? You must mean to go into the interpreter. method_code = GetInterpreterEntryPoint(); @@ -353,8 +352,6 @@ class CommonTest : public testing::Test { CompilerBackend compiler_backend = kQuick; #endif - runtime_->SetJniDlsymLookupStub(CompilerDriver::CreateJniDlsymLookupStub(instruction_set)); - runtime_->SetAbstractMethodErrorStubArray(CompilerDriver::CreateAbstractMethodErrorStub(instruction_set)); if (!runtime_->HasResolutionMethod()) { runtime_->SetResolutionMethod(runtime_->CreateResolutionMethod()); } @@ -487,8 +484,6 @@ class CommonTest : public testing::Test { CHECK(method != NULL); compiler_driver_->CompileOne(method); MakeExecutable(method); - - MakeExecutable(runtime_->GetJniDlsymLookupStub()); } void CompileDirectMethod(mirror::ClassLoader* class_loader, diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc index e6f4b67b91..1660914ce3 100644 --- a/src/compiler/driver/compiler_driver.cc +++ b/src/compiler/driver/compiler_driver.cc @@ -28,7 +28,6 @@ #include "dex_file-inl.h" #include "jni_internal.h" #include "oat_file.h" -#include "oat/runtime/stub.h" #include "object_utils.h" #include "runtime.h" #include "gc/card_table-inl.h" @@ -409,36 +408,6 @@ CompilerTls* CompilerDriver::GetTls() { return res; } -mirror::ByteArray* CompilerDriver::CreateJniDlsymLookupStub(InstructionSet instruction_set) { - switch (instruction_set) { - case kArm: - case kThumb2: - return arm::CreateJniDlsymLookupStub(); - case kMips: - return mips::CreateJniDlsymLookupStub(); - case kX86: - return x86::CreateJniDlsymLookupStub(); - default: - LOG(FATAL) << "Unknown InstructionSet: " << instruction_set; - return NULL; - } -} - -mirror::ByteArray* CompilerDriver::CreateAbstractMethodErrorStub(InstructionSet instruction_set) { - switch (instruction_set) { - case kArm: - case kThumb2: - return arm::CreateAbstractMethodErrorStub(); - case kMips: - return mips::CreateAbstractMethodErrorStub(); - case kX86: - return x86::CreateAbstractMethodErrorStub(); - default: - LOG(FATAL) << "Unknown InstructionSet: " << instruction_set; - return NULL; - } -} - void CompilerDriver::CompileAll(jobject class_loader, const std::vector<const DexFile*>& dex_files) { DCHECK(!Runtime::Current()->IsStarted()); diff --git a/src/compiler/driver/compiler_driver.h b/src/compiler/driver/compiler_driver.h index 3581f5f68f..a20e5ef585 100644 --- a/src/compiler/driver/compiler_driver.h +++ b/src/compiler/driver/compiler_driver.h @@ -102,13 +102,6 @@ class CompilerDriver { CompilerTls* GetTls(); - // Stub to throw AbstractMethodError - static mirror::ByteArray* CreateAbstractMethodErrorStub(InstructionSet instruction_set) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - static mirror::ByteArray* CreateJniDlsymLookupStub(InstructionSet instruction_set) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // A class is uniquely located by its DexFile and the class_defs_ table index into that DexFile typedef std::pair<const DexFile*, uint32_t> ClassReference; diff --git a/src/dex2oat.cc b/src/dex2oat.cc index 36b8d260a0..e41e537ee0 100644 --- a/src/dex2oat.cc +++ b/src/dex2oat.cc @@ -372,12 +372,6 @@ class Dex2Oat { } Runtime* runtime = Runtime::Current(); // if we loaded an existing image, we will reuse values from the image roots. - if (!runtime->HasJniDlsymLookupStub()) { - runtime->SetJniDlsymLookupStub(CompilerDriver::CreateJniDlsymLookupStub(instruction_set)); - } - if (!runtime->HasAbstractMethodErrorStubArray()) { - runtime->SetAbstractMethodErrorStubArray(CompilerDriver::CreateAbstractMethodErrorStub(instruction_set)); - } if (!runtime->HasResolutionMethod()) { runtime->SetResolutionMethod(runtime->CreateResolutionMethod()); } diff --git a/src/gc/space.cc b/src/gc/space.cc index d7378c3d70..bfc3e86d0a 100644 --- a/src/gc/space.cc +++ b/src/gc/space.cc @@ -512,12 +512,6 @@ ImageSpace* ImageSpace::Create(const std::string& image_file_name) { DCHECK_EQ(0, memcmp(&image_header, map->Begin(), sizeof(ImageHeader))); Runtime* runtime = Runtime::Current(); - mirror::Object* jni_stub_array = image_header.GetImageRoot(ImageHeader::kJniStubArray); - runtime->SetJniDlsymLookupStub(down_cast<mirror::ByteArray*>(jni_stub_array)); - - mirror::Object* ame_stub_array = image_header.GetImageRoot(ImageHeader::kAbstractMethodErrorStubArray); - runtime->SetAbstractMethodErrorStubArray(down_cast<mirror::ByteArray*>(ame_stub_array)); - mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod); runtime->SetResolutionMethod(down_cast<mirror::AbstractMethod*>(resolution_method)); diff --git a/src/image.cc b/src/image.cc index c746c8e6e3..686a117c99 100644 --- a/src/image.cc +++ b/src/image.cc @@ -24,7 +24,7 @@ namespace art { const byte ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; -const byte ImageHeader::kImageVersion[] = { '0', '0', '3', '\0' }; +const byte ImageHeader::kImageVersion[] = { '0', '0', '4', '\0' }; ImageHeader::ImageHeader(uint32_t image_begin, uint32_t image_roots, diff --git a/src/image.h b/src/image.h index 040e3fe36c..f14d7d190a 100644 --- a/src/image.h +++ b/src/image.h @@ -81,8 +81,6 @@ class PACKED(4) ImageHeader { } enum ImageRoot { - kJniStubArray, - kAbstractMethodErrorStubArray, kResolutionMethod, kCalleeSaveMethod, kRefsOnlySaveMethod, diff --git a/src/image_test.cc b/src/image_test.cc index e4deda3e6d..192e28ac0e 100644 --- a/src/image_test.cc +++ b/src/image_test.cc @@ -127,8 +127,6 @@ TEST_F(ImageTest, WriteRead) { ASSERT_TRUE(runtime_.get() != NULL); class_linker_ = runtime_->GetClassLinker(); - ASSERT_TRUE(runtime_->GetJniDlsymLookupStub() != NULL); - Heap* heap = Runtime::Current()->GetHeap(); ASSERT_EQ(2U, heap->GetSpaces().size()); ASSERT_TRUE(heap->GetSpaces()[0]->IsImageSpace()); diff --git a/src/image_writer.cc b/src/image_writer.cc index 16ac385212..d9e435380d 100644 --- a/src/image_writer.cc +++ b/src/image_writer.cc @@ -351,9 +351,6 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { image_roots(self, ObjectArray<Object>::Alloc(self, object_array_class, ImageHeader::kImageRootsMax)); - image_roots->Set(ImageHeader::kJniStubArray, runtime->GetJniDlsymLookupStub()); - image_roots->Set(ImageHeader::kAbstractMethodErrorStubArray, - runtime->GetAbstractMethodErrorStubArray()); image_roots->Set(ImageHeader::kResolutionMethod, runtime->GetResolutionMethod()); image_roots->Set(ImageHeader::kCalleeSaveMethod, runtime->GetCalleeSaveMethod(Runtime::kSaveAll)); @@ -478,10 +475,8 @@ void ImageWriter::FixupMethod(const AbstractMethod* orig, AbstractMethod* copy) // OatWriter replaces the code_ with an offset value. // Here we readjust to a pointer relative to oat_begin_ if (orig->IsAbstract()) { - // Abstract methods are pointed to a stub that will throw AbstractMethodError if they are called - ByteArray* orig_ame_stub_array_ = Runtime::Current()->GetAbstractMethodErrorStubArray(); - ByteArray* copy_ame_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_ame_stub_array_)); - copy->SetCode(copy_ame_stub_array_->GetData()); + // Code for abstract methods is set to the abstract method error stub when we load the image. + copy->SetCode(NULL); return; } @@ -495,11 +490,9 @@ void ImageWriter::FixupMethod(const AbstractMethod* orig, AbstractMethod* copy) copy->SetCode(GetOatAddress(orig->GetOatCodeOffset())); if (orig->IsNative()) { - // The native method's pointer is directed to a stub to lookup via dlsym. + // The native method's pointer is set to a stub to lookup via dlsym when we load the image. // Note this is not the code_ pointer, that is handled above. - ByteArray* orig_jni_stub_array_ = Runtime::Current()->GetJniDlsymLookupStub(); - ByteArray* copy_jni_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_jni_stub_array_)); - copy->SetNativeMethod(copy_jni_stub_array_->GetData()); + copy->SetNativeMethod(NULL); } else { // normal (non-abstract non-native) methods have mapping tables to relocate uint32_t mapping_table_off = orig->GetOatMappingTableOffset(); diff --git a/src/jni_internal.h b/src/jni_internal.h index 131032a29d..dc6ca4af52 100644 --- a/src/jni_internal.h +++ b/src/jni_internal.h @@ -51,7 +51,6 @@ class Thread; void SetJniGlobalsMax(size_t max); void JniAbortF(const char* jni_function_name, const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))); -void* FindNativeMethod(Thread* thread); void RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINativeMethod* methods, size_t method_count); diff --git a/src/mirror/abstract_method.cc b/src/mirror/abstract_method.cc index 3ab3a939a8..559b5581ac 100644 --- a/src/mirror/abstract_method.cc +++ b/src/mirror/abstract_method.cc @@ -324,7 +324,7 @@ void AbstractMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JV bool AbstractMethod::IsRegistered() const { void* native_method = GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_), false); CHECK(native_method != NULL); - void* jni_stub = Runtime::Current()->GetJniDlsymLookupStub()->GetData(); + void* jni_stub = GetJniDlsymLookupStub(); return native_method != jni_stub; } @@ -352,7 +352,7 @@ void AbstractMethod::RegisterNative(Thread* self, const void* native_method) { void AbstractMethod::UnregisterNative(Thread* self) { CHECK(IsNative()) << PrettyMethod(this); // restore stub to lookup native pointer via dlsym - RegisterNative(self, Runtime::Current()->GetJniDlsymLookupStub()->GetData()); + RegisterNative(self, GetJniDlsymLookupStub()); } void AbstractMethod::SetNativeMethod(const void* native_method) { diff --git a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc index dcf6bb84d2..1a5fe47e58 100644 --- a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc +++ b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc @@ -109,8 +109,6 @@ extern void CheckSuspendFromCode(Thread* thread); extern "C" void art_quick_test_suspend(); // Throw entrypoints. -extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* thread, - mirror::AbstractMethod** sp); extern "C" void art_quick_deliver_exception_from_code(void*); extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit); extern "C" void art_quick_throw_div_zero_from_code(); @@ -156,7 +154,6 @@ void InitEntryPoints(EntryPoints* points) { points->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code; // JNI - points->pFindNativeMethod = FindNativeMethod; points->pJniMethodStart = JniMethodStart; points->pJniMethodStartSynchronized = JniMethodStartSynchronized; points->pJniMethodEnd = JniMethodEnd; @@ -210,7 +207,6 @@ void InitEntryPoints(EntryPoints* points) { // Throws points->pDeliverException = art_quick_deliver_exception_from_code; - points->pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode; points->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code; points->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code; points->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code; diff --git a/src/oat/runtime/arm/runtime_support_arm.S b/src/oat/runtime/arm/runtime_support_arm.S index 2aa380bb73..3578ba0d16 100644 --- a/src/oat/runtime/arm/runtime_support_arm.S +++ b/src/oat/runtime/arm/runtime_support_arm.S @@ -257,6 +257,7 @@ ENTRY art_portable_resolution_trampoline .cfi_adjust_cfa_offset 20 sub sp, #12 @ pad stack pointer to align frame .pad #12 + .cfi_adjust_cfa_offset 12 mov r2, r9 @ pass Thread::Current mov r1, sp @ pass stack pointer blx artPortableResolutionTrampoline @ (method_idx, sp, Thread*) @@ -1067,6 +1068,49 @@ ENTRY art_quick_deoptimize END art_quick_deoptimize /* + * Portable abstract method error stub. r0 contains method* on entry. SP unused in portable. + */ + .extern artThrowAbstractMethodErrorFromCode +ENTRY art_portable_abstract_method_error_stub + mov r1, r9 @ pass Thread::Current + b artThrowAbstractMethodErrorFromCode @ (Method*, Thread*, SP) +END art_portable_abstract_method_error_stub + + /* + * Quick abstract method error stub. r0 contains method* on entry. + */ +ENTRY art_quick_abstract_method_error_stub + SETUP_SAVE_ALL_CALLEE_SAVE_FRAME + mov r1, r9 @ pass Thread::Current + mov r2, sp @ pass SP + b artThrowAbstractMethodErrorFromCode @ (Method*, Thread*, SP) +END art_quick_abstract_method_error_stub + + /* + * Jni dlsym lookup stub. + */ + .extern artFindNativeMethod +ENTRY art_jni_dlsym_lookup_stub + push {r0, r1, r2, r3, lr} @ spill regs + .save {r0, r1, r2, r3, lr} + .pad #20 + .cfi_adjust_cfa_offset 20 + sub sp, #12 @ pad stack pointer to align frame + .pad #12 + .cfi_adjust_cfa_offset 12 + mov r0, r9 @ pass Thread::Current + blx artFindNativeMethod @ (Thread*) + mov r12, r0 @ save result in r12 + add sp, #12 @ restore stack pointer + .cfi_adjust_cfa_offset -12 + pop {r0, r1, r2, r3, lr} @ restore regs + .cfi_adjust_cfa_offset -20 + cmp r12, #0 @ is method code null? + bxne r12 @ if non-null, tail call to method's code + bx lr @ otherwise, return to caller to handle exception +END art_jni_dlsym_lookup_stub + + /* * Signed 64-bit integer multiply. * * Consider WXxYZ (r1r0 x r3r2) with a long multiply: diff --git a/src/oat/runtime/arm/stub_arm.cc b/src/oat/runtime/arm/stub_arm.cc deleted file mode 100644 index 7c97f4ccb1..0000000000 --- a/src/oat/runtime/arm/stub_arm.cc +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2011 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 "jni_internal.h" -#include "mirror/array.h" -#include "mirror/object-inl.h" -#include "oat/utils/arm/assembler_arm.h" -#include "oat/runtime/oat_support_entrypoints.h" -#include "oat/runtime/stub.h" -#include "stack_indirect_reference_table.h" -#include "sirt_ref.h" - -#define __ assembler-> - -namespace art { -namespace arm { - -typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*); - -mirror::ByteArray* CreateAbstractMethodErrorStub() { - UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm))); -#if !defined(ART_USE_PORTABLE_COMPILER) - // Save callee saves and ready frame for exception delivery - RegList save = (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8) | (1 << R9) | - (1 << R10) | (1 << R11) | (1 << LR); - // TODO: enable when GetCalleeSaveMethod is available at stub generation time - // DCHECK_EQ(save, Runtime::Current()->GetCalleeSaveMethod(Runtime::kSaveAll)->GetCoreSpillMask()); - __ PushList(save); // push {r4-r11, lr} - 9 words of callee saves - // TODO: enable when GetCalleeSaveMethod is available at stub generation time - // DCHECK_EQ(Runtime::Current()->GetCalleeSaveMethod(Runtime::kSaveAll)->GetFpSpillMask(), 0xFFFFU); - __ Emit(0xed2d0a20); // vpush {s0-s31} - - __ IncreaseFrameSize(12); // 3 words of space, bottom word will hold callee save Method* - - // R0 is the Method* already - __ mov(R1, ShifterOperand(R9)); // Pass Thread::Current() in R1 - __ mov(R2, ShifterOperand(SP)); // Pass SP in R2 - // Call to throw AbstractMethodError - __ LoadFromOffset(kLoadWord, R12, TR, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode)); - __ mov(PC, ShifterOperand(R12)); // Leaf call to routine that never returns - - __ bkpt(0); -#else // ART_USE_PORTABLE_COMPILER - // R0 is the Method* already - __ mov(R1, ShifterOperand(R9)); // Pass Thread::Current() in R1 - // Call to throw AbstractMethodError - __ LoadFromOffset(kLoadWord, R12, TR, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode)); - __ mov(PC, ShifterOperand(R12)); // Leaf call to routine that never returns - - __ bkpt(0); -#endif // ART_USE_PORTABLE_COMPILER - - assembler->EmitSlowPaths(); - - size_t cs = assembler->CodeSize(); - Thread* self = Thread::Current(); - SirtRef<mirror::ByteArray> abstract_stub(self, mirror::ByteArray::Alloc(self, cs)); - CHECK(abstract_stub.get() != NULL); - MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength()); - assembler->FinalizeInstructions(code); - - return abstract_stub.get(); -} - -mirror::ByteArray* CreateJniDlsymLookupStub() { - UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm))); - // Build frame and save argument registers and LR. - RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR); - __ PushList(save); - __ AddConstant(SP, -12); // Ensure 16-byte alignment - __ mov(R0, ShifterOperand(R9)); // Pass Thread::Current() in R0 - // Call FindNativeMethod - __ LoadFromOffset(kLoadWord, R12, TR, ENTRYPOINT_OFFSET(pFindNativeMethod)); - __ blx(R12); - __ mov(R12, ShifterOperand(R0)); // Save result of FindNativeMethod in R12 - __ AddConstant(SP, 12); // Restore registers (including outgoing arguments) - __ PopList(save); - __ cmp(R12, ShifterOperand(0)); - __ bx(R12, NE); // If R12 != 0 tail call into native code - __ bx(LR); // Return to caller to handle exception - - assembler->EmitSlowPaths(); - - size_t cs = assembler->CodeSize(); - Thread* self = Thread::Current(); - SirtRef<mirror::ByteArray> jni_stub(self, mirror::ByteArray::Alloc(self, cs)); - CHECK(jni_stub.get() != NULL); - MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength()); - assembler->FinalizeInstructions(code); - - return jni_stub.get(); -} - -} // namespace arm -} // namespace art diff --git a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc index b201b07d17..eb82c42894 100644 --- a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc +++ b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc @@ -111,8 +111,6 @@ extern void CheckSuspendFromCode(Thread* thread); extern "C" void art_quick_test_suspend(); // Throw entrypoints. -extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* thread, - mirror::AbstractMethod** sp); extern "C" void art_quick_deliver_exception_from_code(void*); extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit); extern "C" void art_quick_throw_div_zero_from_code(); @@ -158,7 +156,6 @@ void InitEntryPoints(EntryPoints* points) { points->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code; // JNI - points->pFindNativeMethod = FindNativeMethod; points->pJniMethodStart = JniMethodStart; points->pJniMethodStartSynchronized = JniMethodStartSynchronized; points->pJniMethodEnd = JniMethodEnd; @@ -211,7 +208,6 @@ void InitEntryPoints(EntryPoints* points) { // Throws points->pDeliverException = art_quick_deliver_exception_from_code; - points->pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode; points->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code; points->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code; points->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code; diff --git a/src/oat/runtime/mips/runtime_support_mips.S b/src/oat/runtime/mips/runtime_support_mips.S index f5f8d9be7a..295e3fe086 100644 --- a/src/oat/runtime/mips/runtime_support_mips.S +++ b/src/oat/runtime/mips/runtime_support_mips.S @@ -408,10 +408,10 @@ INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvok INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck - /* + /* * Portable resolution trampoline. */ - .extern artPortableResolutionTrampoline + .extern artPortableResolutionTrampoline ENTRY art_portable_resolution_trampoline GENERATE_GLOBAL_POINTER addiu $sp, $sp, -32 # leave room for $a0, $a1, $a2, $a3, and $ra @@ -444,10 +444,10 @@ resolve_fail: nop END art_portable_resolution_trampoline - /* + /* * Quick resolution trampoline. */ - .extern artQuickResolutionTrampoline + .extern artQuickResolutionTrampoline ENTRY art_quick_resolution_trampoline GENERATE_GLOBAL_POINTER SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME @@ -482,8 +482,8 @@ END art_quick_resolution_trampoline * [sp + 16] = JValue* result * [sp + 20] = result type char */ - .type art_portable_invoke_stub, %function - .global art_portable_invoke_stub + .type art_portable_invoke_stub, %function + .global art_portable_invoke_stub art_portable_invoke_stub: ENTRY art_quick_invoke_stub GENERATE_GLOBAL_POINTER @@ -1102,6 +1102,64 @@ ENTRY art_quick_deoptimize END art_quick_deoptimize /* + * Portable abstract method error stub. $a0 contains method* on entry. SP unused in portable. + */ + .extern artThrowAbstractMethodErrorFromCode +ENTRY art_portable_abstract_method_error_stub + GENERATE_GLOBAL_POINTER + la $t9, artThrowAbstractMethodErrorFromCode + jr $t9 # (Method*, Thread*, SP) + move $a1, $s1 # pass Thread::Current +END art_portable_abstract_method_error_stub + + /* + * Quick abstract method error stub. $a0 contains method* on entry. + */ +ENTRY art_quick_abstract_method_error_stub + GENERATE_GLOBAL_POINTER + SETUP_SAVE_ALL_CALLEE_SAVE_FRAME + move $a1, $s1 # pass Thread::Current + la $t9, artThrowAbstractMethodErrorFromCode + jr $t9 # (Method*, Thread*, SP) + move $a2, $sp # pass SP +END art_quick_abstract_method_error_stub + + /* + * Jni dlsym lookup stub. + */ + .extern artFindNativeMethod +ENTRY art_jni_dlsym_lookup_stub + GENERATE_GLOBAL_POINTER + addiu $sp, $sp, -32 # leave room for $a0, $a1, $a2, $a3, and $ra + .cfi_adjust_cfa_offset 32 + sw $ra, 16($sp) + .cfi_rel_offset 31, 16 + sw $a3, 12($sp) + .cfi_rel_offset 7, 12 + sw $a2, 8($sp) + .cfi_rel_offset 6, 8 + sw $a1, 4($sp) + .cfi_rel_offset 5, 4 + sw $a0, 0($sp) + .cfi_rel_offset 4, 0 + jal artFindNativeMethod # (Thread*) + move $a0, $s1 # pass Thread::Current() + lw $a0, 0($sp) # restore registers from stack + lw $a1, 4($sp) + lw $a2, 8($sp) + lw $a3, 12($sp) + lw $ra, 16($sp) + beq $v0, $zero, no_native_code_found + addiu $sp, $sp, 32 # restore the stack + .cfi_adjust_cfa_offset -32 + jr $t9 # leaf call to method's code + move $t9, $v0 # put method code result in $t9 +no_native_code_found: + jr $ra + nop +END art_jni_dlsym_lookup_stub + + /* * Long integer shift. This is different from the generic 32/64-bit * binary operations because vAA/vBB are 64-bit but vCC (the shift * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low diff --git a/src/oat/runtime/mips/stub_mips.cc b/src/oat/runtime/mips/stub_mips.cc deleted file mode 100644 index a1adf6687c..0000000000 --- a/src/oat/runtime/mips/stub_mips.cc +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2011 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 "jni_internal.h" -#include "mirror/array.h" -#include "mirror/object-inl.h" -#include "oat/runtime/oat_support_entrypoints.h" -#include "oat/runtime/stub.h" -#include "oat/utils/mips/assembler_mips.h" -#include "stack_indirect_reference_table.h" -#include "sirt_ref.h" - -#define __ assembler-> - -namespace art { -namespace mips { - -typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*); - -mirror::ByteArray* CreateAbstractMethodErrorStub() { - UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips))); -#if !defined(ART_USE_PORTABLE_COMPILER) - // Save callee saves and ready frame for exception delivery - __ AddConstant(SP, SP, -64); - __ StoreToOffset(kStoreWord, RA, SP, 60); - __ StoreToOffset(kStoreWord, FP, SP, 56); - __ StoreToOffset(kStoreWord, S7, SP, 52); - __ StoreToOffset(kStoreWord, S6, SP, 48); - __ StoreToOffset(kStoreWord, S5, SP, 44); - __ StoreToOffset(kStoreWord, S4, SP, 40); - __ StoreToOffset(kStoreWord, S3, SP, 36); - __ StoreToOffset(kStoreWord, S2, SP, 32); - __ StoreToOffset(kStoreWord, S1, SP, 28); - __ StoreToOffset(kStoreWord, S0, SP, 24); - - // A0 is the Method* already - __ Move(A1, S1); // Pass Thread::Current() in A1 - __ Move(A2, SP); // Pass SP in A2 - // Call to throw AbstractMethodError - __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode)); - __ Jr(T9); // Leaf call to routine that never returns - - __ Break(); -#else // ART_USE_PORTABLE_COMPILER - // R0 is the Method* already - __ Move(A1, S1); // Pass Thread::Current() in A1 - // Call to throw AbstractMethodError - __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode)); - __ Jr(T9); // Leaf call to routine that never returns - - __ Break(); -#endif // ART_USE_PORTABLE_COMPILER - - assembler->EmitSlowPaths(); - - size_t cs = assembler->CodeSize(); - Thread* self = Thread::Current(); - SirtRef<mirror::ByteArray> abstract_stub(self, mirror::ByteArray::Alloc(self, cs)); - CHECK(abstract_stub.get() != NULL); - MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength()); - assembler->FinalizeInstructions(code); - - return abstract_stub.get(); -} - -mirror::ByteArray* CreateJniDlsymLookupStub() { - UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips))); - - // Build frame and save argument registers and RA. - __ AddConstant(SP, SP, -32); - __ StoreToOffset(kStoreWord, RA, SP, 28); - __ StoreToOffset(kStoreWord, A3, SP, 24); - __ StoreToOffset(kStoreWord, A2, SP, 20); - __ StoreToOffset(kStoreWord, A1, SP, 16); - __ StoreToOffset(kStoreWord, A0, SP, 12); - - __ Move(A0, S1); // Pass Thread::Current() in A0 - __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pFindNativeMethod)); - __ Jalr(T9); // Call FindNativeMethod - - // Restore frame, argument registers, and RA. - __ LoadFromOffset(kLoadWord, A0, SP, 12); - __ LoadFromOffset(kLoadWord, A1, SP, 16); - __ LoadFromOffset(kLoadWord, A2, SP, 20); - __ LoadFromOffset(kLoadWord, A3, SP, 24); - __ LoadFromOffset(kLoadWord, RA, SP, 28); - __ AddConstant(SP, SP, 32); - - Label no_native_code_found; - __ EmitBranch(V0, ZERO, &no_native_code_found, true); - __ Move(T9, V0); // Move result into T9 - __ Jr(T9); // If result != 0, tail call method's code - __ Bind(&no_native_code_found, false); - __ Jr(RA); // Return to caller to handle exception - - assembler->EmitSlowPaths(); - - size_t cs = assembler->CodeSize(); - Thread* self = Thread::Current(); - SirtRef<mirror::ByteArray> jni_stub(self, mirror::ByteArray::Alloc(self, cs)); - CHECK(jni_stub.get() != NULL); - MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength()); - assembler->FinalizeInstructions(code); - - return jni_stub.get(); -} - -} // namespace mips -} // namespace art diff --git a/src/oat/runtime/oat_support_entrypoints.h b/src/oat/runtime/oat_support_entrypoints.h index 5be1e4908e..72d5348556 100644 --- a/src/oat/runtime/oat_support_entrypoints.h +++ b/src/oat/runtime/oat_support_entrypoints.h @@ -70,7 +70,6 @@ struct PACKED(4) EntryPoints { void (*pHandleFillArrayDataFromCode)(void*, void*); // JNI - void* (*pFindNativeMethod)(Thread* thread); uint32_t (*pJniMethodStart)(Thread*); uint32_t (*pJniMethodStartSynchronized)(jobject to_lock, Thread* self); void (*pJniMethodEnd)(uint32_t cookie, Thread* self); @@ -125,8 +124,6 @@ struct PACKED(4) EntryPoints { // Throws void (*pDeliverException)(void*); - void (*pThrowAbstractMethodErrorFromCode)(mirror::AbstractMethod* m, Thread* thread, - mirror::AbstractMethod** sp); void (*pThrowArrayBoundsFromCode)(int32_t, int32_t); void (*pThrowDivZeroFromCode)(); void (*pThrowNoSuchMethodFromCode)(int32_t); @@ -135,7 +132,6 @@ struct PACKED(4) EntryPoints { }; // JNI entrypoints. -extern void* FindNativeMethod(Thread* thread) LOCKS_EXCLUDED(Locks::mutator_lock_); extern uint32_t JniMethodStart(Thread* self) UNLOCK_FUNCTION(Locks::mutator_lock_) __attribute__ ((hot)); extern uint32_t JniMethodStartSynchronized(jobject to_lock, Thread* self) diff --git a/src/oat/runtime/stub.h b/src/oat/runtime/stub.h deleted file mode 100644 index ee39273785..0000000000 --- a/src/oat/runtime/stub.h +++ /dev/null @@ -1,51 +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. - */ - -#ifndef ART_SRC_OAT_RUNTIME_OAT_RUNTIME_STUB_H_ -#define ART_SRC_OAT_RUNTIME_OAT_RUNTIME_STUB_H_ - -#include "runtime.h" - -namespace art { -namespace mirror { -template<class T> class PrimitiveArray; -typedef PrimitiveArray<int8_t> ByteArray; -} // namespace mirror - -namespace arm { - mirror::ByteArray* CreateAbstractMethodErrorStub() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::ByteArray* CreateJniDlsymLookupStub() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -} - -namespace mips { - mirror::ByteArray* CreateAbstractMethodErrorStub() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::ByteArray* CreateJniDlsymLookupStub() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -} - -namespace x86 { - mirror::ByteArray* CreateAbstractMethodErrorStub() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::ByteArray* CreateJniDlsymLookupStub() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -} - -} // namespace art - -#endif // ART_SRC_OAT_RUNTIME_OAT_RUNTIME_STUB_H_ diff --git a/src/oat/runtime/support_jni.cc b/src/oat/runtime/support_jni.cc index bc9cc45c04..8f0f7ca93d 100644 --- a/src/oat/runtime/support_jni.cc +++ b/src/oat/runtime/support_jni.cc @@ -27,28 +27,6 @@ namespace art { -// Used by the JNI dlsym stub to find the native method to invoke if none is registered. -extern void* FindNativeMethod(Thread* self) { - Locks::mutator_lock_->AssertNotHeld(self); // We come here as Native. - DCHECK(Thread::Current() == self); - ScopedObjectAccess soa(self); - - mirror::AbstractMethod* method = self->GetCurrentMethod(NULL); - DCHECK(method != NULL); - - // Lookup symbol address for method, on failure we'll return NULL with an - // exception set, otherwise we return the address of the method we found. - void* native_code = soa.Vm()->FindCodeForNativeMethod(method); - if (native_code == NULL) { - DCHECK(self->IsExceptionPending()); - return NULL; - } else { - // Register so that future calls don't come here - method->RegisterNative(self, native_code); - return native_code; - } -} - // Called on entry to JNI, transition out of Runnable and release share of mutator_lock_. extern uint32_t JniMethodStart(Thread* self) { JNIEnvExt* env = self->GetJniEnv(); @@ -184,7 +162,7 @@ extern "C" const void* artWorkAroundAppJniBugs(Thread* self, intptr_t* sp) // Load expected destination, see Method::RegisterNative const void* code = reinterpret_cast<const void*>(jni_method->GetNativeGcMap()); if (UNLIKELY(code == NULL)) { - code = Runtime::Current()->GetJniDlsymLookupStub()->GetData(); + code = GetJniDlsymLookupStub(); jni_method->RegisterNative(self, code); } return code; diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc index f78cc79f1b..9f77ae0429 100644 --- a/src/oat/runtime/support_stubs.cc +++ b/src/oat/runtime/support_stubs.cc @@ -335,9 +335,9 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* call return code; } -// Called by the AbstractMethodError. Called by stub code. -extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* self, - mirror::AbstractMethod** sp) +// Called by the abstract method error stub. +extern "C" void artThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* self, + mirror::AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if !defined(ART_USE_PORTABLE_COMPILER) FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll); @@ -350,4 +350,26 @@ extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thr self->QuickDeliverException(); } +// Used by the JNI dlsym stub to find the native method to invoke if none is registered. +extern "C" void* artFindNativeMethod(Thread* self) { + Locks::mutator_lock_->AssertNotHeld(self); // We come here as Native. + DCHECK(Thread::Current() == self); + ScopedObjectAccess soa(self); + + mirror::AbstractMethod* method = self->GetCurrentMethod(NULL); + DCHECK(method != NULL); + + // Lookup symbol address for method, on failure we'll return NULL with an + // exception set, otherwise we return the address of the method we found. + void* native_code = soa.Vm()->FindCodeForNativeMethod(method); + if (native_code == NULL) { + DCHECK(self->IsExceptionPending()); + return NULL; + } else { + // Register so that future calls don't come here + method->RegisterNative(self, native_code); + return native_code; + } +} + } // namespace art diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc index 2e35d78503..357bbe0819 100644 --- a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc +++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc @@ -94,8 +94,6 @@ extern void CheckSuspendFromCode(Thread* thread); extern "C" void art_quick_test_suspend(); // Throw entrypoints. -extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* thread, - mirror::AbstractMethod** sp); extern "C" void art_quick_deliver_exception_from_code(void*); extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit); extern "C" void art_quick_throw_div_zero_from_code(); @@ -141,7 +139,6 @@ void InitEntryPoints(EntryPoints* points) { points->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code; // JNI - points->pFindNativeMethod = FindNativeMethod; points->pJniMethodStart = JniMethodStart; points->pJniMethodStartSynchronized = JniMethodStartSynchronized; points->pJniMethodEnd = JniMethodEnd; @@ -194,7 +191,6 @@ void InitEntryPoints(EntryPoints* points) { // Throws points->pDeliverException = art_quick_deliver_exception_from_code; - points->pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode; points->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code; points->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code; points->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code; diff --git a/src/oat/runtime/x86/runtime_support_x86.S b/src/oat/runtime/x86/runtime_support_x86.S index 22330c9336..d3a1fb73ff 100644 --- a/src/oat/runtime/x86/runtime_support_x86.S +++ b/src/oat/runtime/x86/runtime_support_x86.S @@ -307,6 +307,7 @@ INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvo DEFINE_FUNCTION art_portable_resolution_trampoline PUSH ebp // stash %ebp movl %esp, %ebp // save %esp + .cfi_def_cfa_register ebp subl LITERAL(8), %esp // align stack movl 8(%ebp), %eax // load the called method* into %eax leal 8(%ebp), %edx // put the called method* address in %edx @@ -314,7 +315,9 @@ DEFINE_FUNCTION art_portable_resolution_trampoline PUSH edx // pass called method* address PUSH eax // pass method* call SYMBOL(artPortableResolutionTrampoline) // (method_idx, sp, Thread*) - leave // restore the stack + leave // restore the stack and %ebp + .cfi_def_cfa esp, 4 + .cfi_restore ebp cmpl LITERAL(0), %eax // check if returned method code is null je resolve_fail // if null, jump to return to handle jmp *%eax // otherwise, tail call to intended method @@ -330,11 +333,13 @@ DEFINE_FUNCTION art_quick_resolution_trampoline movl %esp, %ecx // save stack pointer PUSH eax // align stack pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + .cfi_adjust_cfa_offset 4 PUSH ecx // pass stack pointer PUSH eax // pass method* call SYMBOL(artQuickResolutionTrampoline) // (method_idx, sp, Thread*) movl %eax, %edi // save returned code pointer in %edi addl LITERAL(16), %esp // pop arguments + .cfi_adjust_cfa_offset -16 POP eax // restore registers POP ecx POP edx @@ -1098,6 +1103,57 @@ DEFINE_FUNCTION art_quick_deoptimize END_FUNCTION art_quick_deoptimize /* + * Portable abstract method error stub. method* is at %esp + 4 on entry. + */ +DEFINE_FUNCTION art_portable_abstract_method_error_stub + PUSH ebp + movl %esp, %ebp // Remember SP. + .cfi_def_cfa_register ebp + subl LITERAL(12), %esp // Align stack. + PUSH esp // Pass sp (not used). + pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). + pushl 8(%ebp) // Pass Method*. + call SYMBOL(artThrowAbstractMethodErrorFromCode) // (Method*, Thread*, SP) + leave // Restore the stack and %ebp. + .cfi_def_cfa esp, 4 + .cfi_restore ebp + ret // Return to caller to handle pending exception. +END_FUNCTION art_portable_abstract_method_error_stub + + /* + * Quick abstract method error stub. %eax contains method* on entry. + */ +DEFINE_FUNCTION art_quick_abstract_method_error_stub + SETUP_SAVE_ALL_CALLEE_SAVE_FRAME + movl %esp, %ecx // Remember SP. + PUSH eax // Align frame. + PUSH ecx // Pass SP for Method*. + pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). + .cfi_adjust_cfa_offset 4 + PUSH eax // Pass Method*. + call SYMBOL(artThrowAbstractMethodErrorFromCode) // (Method*, Thread*, SP) + int3 // Unreachable. +END_FUNCTION art_quick_abstract_method_error_stub + + /* + * Portable resolution trampoline. + */ +DEFINE_FUNCTION art_jni_dlsym_lookup_stub + subl LITERAL(8), %esp // align stack + .cfi_adjust_cfa_offset 8 + pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() + .cfi_adjust_cfa_offset 4 + call SYMBOL(artFindNativeMethod) // (Thread*) + addl LITERAL(12), %esp // restore the stack + .cfi_adjust_cfa_offset -12 + cmpl LITERAL(0), %eax // check if returned method code is null + je no_native_code_found // if null, jump to return to handle + jmp *%eax // otherwise, tail call to intended method +no_native_code_found: + ret +END_FUNCTION art_jni_dlsym_lookup_stub + + /* * String's indexOf. * * On entry: diff --git a/src/oat/runtime/x86/stub_x86.cc b/src/oat/runtime/x86/stub_x86.cc deleted file mode 100644 index 3f85b2886f..0000000000 --- a/src/oat/runtime/x86/stub_x86.cc +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2011 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 "jni_internal.h" -#include "mirror/array.h" -#include "mirror/object-inl.h" -#include "oat/runtime/oat_support_entrypoints.h" -#include "oat/runtime/stub.h" -#include "oat/utils/x86/assembler_x86.h" -#include "stack_indirect_reference_table.h" -#include "sirt_ref.h" - -#define __ assembler-> - -namespace art { -namespace x86 { - -typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*); - -mirror::ByteArray* CreateAbstractMethodErrorStub() { - UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86))); - -#if !defined(ART_USE_PORTABLE_COMPILER) - // Set up the callee save frame to conform with Runtime::CreateCalleeSaveMethod(kSaveAll) - - // return address - __ pushl(EDI); - __ pushl(ESI); - __ pushl(EBP); - __ pushl(Immediate(0)); - __ pushl(Immediate(0)); - __ pushl(Immediate(0)); - __ pushl(Immediate(0)); // <-- callee save Method* to go here - __ movl(ECX, ESP); // save ESP - __ pushl(Immediate(0)); // align frame - __ pushl(ECX); // pass ESP for Method* - __ fs()->pushl(Address::Absolute(Thread::SelfOffset())); // Thread* - __ pushl(EAX); // pass Method* - - // Call to throw AbstractMethodError. - __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode)), - X86ManagedRegister::FromCpuRegister(ECX)); - - // Call never returns. - __ int3(); -#else // ART_USE_PORTABLE_COMPILER - __ pushl(EBP); - __ movl(EBP, ESP); // save ESP - __ subl(ESP, Immediate(12)); // Align stack - __ pushl(ESP); // pass sp (not use) - __ fs()->pushl(Address::Absolute(Thread::SelfOffset())); // pass thread* - __ pushl(Address(EBP, 8)); // pass method - // Call to throw AbstractMethodError. - __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode)), - X86ManagedRegister::FromCpuRegister(ECX)); - __ leave(); - // Return to caller who will handle pending exception. - __ ret(); -#endif // ART_USE_PORTABLE_COMPILER - - assembler->EmitSlowPaths(); - - size_t cs = assembler->CodeSize(); - Thread* self = Thread::Current(); - SirtRef<mirror::ByteArray> abstract_stub(self, mirror::ByteArray::Alloc(self, cs)); - CHECK(abstract_stub.get() != NULL); - MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength()); - assembler->FinalizeInstructions(code); - - return abstract_stub.get(); -} - -mirror::ByteArray* CreateJniDlsymLookupStub() { - UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86))); - - // Pad stack to ensure 16-byte alignment - __ pushl(Immediate(0)); - __ pushl(Immediate(0)); - __ fs()->pushl(Address::Absolute(Thread::SelfOffset())); // Thread* - - __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pFindNativeMethod)), - X86ManagedRegister::FromCpuRegister(ECX)); - - __ addl(ESP, Immediate(12)); - - Label no_native_code_found; // forward declaration - __ cmpl(EAX, Immediate(0)); - __ j(kEqual, &no_native_code_found); - - __ jmp(EAX); // Tail call into native code - - __ Bind(&no_native_code_found); - __ ret(); // return to caller to handle exception - - assembler->EmitSlowPaths(); - - size_t cs = assembler->CodeSize(); - Thread* self = Thread::Current(); - SirtRef<mirror::ByteArray> jni_stub(self, mirror::ByteArray::Alloc(self, cs)); - CHECK(jni_stub.get() != NULL); - MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength()); - assembler->FinalizeInstructions(code); - - return jni_stub.get(); -} - -} // namespace x86 -} // namespace art diff --git a/src/oatdump.cc b/src/oatdump.cc index 62af7a99a6..353abcaf03 100644 --- a/src/oatdump.cc +++ b/src/oatdump.cc @@ -82,8 +82,6 @@ static void usage() { } const char* image_roots_descriptions_[] = { - "kJniStubArray", - "kAbstractMethodErrorStubArray", "kResolutionMethod", "kCalleeSaveMethod", "kRefsOnlySaveMethod", diff --git a/src/runtime.cc b/src/runtime.cc index b33615622f..25d26b8005 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -82,8 +82,6 @@ Runtime::Runtime() signal_catcher_(NULL), java_vm_(NULL), pre_allocated_OutOfMemoryError_(NULL), - jni_stub_array_(NULL), - abstract_method_error_stub_array_(NULL), resolution_method_(NULL), system_class_loader_(NULL), threads_being_born_(0), @@ -1065,8 +1063,6 @@ void Runtime::VisitNonThreadRoots(RootVisitor* visitor, void* arg) { if (pre_allocated_OutOfMemoryError_ != NULL) { visitor(pre_allocated_OutOfMemoryError_, arg); } - visitor(jni_stub_array_, arg); - visitor(abstract_method_error_stub_array_, arg); visitor(resolution_method_, arg); for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { visitor(callee_save_methods_[i], arg); @@ -1090,19 +1086,6 @@ void Runtime::VisitRoots(RootVisitor* visitor, void* arg) { VisitNonConcurrentRoots(visitor, arg); } -void Runtime::SetJniDlsymLookupStub(mirror::ByteArray* jni_stub_array) { - CHECK(jni_stub_array != NULL) << " jni_stub_array=" << jni_stub_array; - CHECK(jni_stub_array_ == NULL || jni_stub_array_ == jni_stub_array) - << "jni_stub_array_=" << jni_stub_array_ << " jni_stub_array=" << jni_stub_array; - jni_stub_array_ = jni_stub_array; -} - -void Runtime::SetAbstractMethodErrorStubArray(mirror::ByteArray* abstract_method_error_stub_array) { - CHECK(abstract_method_error_stub_array != NULL); - CHECK(abstract_method_error_stub_array_ == NULL || abstract_method_error_stub_array_ == abstract_method_error_stub_array); - abstract_method_error_stub_array_ = abstract_method_error_stub_array; -} - mirror::AbstractMethod* Runtime::CreateResolutionMethod() { mirror::Class* method_class = mirror::AbstractMethod::GetMethodClass(); Thread* self = Thread::Current(); diff --git a/src/runtime.h b/src/runtime.h index 93cffbe56e..c7ccda1877 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -242,28 +242,6 @@ class Runtime { void VisitNonConcurrentRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool HasJniDlsymLookupStub() const { - return jni_stub_array_ != NULL; - } - - mirror::ByteArray* GetJniDlsymLookupStub() const { - CHECK(HasJniDlsymLookupStub()); - return jni_stub_array_; - } - - void SetJniDlsymLookupStub(mirror::ByteArray* jni_stub_array); - - bool HasAbstractMethodErrorStubArray() const { - return abstract_method_error_stub_array_ != NULL; - } - - mirror::ByteArray* GetAbstractMethodErrorStubArray() const { - CHECK(abstract_method_error_stub_array_ != NULL); - return abstract_method_error_stub_array_; - } - - void SetAbstractMethodErrorStubArray(mirror::ByteArray* abstract_method_error_stub_array); - // Returns a special method that calls into a trampoline for runtime method resolution mirror::AbstractMethod* GetResolutionMethod() const { CHECK(HasResolutionMethod()); @@ -397,10 +375,6 @@ class Runtime { mirror::Throwable* pre_allocated_OutOfMemoryError_; - mirror::ByteArray* jni_stub_array_; - - mirror::ByteArray* abstract_method_error_stub_array_; - mirror::AbstractMethod* callee_save_methods_[kLastCalleeSaveType]; mirror::AbstractMethod* resolution_method_; diff --git a/src/runtime_support.h b/src/runtime_support.h index 2bab3238fd..1c39214ff3 100644 --- a/src/runtime_support.h +++ b/src/runtime_support.h @@ -31,8 +31,11 @@ #include "thread.h" extern "C" void art_interpreter_invoke_handler(); +extern "C" void art_jni_dlsym_lookup_stub(); +extern "C" void art_portable_abstract_method_error_stub(); extern "C" void art_portable_proxy_invoke_handler(); extern "C" void art_portable_resolution_trampoline(); +extern "C" void art_quick_abstract_method_error_stub(); extern "C" void art_quick_deoptimize(); extern "C" void art_quick_instrumentation_entry_from_code(void*); extern "C" void art_quick_instrumentation_exit_from_code(); @@ -356,9 +359,29 @@ static inline void* GetResolutionTrampoline() { #else return GetQuickResolutionTrampoline(); #endif +} -} // namespace art +static inline void* GetPortableAbstractMethodErrorStub() { + return reinterpret_cast<void*>(art_portable_abstract_method_error_stub); +} + +static inline void* GetQuickAbstractMethodErrorStub() { + return reinterpret_cast<void*>(art_quick_abstract_method_error_stub); +} + +// Return address of abstract method error stub for defined compiler. +static inline void* GetAbstractMethodErrorStub() { +#if defined(ART_USE_PORTABLE_COMPILER) + return GetPortableAbstractMethodErrorStub(); +#else + return GetQuickAbstractMethodErrorStub(); +#endif +} +static inline void* GetJniDlsymLookupStub() { + return reinterpret_cast<void*>(art_jni_dlsym_lookup_stub); } +} // namespace art + #endif // ART_SRC_RUNTIME_SUPPORT_H_ diff --git a/src/thread.cc b/src/thread.cc index 70217710bf..84870780a3 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -1613,7 +1613,6 @@ static const EntryPointInfo gThreadEntryPointInfo[] = { ENTRY_POINT_INFO(pGetObjInstance), ENTRY_POINT_INFO(pGetObjStatic), ENTRY_POINT_INFO(pHandleFillArrayDataFromCode), - ENTRY_POINT_INFO(pFindNativeMethod), ENTRY_POINT_INFO(pJniMethodStart), ENTRY_POINT_INFO(pJniMethodStartSynchronized), ENTRY_POINT_INFO(pJniMethodEnd), @@ -1655,7 +1654,6 @@ static const EntryPointInfo gThreadEntryPointInfo[] = { ENTRY_POINT_INFO(pCheckSuspendFromCode), ENTRY_POINT_INFO(pTestSuspendFromCode), ENTRY_POINT_INFO(pDeliverException), - ENTRY_POINT_INFO(pThrowAbstractMethodErrorFromCode), ENTRY_POINT_INFO(pThrowArrayBoundsFromCode), ENTRY_POINT_INFO(pThrowDivZeroFromCode), ENTRY_POINT_INFO(pThrowNoSuchMethodFromCode), |