Clean up JNI dlsym lookup trampoline.
Make sure the GenericJniTrampoline recognizes the trampoline
in primary boot image oat file. Rename that trampoline, add
a test and flag some issues in the code.
Test: New test 178-app-image-native-method.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: testrunner.py --host -t 178-app-image-native-method
Bug: 112189621
Change-Id: I8f8cd11998af536fd3842dd4183a25f0367655a6
diff --git a/test/178-app-image-native-method/check b/test/178-app-image-native-method/check
new file mode 100755
index 0000000..5336295
--- /dev/null
+++ b/test/178-app-image-native-method/check
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Filter out error messages for missing native methods.
+grep -v 'No implementation found for ' "$2" | diff -q "$1" - >/dev/null
diff --git a/test/178-app-image-native-method/expected.txt b/test/178-app-image-native-method/expected.txt
new file mode 100644
index 0000000..02384cd
--- /dev/null
+++ b/test/178-app-image-native-method/expected.txt
@@ -0,0 +1,6 @@
+JNI_OnLoad called
+test
+testMissing
+JNI_OnLoad called
+test
+testMissing
diff --git a/test/178-app-image-native-method/info.txt b/test/178-app-image-native-method/info.txt
new file mode 100644
index 0000000..4cf01fe
--- /dev/null
+++ b/test/178-app-image-native-method/info.txt
@@ -0,0 +1 @@
+Tests that native methods in app image using compiled stubs or Generic JNI work correctly.
diff --git a/test/178-app-image-native-method/native_methods.cc b/test/178-app-image-native-method/native_methods.cc
new file mode 100644
index 0000000..5c4fb3e
--- /dev/null
+++ b/test/178-app-image-native-method/native_methods.cc
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+
+namespace art {
+
+static inline bool VerifyManyParameters(
+ jint i1, jlong l1, jfloat f1, jdouble d1,
+ jint i2, jlong l2, jfloat f2, jdouble d2,
+ jint i3, jlong l3, jfloat f3, jdouble d3,
+ jint i4, jlong l4, jfloat f4, jdouble d4,
+ jint i5, jlong l5, jfloat f5, jdouble d5,
+ jint i6, jlong l6, jfloat f6, jdouble d6,
+ jint i7, jlong l7, jfloat f7, jdouble d7,
+ jint i8, jlong l8, jfloat f8, jdouble d8) {
+ return
+ (i1 == 11) && (l1 == 12) && (f1 == 13.0) && (d1 == 14.0) &&
+ (i2 == 21) && (l2 == 22) && (f2 == 23.0) && (d2 == 24.0) &&
+ (i3 == 31) && (l3 == 32) && (f3 == 33.0) && (d3 == 34.0) &&
+ (i4 == 41) && (l4 == 42) && (f4 == 43.0) && (d4 == 44.0) &&
+ (i5 == 51) && (l5 == 52) && (f5 == 53.0) && (d5 == 54.0) &&
+ (i6 == 61) && (l6 == 62) && (f6 == 63.0) && (d6 == 64.0) &&
+ (i7 == 71) && (l7 == 72) && (f7 == 73.0) && (d7 == 74.0) &&
+ (i8 == 81) && (l8 == 82) && (f8 == 83.0) && (d8 == 84.0);
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Test_nativeMethod(JNIEnv*, jclass, jint i) {
+ return i;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Test_nativeMethodWithManyParameters(
+ JNIEnv*, jclass,
+ jint i1, jlong l1, jfloat f1, jdouble d1,
+ jint i2, jlong l2, jfloat f2, jdouble d2,
+ jint i3, jlong l3, jfloat f3, jdouble d3,
+ jint i4, jlong l4, jfloat f4, jdouble d4,
+ jint i5, jlong l5, jfloat f5, jdouble d5,
+ jint i6, jlong l6, jfloat f6, jdouble d6,
+ jint i7, jlong l7, jfloat f7, jdouble d7,
+ jint i8, jlong l8, jfloat f8, jdouble d8) {
+ bool ok = VerifyManyParameters(
+ i1, l1, f1, d1,
+ i2, l2, f2, d2,
+ i3, l3, f3, d3,
+ i4, l4, f4, d4,
+ i5, l5, f5, d5,
+ i6, l6, f6, d6,
+ i7, l7, f7, d7,
+ i8, l8, f8, d8);
+ return ok ? 42 : -1;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_TestFast_nativeMethod(JNIEnv*, jclass, jint i) {
+ return i;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_TestFast_nativeMethodWithManyParameters(
+ JNIEnv*, jclass,
+ jint i1, jlong l1, jfloat f1, jdouble d1,
+ jint i2, jlong l2, jfloat f2, jdouble d2,
+ jint i3, jlong l3, jfloat f3, jdouble d3,
+ jint i4, jlong l4, jfloat f4, jdouble d4,
+ jint i5, jlong l5, jfloat f5, jdouble d5,
+ jint i6, jlong l6, jfloat f6, jdouble d6,
+ jint i7, jlong l7, jfloat f7, jdouble d7,
+ jint i8, jlong l8, jfloat f8, jdouble d8) {
+ bool ok = VerifyManyParameters(
+ i1, l1, f1, d1,
+ i2, l2, f2, d2,
+ i3, l3, f3, d3,
+ i4, l4, f4, d4,
+ i5, l5, f5, d5,
+ i6, l6, f6, d6,
+ i7, l7, f7, d7,
+ i8, l8, f8, d8);
+ return ok ? 42 : -1;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_TestCritical_nativeMethod(jint i) {
+ return i;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_TestCritical_nativeMethodWithManyParameters(
+ jint i1, jlong l1, jfloat f1, jdouble d1,
+ jint i2, jlong l2, jfloat f2, jdouble d2,
+ jint i3, jlong l3, jfloat f3, jdouble d3,
+ jint i4, jlong l4, jfloat f4, jdouble d4,
+ jint i5, jlong l5, jfloat f5, jdouble d5,
+ jint i6, jlong l6, jfloat f6, jdouble d6,
+ jint i7, jlong l7, jfloat f7, jdouble d7,
+ jint i8, jlong l8, jfloat f8, jdouble d8) {
+ bool ok = VerifyManyParameters(
+ i1, l1, f1, d1,
+ i2, l2, f2, d2,
+ i3, l3, f3, d3,
+ i4, l4, f4, d4,
+ i5, l5, f5, d5,
+ i6, l6, f6, d6,
+ i7, l7, f7, d7,
+ i8, l8, f8, d8);
+ return ok ? 42 : -1;
+}
+
+} // namespace art
diff --git a/test/178-app-image-native-method/profile b/test/178-app-image-native-method/profile
new file mode 100644
index 0000000..597dde1
--- /dev/null
+++ b/test/178-app-image-native-method/profile
@@ -0,0 +1,8 @@
+LMain;
+LTest;
+HSPLMain;->test()V
+HSPLMain;->testFast()V
+HSPLMain;->testCritical()V
+HSPLMain;->testMissing()V
+HSPLMain;->testMissingFast()V
+HSPLMain;->testMissingCritical()V
diff --git a/test/178-app-image-native-method/run b/test/178-app-image-native-method/run
new file mode 100644
index 0000000..3cb4d09
--- /dev/null
+++ b/test/178-app-image-native-method/run
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Use a profile to put specific classes in the app image.
+${RUN} $@ --profile -Xcompiler-option --compiler-filter=speed-profile
+return_status1=$?
+
+# Also run with the verify filter to avoid compiling JNI stubs.
+${RUN} ${@} --profile -Xcompiler-option --compiler-filter=verify
+return_status2=$?
+
+(exit ${return_status1}) # && (exit ${return_status2})
diff --git a/test/178-app-image-native-method/src/Main.java b/test/178-app-image-native-method/src/Main.java
new file mode 100644
index 0000000..d63d112
--- /dev/null
+++ b/test/178-app-image-native-method/src/Main.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import dalvik.annotation.optimization.FastNative;
+import dalvik.annotation.optimization.CriticalNative;
+
+public class Main {
+
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+
+ if (!checkAppImageLoaded()) {
+ System.out.println("AppImage not loaded.");
+ }
+ // To avoid going through resolution trampoline, make test classes visibly initialized.
+ new Test();
+ new TestFast();
+ new TestCritical();
+ new TestMissing();
+ new TestMissingFast();
+ new TestMissingCritical();
+ makeVisiblyInitialized(); // Make sure they are visibly initialized.
+
+ // FIXME: @FastNative and @CriticalNative fail a state check in artFindNativeMethod().
+ test();
+ // testFast();
+ // testCritical();
+ testMissing();
+ // testMissingFast();
+ // testMissingCritical();
+ }
+
+ static void test() {
+ System.out.println("test");
+ assertEquals(42, Test.nativeMethod(42));
+ assertEquals(42, Test.nativeMethodWithManyParameters(
+ 11, 12L, 13.0f, 14.0d,
+ 21, 22L, 23.0f, 24.0d,
+ 31, 32L, 33.0f, 34.0d,
+ 41, 42L, 43.0f, 44.0d,
+ 51, 52L, 53.0f, 54.0d,
+ 61, 62L, 63.0f, 64.0d,
+ 71, 72L, 73.0f, 74.0d,
+ 81, 82L, 83.0f, 84.0d));
+ }
+
+ static void testFast() {
+ System.out.println("testFast");
+ assertEquals(42, TestFast.nativeMethod(42));
+ assertEquals(42, TestFast.nativeMethodWithManyParameters(
+ 11, 12L, 13.0f, 14.0d,
+ 21, 22L, 23.0f, 24.0d,
+ 31, 32L, 33.0f, 34.0d,
+ 41, 42L, 43.0f, 44.0d,
+ 51, 52L, 53.0f, 54.0d,
+ 61, 62L, 63.0f, 64.0d,
+ 71, 72L, 73.0f, 74.0d,
+ 81, 82L, 83.0f, 84.0d));
+ }
+
+ static void testCritical() {
+ System.out.println("testCritical");
+ assertEquals(42, TestCritical.nativeMethod(42));
+ assertEquals(42, TestCritical.nativeMethodWithManyParameters(
+ 11, 12L, 13.0f, 14.0d,
+ 21, 22L, 23.0f, 24.0d,
+ 31, 32L, 33.0f, 34.0d,
+ 41, 42L, 43.0f, 44.0d,
+ 51, 52L, 53.0f, 54.0d,
+ 61, 62L, 63.0f, 64.0d,
+ 71, 72L, 73.0f, 74.0d,
+ 81, 82L, 83.0f, 84.0d));
+ }
+
+ static void testMissing() {
+ System.out.println("testMissing");
+
+ try {
+ TestMissing.nativeMethod(42);
+ throw new Error("UNREACHABLE");
+ } catch (LinkageError expected) {}
+
+ try {
+ TestMissing.nativeMethodWithManyParameters(
+ 11, 12L, 13.0f, 14.0d,
+ 21, 22L, 23.0f, 24.0d,
+ 31, 32L, 33.0f, 34.0d,
+ 41, 42L, 43.0f, 44.0d,
+ 51, 52L, 53.0f, 54.0d,
+ 61, 62L, 63.0f, 64.0d,
+ 71, 72L, 73.0f, 74.0d,
+ 81, 82L, 83.0f, 84.0d);
+ throw new Error("UNREACHABLE");
+ } catch (LinkageError expected) {}
+ }
+
+ static void testMissingFast() {
+ System.out.println("testMissingFast");
+
+ try {
+ TestMissingFast.nativeMethod(42);
+ throw new Error("UNREACHABLE");
+ } catch (LinkageError expected) {}
+
+ try {
+ TestMissingFast.nativeMethodWithManyParameters(
+ 11, 12L, 13.0f, 14.0d,
+ 21, 22L, 23.0f, 24.0d,
+ 31, 32L, 33.0f, 34.0d,
+ 41, 42L, 43.0f, 44.0d,
+ 51, 52L, 53.0f, 54.0d,
+ 61, 62L, 63.0f, 64.0d,
+ 71, 72L, 73.0f, 74.0d,
+ 81, 82L, 83.0f, 84.0d);
+ throw new Error("UNREACHABLE");
+ } catch (LinkageError expected) {}
+ }
+
+ static void testMissingCritical() {
+ System.out.println("testMissingCritical");
+
+ try {
+ TestMissingCritical.nativeMethod(42);
+ throw new Error("UNREACHABLE");
+ } catch (LinkageError expected) {}
+
+ try {
+ TestMissingCritical.nativeMethodWithManyParameters(
+ 11, 12L, 13.0f, 14.0d,
+ 21, 22L, 23.0f, 24.0d,
+ 31, 32L, 33.0f, 34.0d,
+ 41, 42L, 43.0f, 44.0d,
+ 51, 52L, 53.0f, 54.0d,
+ 61, 62L, 63.0f, 64.0d,
+ 71, 72L, 73.0f, 74.0d,
+ 81, 82L, 83.0f, 84.0d);
+ throw new Error("UNREACHABLE");
+ } catch (LinkageError expected) {}
+ }
+
+ static void assertEquals(int expected, int actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected " + expected + " got " + actual);
+ }
+ }
+
+ public static native boolean checkAppImageLoaded();
+ public static native void makeVisiblyInitialized();
+}
+
+class Test {
+ public static native int nativeMethod(int i);
+
+ public static native int nativeMethodWithManyParameters(
+ int i1, long l1, float f1, double d1,
+ int i2, long l2, float f2, double d2,
+ int i3, long l3, float f3, double d3,
+ int i4, long l4, float f4, double d4,
+ int i5, long l5, float f5, double d5,
+ int i6, long l6, float f6, double d6,
+ int i7, long l7, float f7, double d7,
+ int i8, long l8, float f8, double d8);
+}
+
+class TestFast {
+ @FastNative
+ public static native int nativeMethod(int i);
+
+ @FastNative
+ public static native int nativeMethodWithManyParameters(
+ int i1, long l1, float f1, double d1,
+ int i2, long l2, float f2, double d2,
+ int i3, long l3, float f3, double d3,
+ int i4, long l4, float f4, double d4,
+ int i5, long l5, float f5, double d5,
+ int i6, long l6, float f6, double d6,
+ int i7, long l7, float f7, double d7,
+ int i8, long l8, float f8, double d8);
+}
+
+class TestCritical {
+ @CriticalNative
+ public static native int nativeMethod(int i);
+
+ @CriticalNative
+ public static native int nativeMethodWithManyParameters(
+ int i1, long l1, float f1, double d1,
+ int i2, long l2, float f2, double d2,
+ int i3, long l3, float f3, double d3,
+ int i4, long l4, float f4, double d4,
+ int i5, long l5, float f5, double d5,
+ int i6, long l6, float f6, double d6,
+ int i7, long l7, float f7, double d7,
+ int i8, long l8, float f8, double d8);
+}
+
+class TestMissing {
+ public static native int nativeMethod(int i);
+
+ public static native int nativeMethodWithManyParameters(
+ int i1, long l1, float f1, double d1,
+ int i2, long l2, float f2, double d2,
+ int i3, long l3, float f3, double d3,
+ int i4, long l4, float f4, double d4,
+ int i5, long l5, float f5, double d5,
+ int i6, long l6, float f6, double d6,
+ int i7, long l7, float f7, double d7,
+ int i8, long l8, float f8, double d8);
+}
+
+class TestMissingFast {
+ @FastNative
+ public static native int nativeMethod(int i);
+
+ @FastNative
+ public static native int nativeMethodWithManyParameters(
+ int i1, long l1, float f1, double d1,
+ int i2, long l2, float f2, double d2,
+ int i3, long l3, float f3, double d3,
+ int i4, long l4, float f4, double d4,
+ int i5, long l5, float f5, double d5,
+ int i6, long l6, float f6, double d6,
+ int i7, long l7, float f7, double d7,
+ int i8, long l8, float f8, double d8);
+}
+
+class TestMissingCritical {
+ @CriticalNative
+ public static native int nativeMethod(int i);
+
+ @CriticalNative
+ public static native int nativeMethodWithManyParameters(
+ int i1, long l1, float f1, double d1,
+ int i2, long l2, float f2, double d2,
+ int i3, long l3, float f3, double d3,
+ int i4, long l4, float f4, double d4,
+ int i5, long l5, float f5, double d5,
+ int i6, long l6, float f6, double d6,
+ int i7, long l7, float f7, double d7,
+ int i8, long l8, float f8, double d8);
+}