diff options
| -rw-r--r-- | src/assembler_arm.cc | 17 | ||||
| -rw-r--r-- | src/assembler_arm.h | 4 | ||||
| -rw-r--r-- | src/assembler_x86.cc | 15 | ||||
| -rw-r--r-- | src/assembler_x86.h | 4 | ||||
| -rw-r--r-- | src/calling_convention.cc | 16 | ||||
| -rw-r--r-- | src/calling_convention.h | 4 | ||||
| -rw-r--r-- | src/calling_convention_arm.cc | 4 | ||||
| -rw-r--r-- | src/jni_compiler.cc | 85 | ||||
| -rw-r--r-- | src/jni_compiler.h | 4 | ||||
| -rw-r--r-- | src/thread.h | 3 |
10 files changed, 114 insertions, 42 deletions
diff --git a/src/assembler_arm.cc b/src/assembler_arm.cc index e613307cf9..472d0005bf 100644 --- a/src/assembler_arm.cc +++ b/src/assembler_arm.cc @@ -1694,6 +1694,23 @@ void Assembler::Call(FrameOffset base, Offset offset, // TODO: place reference map on call } +void Assembler::Call(uintptr_t addr, + ManagedRegister scratch) { + CHECK(scratch.IsCoreRegister()); + CHECK(sizeof(uintptr_t) == sizeof(int32_t)); + LoadImmediate(scratch.AsCoreRegister(), static_cast<int32_t>(addr)); + blx(scratch.AsCoreRegister()); + // TODO: place reference map on call +} + +void Assembler::GetCurrentThread(ManagedRegister tr) { + mov(tr.AsCoreRegister(), ShifterOperand(TR)); +} + +void Assembler::GetCurrentThread(FrameOffset offset, ManagedRegister scratch) { + StoreToOffset(kStoreWord, TR, SP, offset.Int32Value(), AL); +} + void Assembler::SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg, FrameOffset return_save_location, size_t return_size) { diff --git a/src/assembler_arm.h b/src/assembler_arm.h index c35934e10a..af3ce40bd7 100644 --- a/src/assembler_arm.h +++ b/src/assembler_arm.h @@ -471,6 +471,10 @@ class Assembler { void Call(ManagedRegister base, Offset offset, ManagedRegister scratch); void Call(FrameOffset base, Offset offset, ManagedRegister scratch); + void Call(uintptr_t addr, ManagedRegister scratch); + + void GetCurrentThread(ManagedRegister tr); + void GetCurrentThread(FrameOffset offset, ManagedRegister scratch); // Generate code to check if Thread::Current()->suspend_count_ is non-zero // and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue diff --git a/src/assembler_x86.cc b/src/assembler_x86.cc index dc04f87a65..59fd33e95b 100644 --- a/src/assembler_x86.cc +++ b/src/assembler_x86.cc @@ -1619,6 +1619,21 @@ void Assembler::Call(FrameOffset base, Offset offset, UNIMPLEMENTED(FATAL); } +void Assembler::Call(uintptr_t addr, + ManagedRegister scratch) { + leal(scratch.AsCpuRegister(), Address::Absolute(addr)); + call(scratch.AsCpuRegister()); +} + +void Assembler::GetCurrentThread(ManagedRegister tr) { + fs()->movl(tr.AsCpuRegister(), Address::Absolute(Thread::SelfOffset())); +} + +void Assembler::GetCurrentThread(FrameOffset offset, ManagedRegister scratch) { + fs()->movl(scratch.AsCpuRegister(), Address::Absolute(Thread::SelfOffset())); + movl(Address(ESP, offset), scratch.AsCpuRegister()); +} + void Assembler::SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg, FrameOffset return_save_location, size_t return_size) { diff --git a/src/assembler_x86.h b/src/assembler_x86.h index d26d33f9ce..1b882e0002 100644 --- a/src/assembler_x86.h +++ b/src/assembler_x86.h @@ -482,6 +482,10 @@ class Assembler { void Call(ManagedRegister base, Offset offset, ManagedRegister scratch); void Call(FrameOffset base, Offset offset, ManagedRegister scratch); + void Call(uintptr_t addr, ManagedRegister scratch); + + void GetCurrentThread(ManagedRegister tr); + void GetCurrentThread(FrameOffset offset, ManagedRegister scratch); // Generate code to check if Thread::Current()->suspend_count_ is non-zero // and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue diff --git a/src/calling_convention.cc b/src/calling_convention.cc index 12dab2e8a8..83f7a00712 100644 --- a/src/calling_convention.cc +++ b/src/calling_convention.cc @@ -29,6 +29,9 @@ void ManagedRuntimeCallingConvention::Next() { itr_longs_and_doubles_++; itr_slots_++; } + if (IsCurrentParamAReference()) { + itr_refs_++; + } itr_args_++; itr_slots_++; } @@ -84,6 +87,9 @@ void JniCallingConvention::Next() { itr_slots_++; } } + if (IsCurrentParamAReference()) { + itr_refs_++; + } itr_args_++; itr_slots_++; } @@ -108,15 +114,7 @@ FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() { CHECK_GT(SirtLinkOffset(), SirtNumRefsOffset()); // Address of 1st SIRT entry int result = SirtLinkOffset().Int32Value() + kPointerSize; - if (itr_args_ != kObjectOrClass) { - const Method *method = GetMethod(); - int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(method); - int previous_refs = GetMethod()->NumReferenceArgsBefore(arg_pos); - if (method->IsStatic()) { - previous_refs++; // account for jclass - } - result += previous_refs * kPointerSize; - } + result += itr_refs_ * kPointerSize; CHECK_GT(result, SirtLinkOffset().Int32Value()); return FrameOffset(result); } diff --git a/src/calling_convention.h b/src/calling_convention.h index 1385337824..44ce93f5ad 100644 --- a/src/calling_convention.h +++ b/src/calling_convention.h @@ -26,6 +26,8 @@ class CallingConvention { // Register reserved for scratch usage during procedure calls ManagedRegister InterproceduralScratchRegister(); + ManagedRegister ThreadRegister(); + // Offset of Method within the frame FrameOffset MethodStackOffset(); @@ -38,6 +40,7 @@ class CallingConvention { displacement_ = displacement; itr_slots_ = 0; itr_args_ = 0; + itr_refs_ = 0; itr_longs_and_doubles_ = 0; } @@ -49,6 +52,7 @@ class CallingConvention { // The slot number for current calling_convention argument. // Note that each slot is 32-bit. When the current argument is bigger // than 32 bits, return the first slot number for this argument. + unsigned int itr_refs_; unsigned int itr_slots_; // The argument number along argument list for current argument unsigned int itr_args_; diff --git a/src/calling_convention_arm.cc b/src/calling_convention_arm.cc index 00720debf3..9c7ba6f343 100644 --- a/src/calling_convention_arm.cc +++ b/src/calling_convention_arm.cc @@ -9,6 +9,10 @@ ManagedRegister CallingConvention::MethodRegister() { return ManagedRegister::FromCoreRegister(R0); } +ManagedRegister CallingConvention::ThreadRegister() { + return ManagedRegister::FromCoreRegister(TR); +} + ManagedRegister CallingConvention::InterproceduralScratchRegister() { return ManagedRegister::FromCoreRegister(R12); } diff --git a/src/jni_compiler.cc b/src/jni_compiler.cc index 238b9ef350..1789e1bd47 100644 --- a/src/jni_compiler.cc +++ b/src/jni_compiler.cc @@ -16,6 +16,10 @@ namespace art { +static Object* DecodeJObjectInThread(Thread* thread, jobject obj) { + return thread->DecodeJObject(obj); +} + // Generate the JNI bridge for the given method, general contract: // - Arguments are in the managed runtime format, either on stack or in // registers, a reference to the method object is supplied as part of this @@ -128,21 +132,14 @@ void JniCompiler::Compile(Assembler* jni_asm, Method* native_method) { } else { CopyParameter(jni_asm, &mr_conv, &jni_conv, frame_size, out_arg_size); } - // Generate JNIEnv* in place and leave a copy in jni_env_register + // Generate JNIEnv* in place and leave a copy in jni_fns_register jni_conv.ResetIterator(FrameOffset(out_arg_size)); - ManagedRegister jni_env_register = + ManagedRegister jni_fns_register = jni_conv.InterproceduralScratchRegister(); - if (jni_conv.IsCurrentParamInRegister()) { - jni_env_register = jni_conv.CurrentParamRegister(); - } - jni_asm->LoadRawPtrFromThread(jni_env_register, Thread::JniEnvOffset()); - if (!jni_conv.IsCurrentParamInRegister()) { - FrameOffset out_off = jni_conv.CurrentParamStackOffset(); - jni_asm->StoreRawPtr(out_off, jni_env_register); - } + jni_asm->LoadRawPtrFromThread(jni_fns_register, Thread::JniEnvOffset()); + SetNativeParameter(jni_asm, &jni_conv, jni_fns_register); // Call JNIEnv->MonitorEnter(object) - ManagedRegister jni_fns_register = jni_conv.InterproceduralScratchRegister(); - jni_asm->LoadRawPtr(jni_fns_register, jni_env_register, functions); + jni_asm->LoadRawPtr(jni_fns_register, jni_fns_register, functions); jni_asm->Call(jni_fns_register, monitor_enter, jni_conv.InterproceduralScratchRegister()); jni_asm->FillFromSpillArea(spill_regs, out_arg_size); @@ -247,30 +244,23 @@ void JniCompiler::Compile(Assembler* jni_asm, Method* native_method) { jni_conv.ResetIterator(FrameOffset(out_arg_size)); ManagedRegister jni_env_register = jni_conv.InterproceduralScratchRegister(); - if (jni_conv.IsCurrentParamInRegister()) { - jni_env_register = jni_conv.CurrentParamRegister(); - } jni_asm->LoadRawPtrFromThread(jni_env_register, Thread::JniEnvOffset()); - if (!jni_conv.IsCurrentParamInRegister()) { - FrameOffset out_off = jni_conv.CurrentParamStackOffset(); - jni_asm->StoreRawPtr(out_off, jni_env_register); - } + SetNativeParameter(jni_asm, &jni_conv, jni_env_register); // Call JNIEnv->MonitorExit(object) - ManagedRegister jni_fns_register = jni_conv.InterproceduralScratchRegister(); - jni_asm->LoadRawPtr(jni_fns_register, jni_env_register, functions); - jni_asm->Call(jni_fns_register, monitor_exit, + jni_asm->LoadRawPtr(jni_env_register, jni_env_register, functions); + jni_asm->Call(jni_env_register, monitor_exit, jni_conv.InterproceduralScratchRegister()); // Reload return value jni_asm->Load(jni_conv.ReturnRegister(), return_save_location, jni_conv.SizeOfReturnValue()); } - // 11. Release outgoing argument area + // 12. Release outgoing argument area jni_asm->DecreaseFrameSize(out_arg_size); mr_conv.ResetIterator(FrameOffset(frame_size)); jni_conv.ResetIterator(FrameOffset(0)); - // 12. Transition from being in native to managed code, possibly entering a + // 13. Transition from being in native to managed code, possibly entering a // safepoint CHECK(!jni_conv.InterproceduralScratchRegister() .Equals(jni_conv.ReturnRegister())); // don't clobber result @@ -285,24 +275,40 @@ void JniCompiler::Compile(Assembler* jni_asm, Method* native_method) { jni_conv.InterproceduralScratchRegister()); - // 15. Place result in correct register possibly loading from indirect + // 14. Place result in correct register possibly loading from indirect // reference table if (jni_conv.IsReturnAReference()) { - // TODO: load from local/global reference tables - jni_asm->LoadReferenceFromSirt(mr_conv.ReturnRegister(), - jni_conv.ReturnRegister()); - } else { - jni_asm->Move(mr_conv.ReturnRegister(), jni_conv.ReturnRegister()); + jni_asm->IncreaseFrameSize(kStackAlignment); + jni_conv.ResetIterator(FrameOffset(kStackAlignment)); + + jni_conv.Next(); + SetNativeParameter(jni_asm, &jni_conv, jni_conv.ReturnRegister()); + + jni_conv.ResetIterator(FrameOffset(kStackAlignment)); + + if (jni_conv.IsCurrentParamInRegister()) { + jni_asm->GetCurrentThread(jni_conv.CurrentParamRegister()); + } else { + jni_asm->GetCurrentThread(jni_conv.CurrentParamStackOffset(), + jni_conv.InterproceduralScratchRegister()); + } + + jni_asm->Call(reinterpret_cast<uintptr_t>(DecodeJObjectInThread), + jni_conv.InterproceduralScratchRegister()); + + jni_asm->DecreaseFrameSize(kStackAlignment); + jni_conv.ResetIterator(FrameOffset(0)); } + jni_asm->Move(mr_conv.ReturnRegister(), jni_conv.ReturnRegister()); - // 16. Remove SIRT from thread + // 15. Remove SIRT from thread jni_asm->CopyRawPtrToThread(Thread::TopSirtOffset(), jni_conv.SirtLinkOffset(), jni_conv.InterproceduralScratchRegister()); - // 17. Remove activation + // 16. Remove activation jni_asm->RemoveFrame(frame_size, spill_regs); - // 18. Finalize code generation + // 17. Finalize code generation jni_asm->EmitSlowPaths(); size_t cs = jni_asm->CodeSize(); MemoryRegion code(AllocateCode(cs), cs); @@ -313,6 +319,19 @@ void JniCompiler::Compile(Assembler* jni_asm, Method* native_method) { native_method->SetReturnPcOffsetInBytes(jni_conv.ReturnPcOffset()); } +void JniCompiler::SetNativeParameter(Assembler *jni_asm, + JniCallingConvention *jni_conv, + ManagedRegister in_reg) { + if (jni_conv->IsCurrentParamOnStack()) { + FrameOffset dest = jni_conv->CurrentParamStackOffset(); + jni_asm->StoreRawPtr(dest, in_reg); + } else { + if (!jni_conv->CurrentParamRegister().Equals(in_reg)) { + jni_asm->Move(jni_conv->CurrentParamRegister(), in_reg); + } + } +} + // Copy a single parameter from the managed to the JNI calling convention void JniCompiler::CopyParameter(Assembler* jni_asm, ManagedRuntimeCallingConvention* mr_conv, diff --git a/src/jni_compiler.h b/src/jni_compiler.h index a3b2e5365a..3c0d8b48b0 100644 --- a/src/jni_compiler.h +++ b/src/jni_compiler.h @@ -30,6 +30,10 @@ class JniCompiler { JniCallingConvention* jni_conv, size_t frame_size, size_t out_arg_size); + void SetNativeParameter(Assembler *jni_asm, + JniCallingConvention *jni_conv, + ManagedRegister in_reg); + // A poor man's code cache void* AllocateCode(size_t size); diff --git a/src/thread.h b/src/thread.h index 0a9415106a..8a297d6b88 100644 --- a/src/thread.h +++ b/src/thread.h @@ -313,6 +313,9 @@ class Thread { void* throw_pc, const DexFile& dex_file, ClassLinker* class_linker); + static ThreadOffset SelfOffset() { + return ThreadOffset(OFFSETOF_MEMBER(Thread, self_)); + } // Offset of exception within Thread, used by generated code static ThreadOffset ExceptionOffset() { |