1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @requires vm.gc.Z & !vm.graal.enabled 27 * @bug 8237859 28 * @summary A LoadP node has a wrong control input (too early) which results in an out-of-bounds read of an object array with ZGC. 29 * 30 * @run main/othervm -XX:+UseZGC compiler.loopopts.TestRangeCheckPredicatesControl 31 * @run main/othervm -XX:+UseZGC -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM compiler.loopopts.TestRangeCheckPredicatesControl 32 */ 33 34 package compiler.loopopts; 35 36 public class TestRangeCheckPredicatesControl { 37 static Wrapper w1 = new Wrapper(); 38 static Wrapper w2 = new Wrapper(); 39 static Wrapper w3 = new Wrapper(); 40 41 public static void main(String[] args) { 42 for (int x = 0; x < 10000000; x++) { 43 test(x % 2 == 0); 44 test2(x % 2 == 0, x % 3 == 0); 45 test3(x % 2 == 0); 46 test4(x % 2 == 0); 47 } 48 } 49 50 private static class Wrapper { 51 long longs; 52 int a; 53 public void maybeMaskBits(boolean b) { 54 if (b) { 55 longs &= 0x1F1F1F1F; 56 } 57 } 58 59 public void maybeMaskBits2(boolean b, boolean c) { 60 if (b) { 61 longs &= 0x1F1F1F1F; 62 } 63 if (c) { 64 a += 344; 65 } 66 } 67 } 68 69 private static void test(boolean flag) { 70 Wrapper[] wrappers_array; 71 if (flag) { 72 wrappers_array = new Wrapper[] {w1, w2}; 73 } else { 74 wrappers_array = new Wrapper[] {w1, w2, w3}; 75 } 76 77 // This loop is first unswitched and then pre/main/post loops are created for both unswitched loops. 78 // Both loops are unrolled once (two iterations in main loop, one in pre loop). As a result, the main 79 // loop contains an access of wrappers_array[1] and wrappers_array[2]. If 'flag' is false, then the 80 // main loop is not entered. But the load for wrappers_array[2] is wrongly scheduled before deciding 81 // if the main loop is executed or not due to a wrong control input of the corresponding LoadP node. 82 // The LoadP node still has a control input from a loop predicate of the original loop to be unswitched. 83 // As a consequence, the access wrappers_array[2] is executed regardless of the value of 'flag' resulting 84 // in a segfault. This fix addresses the problem of not updating the control inputs for data nodes 85 // from a predicate before the pre loop to the main and post loop. The fix for JDK-8240227 updates the 86 // control dependencies to predicates of the original loop to be unswitched to newly cloned predicates 87 // of the unswitched loops. 88 for (int i = 0; i < wrappers_array.length; i++) { 89 wrappers_array[i].maybeMaskBits(flag); 90 } 91 } 92 93 // This test unswitches two times 94 private static void test2(boolean flag, boolean flag2) { 95 Wrapper[] wrappers_array; 96 Wrapper[] wrappers_array2; 97 if (flag) { 98 wrappers_array = new Wrapper[] {w1, w2}; 99 wrappers_array2 = new Wrapper[] {w1, w2}; 100 } else { 101 wrappers_array = new Wrapper[] {w1, w2, w3}; 102 wrappers_array2 = new Wrapper[] {w1, w2, w3}; 103 } 104 105 for (int i = 0; i < wrappers_array.length; i++) { 106 wrappers_array[i].maybeMaskBits(flag); 107 wrappers_array2[i].maybeMaskBits2(flag, flag2); 108 } 109 } 110 111 // Test without unswitching but wrong control dependencies for data nodes to predicates before the pre loop. 112 // There is no update for the data nodes belonging to main and post loop after pre/main/post loops are created. 113 private static void test3(boolean flag) { 114 Wrapper[] wrappers_array; 115 if (flag) { 116 wrappers_array = new Wrapper[] {w1, w2}; 117 } else { 118 wrappers_array = new Wrapper[] {w1, w2, w3}; 119 } 120 121 for (int i = 0; i < wrappers_array.length; i++) { 122 wrappers_array[i].longs &= 0x1F1F1F1F; 123 } 124 } 125 126 private static void test4(boolean flag) { 127 Wrapper[] wrappers_array; 128 Wrapper[] wrappers_array2; 129 if (flag) { 130 wrappers_array = new Wrapper[] {w1, w2}; 131 wrappers_array2 = new Wrapper[] {w1, w2}; 132 } else { 133 wrappers_array = new Wrapper[] {w1, w2, w3}; 134 wrappers_array2 = new Wrapper[] {w1, w2, w3}; 135 } 136 137 for (int i = 0; i < wrappers_array.length; i++) { 138 wrappers_array[i].longs &= 0x1F1F1F1F; 139 wrappers_array2[i].longs &= 0x1F1F1F1F; 140 } 141 } 142 }