Support for JNI local reference cookie.
This also fixes a cross compilation bug in reseting the top of the
indirect reference table following a down call.
Change-Id: I40d913a6f86dadfe87b58d6d13a1ff3613f270ac
diff --git a/src/jni_compiler.cc b/src/jni_compiler.cc
index 6404b05..6c09f58 100644
--- a/src/jni_compiler.cc
+++ b/src/jni_compiler.cc
@@ -116,8 +116,10 @@
// Compute SIRT entry, note null is placed in the SIRT but its boxed value
// must be NULL
FrameOffset sirt_offset = jni_conv->CurrentParamSirtEntryOffset();
- // Check SIRT offset is within frame
+ // Check SIRT offset is within frame and doesn't run into the saved segment state
CHECK_LT(sirt_offset.Uint32Value(), frame_size);
+ CHECK_NE(sirt_offset.Uint32Value(),
+ jni_conv->SavedLocalReferenceCookieOffset().Uint32Value());
bool input_in_reg = mr_conv->IsCurrentParamInRegister();
bool input_on_stack = mr_conv->IsCurrentParamOnStack();
CHECK(input_in_reg || input_on_stack);
@@ -267,14 +269,26 @@
ManagedRegister jni_env = jni_conv->CurrentParamRegister();
DCHECK(!jni_env.Equals(jni_conv->InterproceduralScratchRegister()));
__ LoadRawPtrFromThread(jni_env, Thread::JniEnvOffset());
- __ Copy(jni_conv->LocalReferenceTable_SegmentStatesOffset(), jni_env,
- JNIEnvExt::SegmentStateOffset(), jni_conv->InterproceduralScratchRegister(), 4);
+ // Frame[saved_local_ref_cookie_offset] = env->local_ref_cookie
+ __ Copy(jni_conv->SavedLocalReferenceCookieOffset(),
+ jni_env, JNIEnvExt::LocalRefCookieOffset(),
+ jni_conv->InterproceduralScratchRegister(), 4);
+ // env->local_ref_cookie = env->locals.segment_state
+ __ Copy(jni_env, JNIEnvExt::LocalRefCookieOffset(),
+ jni_env, JNIEnvExt::SegmentStateOffset(),
+ jni_conv->InterproceduralScratchRegister(), 4);
} else {
FrameOffset jni_env = jni_conv->CurrentParamStackOffset();
__ CopyRawPtrFromThread(jni_env, Thread::JniEnvOffset(),
jni_conv->InterproceduralScratchRegister());
- __ Copy(jni_conv->LocalReferenceTable_SegmentStatesOffset(), jni_env,
- JNIEnvExt::SegmentStateOffset(), jni_conv->InterproceduralScratchRegister(), 4);
+ // Frame[saved_local_ref_cookie_offset] = env->local_ref_cookie
+ __ Copy(jni_conv->SavedLocalReferenceCookieOffset(),
+ jni_env, JNIEnvExt::LocalRefCookieOffset(),
+ jni_conv->InterproceduralScratchRegister(), 4);
+ // env->local_ref_cookie = env->locals.segment_state
+ __ Copy(jni_env, JNIEnvExt::LocalRefCookieOffset(),
+ jni_env, JNIEnvExt::SegmentStateOffset(),
+ jni_conv->InterproceduralScratchRegister(), 4);
}
// 9. Plant call to native code associated with method
@@ -387,10 +401,18 @@
__ Move(mr_conv->ReturnRegister(), jni_conv->ReturnRegister());
// 15. Restore segment state and remove SIRT from thread
- __ Copy(Thread::JniEnvOffset(), JNIEnvExt::SegmentStateOffset(),
- jni_conv->LocalReferenceTable_SegmentStatesOffset(),
- jni_conv->InterproceduralScratchRegister(),
- jni_conv->ReturnScratchRegister(), 4);
+ {
+ ManagedRegister jni_env = jni_conv->InterproceduralScratchRegister();
+ __ LoadRawPtrFromThread(jni_env, Thread::JniEnvOffset());
+ // env->locals.segment_state = env->local_ref_cookie
+ __ Copy(jni_env, JNIEnvExt::SegmentStateOffset(),
+ jni_env, JNIEnvExt::LocalRefCookieOffset(),
+ jni_conv->ReturnScratchRegister(), 4);
+ // env->local_ref_cookie = Frame[saved_local_ref_cookie_offset]
+ __ Copy(jni_env, JNIEnvExt::LocalRefCookieOffset(),
+ jni_conv->SavedLocalReferenceCookieOffset(),
+ jni_conv->ReturnScratchRegister(), 4);
+ }
__ CopyRawPtrToThread(Thread::TopSirtOffset(), jni_conv->SirtLinkOffset(),
jni_conv->InterproceduralScratchRegister());