Initial ARM JNI compiler support.
Change-Id: I85183eec9a2645e6cb074b4b18bc6af800a77e06
diff --git a/src/jni_compiler.cc b/src/jni_compiler.cc
index f80e7ad..7eabe4e 100644
--- a/src/jni_compiler.cc
+++ b/src/jni_compiler.cc
@@ -74,7 +74,6 @@
bool input_in_reg = mr_conv.IsCurrentParamInRegister();
CHECK(input_in_reg || mr_conv.IsCurrentParamOnStack());
if (input_in_reg) {
- LOG(FATAL) << "UNTESTED";
ManagedRegister in_reg = mr_conv.CurrentParamRegister();
jni_asm->ValidateRef(in_reg, mr_conv.IsCurrentParamPossiblyNull());
jni_asm->StoreRef(handle_offset, in_reg);
@@ -90,8 +89,7 @@
}
// 5. Transition from being in managed to native code
- // TODO: write out anchor, ensure the transition to native follow a store
- // fence.
+ // TODO: ensure the transition to native follow a store fence.
jni_asm->StoreStackPointerToThread(Thread::TopOfManagedStackOffset());
jni_asm->StoreImmediateToThread(Thread::StateOffset(), Thread::kNative,
mr_conv.InterproceduralScratchRegister());
@@ -103,6 +101,7 @@
// 7. Acquire lock for synchronized methods.
if (native_method->IsSynchronized()) {
+ // TODO: preserve incoming arguments in registers
mr_conv.ResetIterator(FrameOffset(frame_size+out_arg_size));
jni_conv.ResetIterator(FrameOffset(out_arg_size));
jni_conv.Next(); // Skip JNIEnv*
@@ -148,6 +147,19 @@
jni_conv.ResetIterator(FrameOffset(out_arg_size));
jni_conv.Next(); // Skip JNIEnv*
if (is_static) {
+ jni_conv.Next(); // Skip Class for now
+ }
+ while (mr_conv.HasNext()) {
+ CHECK(jni_conv.HasNext());
+ CopyParameter(jni_asm, &mr_conv, &jni_conv, frame_size, out_arg_size);
+ mr_conv.Next();
+ jni_conv.Next();
+ }
+ if (is_static) {
+ // Create argument for Class
+ mr_conv.ResetIterator(FrameOffset(frame_size+out_arg_size));
+ jni_conv.ResetIterator(FrameOffset(out_arg_size));
+ jni_conv.Next(); // Skip JNIEnv*
FrameOffset handle_offset = jni_conv.CurrentParamHandleOffset();
if (jni_conv.IsCurrentParamOnStack()) {
FrameOffset out_off = jni_conv.CurrentParamStackOffset();
@@ -159,13 +171,6 @@
jni_asm->CreateStackHandle(out_reg, handle_offset,
ManagedRegister::NoRegister(), false);
}
- jni_conv.Next();
- }
- while (mr_conv.HasNext()) {
- CHECK(jni_conv.HasNext());
- CopyParameter(jni_asm, &mr_conv, &jni_conv, frame_size, out_arg_size);
- mr_conv.Next();
- jni_conv.Next();
}
// 9. Create 1st argument, the JNI environment ptr
jni_conv.ResetIterator(FrameOffset(out_arg_size));
@@ -179,9 +184,15 @@
}
// 10. Plant call to native code associated with method
- jni_asm->Call(mr_conv.MethodRegister(), Method::NativeMethodOffset(),
- mr_conv.InterproceduralScratchRegister());
-
+ if (!jni_conv.IsOutArgRegister(mr_conv.MethodRegister())) {
+ // Method register shouldn't have been crushed by setting up outgoing
+ // arguments
+ jni_asm->Call(mr_conv.MethodRegister(), Method::NativeMethodOffset(),
+ mr_conv.InterproceduralScratchRegister());
+ } else {
+ jni_asm->Call(jni_conv.MethodStackOffset(), Method::NativeMethodOffset(),
+ mr_conv.InterproceduralScratchRegister());
+ }
// 11. Release lock for synchronized methods.
if (native_method->IsSynchronized()) {
mr_conv.ResetIterator(FrameOffset(frame_size+out_arg_size));
@@ -294,7 +305,6 @@
CHECK_LT(handle_offset.Uint32Value(), (frame_size+out_arg_size));
}
if (input_in_reg && output_in_reg) {
- LOG(FATAL) << "UNTESTED";
ManagedRegister in_reg = mr_conv->CurrentParamRegister();
ManagedRegister out_reg = jni_conv->CurrentParamRegister();
if (ref_param) {
@@ -317,7 +327,6 @@
param_size);
}
} else if (!input_in_reg && output_in_reg) {
- LOG(FATAL) << "UNTESTED";
FrameOffset in_off = mr_conv->CurrentParamStackOffset();
ManagedRegister out_reg = jni_conv->CurrentParamRegister();
// Check that incoming stack arguments are above the current stack frame.
@@ -331,7 +340,6 @@
jni_asm->Load(out_reg, in_off, param_size);
}
} else {
- LOG(FATAL) << "UNTESTED";
CHECK(input_in_reg && !output_in_reg);
ManagedRegister in_reg = mr_conv->CurrentParamRegister();
FrameOffset out_off = jni_conv->CurrentParamStackOffset();
@@ -362,8 +370,8 @@
// code cache.
jni_code_size_ = 4096;
jni_code_ = static_cast<byte*>(mmap(NULL, jni_code_size_,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
CHECK_NE(MAP_FAILED, jni_code_);
jni_code_top_ = jni_code_;
}