8175887: C1 value numbering handling of Unsafe.get*Volatile is incorrect

Wed, 08 Mar 2017 14:22:52 +0100

author
shade
date
Wed, 08 Mar 2017 14:22:52 +0100
changeset 8722
0e53cdb9fc2a
parent 8721
575f637864df
child 8723
9f5da1a1724c

8175887: C1 value numbering handling of Unsafe.get*Volatile is incorrect
Reviewed-by: vlivanov

src/share/vm/c1/c1_ValueMap.hpp file | annotate | diff | comparison | revisions
test/compiler/c1/UnsafeVolatileGuardTest.java file | annotate | diff | comparison | revisions
test/compiler/c1/VolatileGuardTest.java file | annotate | diff | comparison | revisions
     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 +}

mercurial