changeset 8816:119a08b69f70

8148175: C1: G1 barriers don't preserve FP registers Reviewed-by: vlivanov, kvn
author mchinnathamb
date Wed, 07 Feb 2018 07:01:44 -0500
parents 427b2fb1944f
children a2c8195708cc
files src/cpu/x86/vm/c1_Runtime1_x86.cpp test/compiler/gcbarriers/PreserveFPRegistersTest.java
diffstat 2 files changed, 111 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Jan 31 19:24:57 2018 -0500
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Feb 07 07:01:44 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. 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
@@ -1667,31 +1667,15 @@
         __ jmp(done);
 
         __ bind(runtime);
-        __ push(rcx);
-#ifdef _LP64
-        __ push(r8);
-        __ push(r9);
-        __ push(r10);
-        __ push(r11);
-#  ifndef _WIN64
-        __ push(rdi);
-        __ push(rsi);
-#  endif
-#endif
+
+        save_live_registers(sasm, 3);
+
         // load the pre-value
         f.load_argument(0, rcx);
         __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), rcx, thread);
-#ifdef _LP64
-#  ifndef _WIN64
-        __ pop(rsi);
-        __ pop(rdi);
-#  endif
-        __ pop(r11);
-        __ pop(r10);
-        __ pop(r9);
-        __ pop(r8);
-#endif
-        __ pop(rcx);
+
+        restore_live_registers(sasm);
+
         __ bind(done);
 
         __ pop(rdx);
@@ -1773,27 +1757,13 @@
 
         __ bind(runtime);
         __ push(rdx);
-#ifdef _LP64
-        __ push(r8);
-        __ push(r9);
-        __ push(r10);
-        __ push(r11);
-#  ifndef _WIN64
-        __ push(rdi);
-        __ push(rsi);
-#  endif
-#endif
+
+        save_live_registers(sasm, 3);
+
         __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);
-#ifdef _LP64
-#  ifndef _WIN64
-        __ pop(rsi);
-        __ pop(rdi);
-#  endif
-        __ pop(r11);
-        __ pop(r10);
-        __ pop(r9);
-        __ pop(r8);
-#endif
+
+        restore_live_registers(sasm);
+
         __ pop(rdx);
         __ bind(done);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/gcbarriers/PreserveFPRegistersTest.java	Wed Feb 07 07:01:44 2018 -0500
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. 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 8148175
+ * @run main/othervm/timeout=300  -XX:+UseG1GC -Xbatch -Xmx128m PreserveFPRegistersTest
+ */
+public class PreserveFPRegistersTest {
+
+    public static void main(String... args) throws InterruptedException {
+        new PreserveFPRegistersTest().go();
+    }
+
+    public final Object[][] storage;
+
+    /**
+     * Number of objects per region.
+     */
+    public final int K = 10;
+
+    /**
+     * Length of object array: sizeOf(Object[N]) ~= regionSize / K .
+     */
+    public final int N;
+
+    /**
+     * How many regions involved into testing.
+     */
+    public final int regionCount;
+
+    PreserveFPRegistersTest() {
+        long regionSize = 1_000_000; //WB.g1RegionSize();
+
+        Runtime rt = Runtime.getRuntime();
+        long used = rt.totalMemory() - rt.freeMemory();
+        long totalFree = rt.maxMemory() - used;
+        regionCount = (int) ( (totalFree / regionSize) * 0.9);
+        int refSize = 4;
+
+        N = (int) ((regionSize / K ) / refSize) - 5;
+        storage = new Object[regionCount * K][];
+        for (int i = 0; i < storage.length; i++) {
+            storage[i] = new Object[N];
+        }
+    }
+
+    public void go() throws InterruptedException {
+        final float FINAL = getValue();
+
+        for (int to = 0; to < regionCount; to++) {
+            Object celebrity = storage[to * K];
+            for (int from = 0; from < regionCount; from++) {
+                for (int rn = 0; rn != 100; rn++) {
+                    storage[getY(to, from, rn)][getX(to, from, rn)] = celebrity;
+                }
+                if (FINAL != getValue()) {
+                    throw new AssertionError("Final value has changed: " + FINAL + " != " + getValue());
+                }
+            }
+        }
+
+        System.out.println("TEST PASSED");
+    }
+
+    public float getValue() {
+        return 6;
+    }
+
+    private int getX(int to, int from, int rn) {
+        return (rn*regionCount + to) % N;
+    }
+
+    private int getY(int to, int from, int rn) {
+        return ((rn*regionCount + to) / N + from * K) % (regionCount*K) ;
+    }
+}