8207838: AArch64: Float registers incorrectly restored in JNI call
Summary: fix the order in which float registers are restored in restore_args for aarch64
Reviewed-by: aph
Contributed-by: guoge1@huawei.com
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp Tue Aug 21 17:47:59 2018 +0200
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp Tue Aug 21 13:44:59 2018 +0100
@@ -1107,7 +1107,7 @@
}
}
__ pop(x, sp);
- for ( int i = first_arg ; i < arg_count ; i++ ) {
+ for ( int i = arg_count - 1 ; i >= first_arg ; i-- ) {
if (args[i].first()->is_Register()) {
;
} else if (args[i].first()->is_FloatRegister()) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/floatingpoint/TestFloatSyncJNIArgs.java Tue Aug 21 13:44:59 2018 +0100
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2018 Red Hat, Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8207838
+ * @summary Regression test for passing float args to a synchronized jni function.
+ *
+ *
+ * @run main/othervm/native compiler.floatingpoint.TestFloatSyncJNIArgs
+ */
+
+package compiler.floatingpoint;
+
+public class TestFloatSyncJNIArgs {
+ static {
+ try {
+ System.loadLibrary("TestFloatSyncJNIArgs");
+ } catch (UnsatisfiedLinkError e) {
+ System.out.println("could not load native lib: " + e);
+ }
+ }
+
+ private static final int numberOfThreads = 8;
+
+ static volatile Error testFailed = null;
+
+ public synchronized static native float combine15floats(
+ float f1, float f2, float f3, float f4,
+ float f5, float f6, float f7, float f8,
+ float f9, float f10, float f11, float f12,
+ float f13, float f14, float f15);
+
+ public synchronized static native double combine15doubles(
+ double d1, double d2, double d3, double d4,
+ double d5, double d6, double d7, double d8,
+ double d9, double d10, double d11, double d12,
+ double d13, double d14, double d15);
+
+ static void test() throws Exception {
+ Thread[] threads = new Thread[numberOfThreads];
+
+ for (int i = 0; i < numberOfThreads; i++) {
+ threads[i] = new Thread(() -> {
+ for (int j = 0; j < 10000; j++) {
+ float f = combine15floats(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f,
+ 9, 10, 11, 12, 13, 14, 15);
+ if (f != 81720.0f) {
+ testFailed = new Error("jni function didn't combine 15 float args properly: " + f);
+ throw testFailed;
+ }
+ }
+ });
+ }
+ for (int i = 0; i < numberOfThreads; i++) {
+ threads[i].start();
+ }
+ for (int i = 0; i < numberOfThreads; i++) {
+ threads[i].join();
+ }
+ if (testFailed != null) {
+ throw testFailed;
+ }
+
+ for (int i = 0; i < numberOfThreads; i++) {
+ threads[i] = new Thread(() -> {
+ for (int j = 0; j < 10000; j++) {
+ double d = combine15doubles(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
+ 9, 10, 11, 12, 13, 14, 15);
+ if (d != 81720.0) {
+ testFailed = new Error("jni function didn't combine 15 double args properly: " + d);
+ throw testFailed;
+ }
+ }
+ });
+ }
+ for (int i = 0; i < numberOfThreads; i++) {
+ threads[i].start();
+ }
+ for (int i = 0; i < numberOfThreads; i++) {
+ threads[i].join();
+ }
+ if (testFailed != null) {
+ throw testFailed;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ for (int i = 0; i < 200; ++i) {
+ test();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/floatingpoint/libTestFloatSyncJNIArgs.c Tue Aug 21 13:44:59 2018 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2018 Red Hat, Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <jni.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Fletcher checksum. This is a nonlinear function which detects both */
+/* missing or otherwise incorrect arguments and arguments in the wrong */
+/* order. */
+static jfloat fcombine(jfloat f[], int len) {
+ int i;
+ jfloat sum = 0, sum_of_sums = 0;
+ for (i = 0; i < len; i++) {
+ sum += f[i];
+ sum_of_sums += sum;
+ }
+ return sum + sum_of_sums * sum;
+}
+
+static jdouble combine(jdouble f[], int len) {
+ int i;
+ double sum = 0, sum_of_sums = 0;
+ for (i = 0; i < len; i++) {
+ sum += f[i];
+ sum_of_sums += sum;
+ }
+ return sum + sum_of_sums * sum;
+}
+
+JNIEXPORT jfloat JNICALL Java_compiler_floatingpoint_TestFloatSyncJNIArgs_combine15floats
+ (JNIEnv *env, jclass cls,
+ jfloat f1, jfloat f2, jfloat f3, jfloat f4,
+ jfloat f5, jfloat f6, jfloat f7, jfloat f8,
+ jfloat f9, jfloat f10, jfloat f11, jfloat f12,
+ jfloat f13, jfloat f14, jfloat f15) {
+
+ jfloat f[15];
+ f[0] = f1; f[1] = f2; f[2] = f3; f[3] = f4; f[4] = f5;
+ f[5] = f6; f[6] = f7; f[7] = f8; f[8] = f9; f[9] = f10;
+ f[10] = f11; f[11] = f12; f[12] = f13; f[13] = f14; f[14] = f15;
+
+ return fcombine(f, sizeof f / sizeof f[0]);
+}
+
+JNIEXPORT jdouble JNICALL Java_compiler_floatingpoint_TestFloatSyncJNIArgs_combine15doubles
+ (JNIEnv *env, jclass cls,
+ jdouble f1, jdouble f2, jdouble f3, jdouble f4,
+ jdouble f5, jdouble f6, jdouble f7, jdouble f8,
+ jdouble f9, jdouble f10, jdouble f11, jdouble f12,
+ jdouble f13, jdouble f14, jdouble f15) {
+
+ jdouble f[15];
+ f[0] = f1; f[1] = f2; f[2] = f3; f[3] = f4; f[4] = f5;
+ f[5] = f6; f[6] = f7; f[7] = f8; f[8] = f9; f[9] = f10;
+ f[10] = f11; f[11] = f12; f[12] = f13; f[13] = f14; f[14] = f15;
+
+ return combine(f, sizeof f / sizeof f[0]);
+}
+
+
+#ifdef __cplusplus
+}
+#endif