summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/assembler_arm.cc17
-rw-r--r--src/assembler_arm.h4
-rw-r--r--src/assembler_x86.cc15
-rw-r--r--src/assembler_x86.h4
-rw-r--r--src/calling_convention.cc16
-rw-r--r--src/calling_convention.h4
-rw-r--r--src/calling_convention_arm.cc4
-rw-r--r--src/jni_compiler.cc85
-rw-r--r--src/jni_compiler.h4
-rw-r--r--src/thread.h3
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() {