Support for synchronized native methods.
This change adds support for synchronized native methods by using
calls to MonitorEnter and MonitorExit on the JNIEnv*. There is
some tidying of the assembler and a straw man JNIEnv implementation.
The JNIEnv implementation just warns when MonitorEnter/Exit are called
and doesn't adhere to the correct JNIEnv layout.
Change-Id: I90ed6ec8f85f5b01b929f16e0dbdecadd0b01359
diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc
index 59d8c2b..23615ed 100644
--- a/src/jni_compiler_test.cc
+++ b/src/jni_compiler_test.cc
@@ -163,6 +163,22 @@
}
}
+int gJava_MyClass_fooSSIOO_calls = 0;
+jobject Java_MyClass_fooSSIOO(JNIEnv*, jclass klass, jint x, jobject y,
+ jobject z) {
+ EXPECT_EQ(3u, Thread::Current()->NumShbHandles());
+ EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
+ gJava_MyClass_fooSSIOO_calls++;
+ switch (x) {
+ case 1:
+ return y;
+ case 2:
+ return z;
+ default:
+ return klass;
+ }
+}
+
TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
scoped_ptr<DexFile> dex(OpenDexFileBase64(kMyClassNativesDex));
scoped_ptr<ClassLinker> linker(ClassLinker::Create());
@@ -387,4 +403,57 @@
EXPECT_EQ(7, gJava_MyClass_fooSIOO_calls);
}
+TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
+ scoped_ptr<DexFile> dex(OpenDexFileBase64(kMyClassNativesDex));
+ scoped_ptr<ClassLinker> linker(ClassLinker::Create());
+ linker->AppendToClassPath(dex.get());
+ Class* klass = linker->FindClass("LMyClass;", NULL);
+ Method* method = klass->FindDirectMethod("fooSSIOO");
+
+ Assembler jni_asm;
+ JniCompiler jni_compiler;
+ jni_compiler.Compile(&jni_asm, method);
+
+ // TODO: should really use JNIEnv to RegisterNative, but missing a
+ // complete story on this, so hack the RegisterNative below
+ method->RegisterNative(reinterpret_cast<void*>(&Java_MyClass_fooSSIOO));
+
+ jvalue a, b, c, d;
+ a.i = 0;
+ b.l = (jobject)NULL;
+ c.l = (jobject)NULL;
+ EXPECT_EQ(0, gJava_MyClass_fooSSIOO_calls);
+ d = RunMethod(method, a, b, c, a);
+ ASSERT_EQ((jobject)method->GetClass(), d.l);
+ EXPECT_EQ(1, gJava_MyClass_fooSSIOO_calls);
+ a.i = 0;
+ b.l = (jobject)NULL;
+ c.l = (jobject)16;
+ d = RunMethod(method, a, b, c, a);
+ ASSERT_EQ((jobject)method->GetClass(), d.l);
+ EXPECT_EQ(2, gJava_MyClass_fooSSIOO_calls);
+ a.i = 1;
+ d = RunMethod(method, a, b, c, a);
+ ASSERT_EQ((jobject)NULL, d.l);
+ EXPECT_EQ(3, gJava_MyClass_fooSSIOO_calls);
+ a.i = 2;
+ d = RunMethod(method, a, b, c, a);
+ ASSERT_EQ((jobject)16, d.l);
+ EXPECT_EQ(4, gJava_MyClass_fooSSIOO_calls);
+ a.i = 0;
+ b.l = (jobject)16;
+ c.l = (jobject)NULL;
+ d = RunMethod(method, a, b, c, a);
+ ASSERT_EQ((jobject)method->GetClass(), d.l);
+ EXPECT_EQ(5, gJava_MyClass_fooSSIOO_calls);
+ a.i = 1;
+ d = RunMethod(method, a, b, c, a);
+ ASSERT_EQ((jobject)16, d.l);
+ EXPECT_EQ(6, gJava_MyClass_fooSSIOO_calls);
+ a.i = 2;
+ d = RunMethod(method, a, b, c, a);
+ ASSERT_EQ((jobject)NULL, d.l);
+ EXPECT_EQ(7, gJava_MyClass_fooSSIOO_calls);
+}
+
} // namespace art