Wed, 08 Mar 2017 14:22:52 +0100
8175887: C1 value numbering handling of Unsafe.get*Volatile is incorrect
Reviewed-by: vlivanov
1.1 --- a/src/share/vm/c1/c1_ValueMap.hpp Fri Feb 24 06:48:48 2017 -0800 1.2 +++ b/src/share/vm/c1/c1_ValueMap.hpp Wed Mar 08 14:22:52 2017 +0100 1.3 @@ -158,6 +158,12 @@ 1.4 void do_UnsafePutRaw (UnsafePutRaw* x) { kill_memory(); } 1.5 void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); } 1.6 void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { kill_memory(); } 1.7 + void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ } 1.8 + void do_UnsafeGetObject(UnsafeGetObject* x) { 1.9 + if (x->is_volatile()) { // the JMM requires this 1.10 + kill_memory(); 1.11 + } 1.12 + } 1.13 void do_Intrinsic (Intrinsic* x) { if (!x->preserves_state()) kill_memory(); } 1.14 1.15 void do_Phi (Phi* x) { /* nothing to do */ } 1.16 @@ -198,8 +204,6 @@ 1.17 void do_OsrEntry (OsrEntry* x) { /* nothing to do */ } 1.18 void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ } 1.19 void do_RoundFP (RoundFP* x) { /* nothing to do */ } 1.20 - void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ } 1.21 - void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ } 1.22 void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ } 1.23 void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ } 1.24 void do_ProfileCall (ProfileCall* x) { /* nothing to do */ }
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/compiler/c1/UnsafeVolatileGuardTest.java Wed Mar 08 14:22:52 2017 +0100 2.3 @@ -0,0 +1,72 @@ 2.4 +/* 2.5 + * Copyright (c) 2017, Red Hat Inc. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +import java.lang.reflect.Field; 2.28 + 2.29 +/** 2.30 + * @test 2.31 + * @bug 8175887 2.32 + * @summary C1 value numbering handling of Unsafe.get*Volatile is incorrect 2.33 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:TieredStopAtLevel=1 UnsafeVolatileGuardTest 2.34 + */ 2.35 +public class UnsafeVolatileGuardTest { 2.36 + volatile static private int a; 2.37 + static private int b; 2.38 + 2.39 + static final sun.misc.Unsafe UNSAFE; 2.40 + 2.41 + static final Object BASE; 2.42 + static final long OFFSET; 2.43 + 2.44 + static { 2.45 + try { 2.46 + Field uf = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); 2.47 + uf.setAccessible(true); 2.48 + UNSAFE = (sun.misc.Unsafe)uf.get(null); 2.49 + 2.50 + Field f = UnsafeVolatileGuardTest.class.getDeclaredField("a"); 2.51 + BASE = UNSAFE.staticFieldBase(f); 2.52 + OFFSET = UNSAFE.staticFieldOffset(f); 2.53 + } catch (Exception e) { 2.54 + throw new RuntimeException(e); 2.55 + } 2.56 + } 2.57 + 2.58 + static void test() { 2.59 + int tt = b; // makes the JVM CSE the value of b 2.60 + 2.61 + while (UNSAFE.getIntVolatile(BASE, OFFSET) == 0) {} // burn 2.62 + if (b == 0) { 2.63 + System.err.println("wrong value of b"); 2.64 + System.exit(1); // fail hard to report the error 2.65 + } 2.66 + } 2.67 + 2.68 + public static void main(String [] args) throws Exception { 2.69 + for (int i = 0; i < 10; i++) { 2.70 + new Thread(UnsafeVolatileGuardTest::test).start(); 2.71 + } 2.72 + b = 1; 2.73 + a = 1; 2.74 + } 2.75 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/compiler/c1/VolatileGuardTest.java Wed Mar 08 14:22:52 2017 +0100 3.3 @@ -0,0 +1,52 @@ 3.4 +/* 3.5 + * Copyright (c) 2017, Red Hat Inc. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +/** 3.28 + * @test 3.29 + * @bug 8175887 3.30 + * @summary C1 doesn't respect the JMM with volatile field loads 3.31 + * 3.32 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:TieredStopAtLevel=1 VolatileGuardTest 3.33 + */ 3.34 +public class VolatileGuardTest { 3.35 + volatile static private int a; 3.36 + static private int b; 3.37 + 3.38 + static void test() { 3.39 + int tt = b; // makes the JVM CSE the value of b 3.40 + 3.41 + while (a == 0) {} // burn 3.42 + if (b == 0) { 3.43 + System.err.println("wrong value of b"); 3.44 + System.exit(1); // fail hard to report the error 3.45 + } 3.46 + } 3.47 + 3.48 + public static void main(String [] args) throws Exception { 3.49 + for (int i = 0; i < 10; i++) { 3.50 + new Thread(VolatileGuardTest::test).start(); 3.51 + } 3.52 + b = 1; 3.53 + a = 1; 3.54 + } 3.55 +}