Exception and suspend count polling on JNI bridge return.
Change-Id: I0e5597fcbdcdb88100b18d63323e7ba8d27f13fe
diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc
index 23615ed..db8a9e7 100644
--- a/src/jni_compiler_test.cc
+++ b/src/jni_compiler_test.cc
@@ -198,7 +198,7 @@
jvalue a;
a.l = (jobject)NULL;
- EXPECT_EQ(0, gJava_MyClass_foo_calls);
+ gJava_MyClass_foo_calls = 0;
RunMethod(method, a, a, a, a);
EXPECT_EQ(1, gJava_MyClass_foo_calls);
RunMethod(method, a, a, a, a);
@@ -456,4 +456,85 @@
EXPECT_EQ(7, gJava_MyClass_fooSSIOO_calls);
}
+int gSuspendCounterHandler_calls;
+void SuspendCountHandler(Method** frame) {
+ EXPECT_EQ(0, (*frame)->GetName().compare("fooI"));
+ gSuspendCounterHandler_calls++;
+ Thread::Current()->DecrementSuspendCount();
+}
+TEST_F(JniCompilerTest, SuspendCountAcknolewdgement) {
+ 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->FindVirtualMethod("fooI");
+
+ 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_fooI));
+ Thread::Current()->RegisterSuspendCountEntryPoint(&SuspendCountHandler);
+
+ gSuspendCounterHandler_calls = 0;
+ gJava_MyClass_fooI_calls = 0;
+ jvalue a, b, c;
+ a.l = (jobject)NULL;
+ b.i = 42;
+ c = RunMethod(method, a, b, a, a);
+ ASSERT_EQ(42, c.i);
+ EXPECT_EQ(1, gJava_MyClass_fooI_calls);
+ EXPECT_EQ(0, gSuspendCounterHandler_calls);
+ Thread::Current()->IncrementSuspendCount();
+ c = RunMethod(method, a, b, a, a);
+ ASSERT_EQ(42, c.i);
+ EXPECT_EQ(2, gJava_MyClass_fooI_calls);
+ EXPECT_EQ(1, gSuspendCounterHandler_calls);
+ c = RunMethod(method, a, b, a, a);
+ ASSERT_EQ(42, c.i);
+ EXPECT_EQ(3, gJava_MyClass_fooI_calls);
+ EXPECT_EQ(1, gSuspendCounterHandler_calls);
+}
+
+int gExceptionHandler_calls;
+void ExceptionHandler(Method** frame) {
+ EXPECT_EQ(0, (*frame)->GetName().compare("foo"));
+ gExceptionHandler_calls++;
+ Thread::Current()->ClearException();
+}
+TEST_F(JniCompilerTest, ExceptionHandling) {
+ 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->FindVirtualMethod("foo");
+
+ 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_foo));
+ Thread::Current()->RegisterExceptionEntryPoint(&ExceptionHandler);
+
+ gExceptionHandler_calls = 0;
+ gJava_MyClass_foo_calls = 0;
+ jvalue a;
+ a.l = (jobject)NULL;
+ RunMethod(method, a, a, a, a);
+ EXPECT_EQ(1, gJava_MyClass_foo_calls);
+ EXPECT_EQ(0, gExceptionHandler_calls);
+ // TODO: create a real exception here
+ Thread::Current()->SetException(reinterpret_cast<Object*>(8));
+ RunMethod(method, a, a, a, a);
+ EXPECT_EQ(2, gJava_MyClass_foo_calls);
+ EXPECT_EQ(1, gExceptionHandler_calls);
+ RunMethod(method, a, a, a, a);
+ EXPECT_EQ(3, gJava_MyClass_foo_calls);
+ EXPECT_EQ(1, gExceptionHandler_calls);
+}
+
} // namespace art