1/*
2 * Copyright (c) 2017, Red Hat, Inc. 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 * @bug 8179678
27 * @summary ArrayCopy with same src and dst can cause incorrect execution or compiler crash
28 *
29 * @run main/othervm -XX:CompileCommand=compileonly,TestACSameSrcDst::test* TestACSameSrcDst
30 *
31 */
32
33public class TestACSameSrcDst {
34
35    static int test1(int[] src, int[] dst) {
36        System.arraycopy(src, 5, dst, 0, 10);
37         // this shouldn't be transformed to src[5] because the copy
38         // can modify src[5] if src and dst are the same.
39        return dst[0];
40    }
41
42    static int test2(int[] src) {
43        System.arraycopy(src, 0, src, 0, 10);
44        // same source and destination. If load from destination is
45        // transformed to load of source, the compiler performs that
46        // optimization in an infinite loop.
47        return src[0];
48    }
49
50    static int test3() {
51        int[] src = new int[15];
52        src[5] = 0x42;
53        System.arraycopy(src, 5, src, 0, 10);
54        // That load can't bypass the arraycopy
55        return src[0];
56    }
57
58    static int test4() {
59        int[] src = new int[15];
60        System.arraycopy(src, 0, src, 5, 10);
61        return src[0];
62    }
63
64    // The dst[0] load can't bypass the arraycopy. After ArrayCopyNode
65    // is expanded, C2 looks for a stub call on the control paths of
66    // the array copy subgraph to decide whether the load's memory
67    // input can bypass the arraycopy. This test verifies the case of
68    // a source array that's not declared as an array.
69    static int test5(Object src, int l, boolean flag) {
70        int[] dst = new int[10];
71        if (flag) {
72            dst[0] = 0x42;
73            System.arraycopy(src, 0, dst, 0, l);
74            return dst[0];
75        }
76        return 0;
77    }
78
79    public static void main(String[] args) {
80        int[] array = new int[15];
81        for (int i = 0; i < 20000; i++) {
82            int res;
83            for (int j = 0; j < array.length; j++) {
84                array[j] = j;
85            }
86            int expected = array[5];
87            res = test1(array, array);
88            if (res != expected) {
89                throw new RuntimeException("bad result: " + res + " != " + expected);
90            }
91            test2(array);
92            res = test3();
93            if (res != 0x42) {
94                throw new RuntimeException("bad result: " + res + " != " + 0x42);
95            }
96            test4();
97            for (int j = 0; j < array.length; j++) {
98                array[j] = j;
99            }
100            res = test5(array, 10, (i%2) == 0);
101            if (res != 0) {
102                throw new RuntimeException("bad result: " + res + " != " + 0);
103            }
104        }
105    }
106}
107