Path: blob/master/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyAsLoadsStores.java
64474 views
/*1* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 691252126* @summary small array copy as loads/stores27* @library /28*29* @run main/othervm -ea -XX:-BackgroundCompilation -XX:-UseOnStackReplacement30* -XX:CompileCommand=dontinline,compiler.arraycopy.TestArrayCopyAsLoadsStores::m*31* -XX:TypeProfileLevel=20032* compiler.arraycopy.TestArrayCopyAsLoadsStores33* @run main/othervm -ea -XX:-BackgroundCompilation -XX:-UseOnStackReplacement34* -XX:CompileCommand=dontinline,compiler.arraycopy.TestArrayCopyAsLoadsStores::m*35* -XX:TypeProfileLevel=20036* -XX:+IgnoreUnrecognizedVMOptions -XX:+StressArrayCopyMacroNode37* compiler.arraycopy.TestArrayCopyAsLoadsStores38*/3940/*41* @test42* @bug 828259043* @library /44*45* @run main/othervm -ea -XX:-BackgroundCompilation -XX:-UseOnStackReplacement46* -XX:CompileCommand=dontinline,compiler.arraycopy.TestArrayCopyAsLoadsStores::m*47* -XX:TypeProfileLevel=20048* -XX:+IgnoreUnrecognizedVMOptions -XX:+StressArrayCopyMacroNode49* -XX:-TieredCompilation -XX:+StressReflectiveCode -XX:-ReduceInitialCardMarks50* compiler.arraycopy.TestArrayCopyAsLoadsStores51*/5253package compiler.arraycopy;5455import java.util.Arrays;5657public class TestArrayCopyAsLoadsStores extends TestArrayCopyUtils {5859// array clone should be compiled as loads/stores60@Args(src=ArraySrc.SMALL)61static A[] m1() throws CloneNotSupportedException {62return (A[])small_a_src.clone();63}6465@Args(src=ArraySrc.SMALL)66static int[] m2() throws CloneNotSupportedException {67return (int[])small_int_src.clone();68}6970// new array allocation should be optimized out71@Args(src=ArraySrc.SMALL)72static int m3() throws CloneNotSupportedException {73int[] array_clone = (int[])small_int_src.clone();74return array_clone[0] + array_clone[1] + array_clone[2] +75array_clone[3] + array_clone[4];76}7778// should not be compiled as loads/stores79@Args(src=ArraySrc.LARGE)80static int[] m4() throws CloneNotSupportedException {81return (int[])large_int_src.clone();82}8384// check that array of length 0 is handled correctly85@Args(src=ArraySrc.ZERO)86static int[] m5() throws CloneNotSupportedException {87return (int[])zero_int_src.clone();88}8990// array copy should be compiled as loads/stores91@Args(src=ArraySrc.SMALL, dst=ArrayDst.NEW)92static void m6(int[] src, int[] dest) {93System.arraycopy(src, 0, dest, 0, 5);94}9596// array copy should not be compiled as loads/stores97@Args(src=ArraySrc.LARGE, dst=ArrayDst.NEW)98static void m7(int[] src, int[] dest) {99System.arraycopy(src, 0, dest, 0, 10);100}101102// array copy should be compiled as loads/stores103@Args(src=ArraySrc.SMALL)104static A[] m8(A[] src) {105src[0] = src[0]; // force null check106A[] dest = new A[5];107System.arraycopy(src, 0, dest, 0, 5);108return dest;109}110111// array copy should not be compiled as loads/stores: we would112// need to emit GC barriers113@Args(src=ArraySrc.SMALL, dst=ArrayDst.NEW)114static void m9(A[] src, A[] dest) {115System.arraycopy(src, 0, dest, 0, 5);116}117118// overlapping array regions: copy backward119@Args(src=ArraySrc.SMALL, dst=ArrayDst.SRC)120static void m10(int[] src, int[] dest) {121System.arraycopy(src, 0, dest, 1, 4);122}123124static boolean m10_check(int[] src, int[] dest) {125boolean failure = false;126for (int i = 0; i < 5; i++) {127int j = Math.max(i - 1, 0);128if (dest[i] != src[j]) {129System.out.println("Test m10 failed for " + i + " src[" + j +"]=" + src[j] + ", dest[" + i + "]=" + dest[i]);130failure = true;131}132}133return failure;134}135136// overlapping array regions: copy forward137@Args(src=ArraySrc.SMALL, dst=ArrayDst.SRC)138static void m11(int[] src, int[] dest) {139System.arraycopy(src, 1, dest, 0, 4);140}141142static boolean m11_check(int[] src, int[] dest) {143boolean failure = false;144for (int i = 0; i < 5; i++) {145int j = Math.min(i + 1, 4);146if (dest[i] != src[j]) {147System.out.println("Test m11 failed for " + i + " src[" + j +"]=" + src[j] + ", dest[" + i + "]=" + dest[i]);148failure = true;149}150}151return failure;152}153154// overlapping array region with unknown src/dest offsets: compiled code must include both forward and backward copies155@Args(src=ArraySrc.SMALL, dst=ArrayDst.SRC, extra_args={0,1})156static void m12(int[] src, int[] dest, int srcPos, int destPos) {157System.arraycopy(src, srcPos, dest, destPos, 4);158}159160static boolean m12_check(int[] src, int[] dest) {161boolean failure = false;162for (int i = 0; i < 5; i++) {163int j = Math.max(i - 1, 0);164if (dest[i] != src[j]) {165System.out.println("Test m10 failed for " + i + " src[" + j +"]=" + src[j] + ", dest[" + i + "]=" + dest[i]);166failure = true;167}168}169return failure;170}171172// Array allocation and copy should optimize out173@Args(src=ArraySrc.SMALL)174static int m13(int[] src) {175int[] dest = new int[5];176System.arraycopy(src, 0, dest, 0, 5);177return dest[0] + dest[1] + dest[2] + dest[3] + dest[4];178}179180// Check that copy of length 0 is handled correctly181@Args(src=ArraySrc.ZERO, dst=ArrayDst.NEW)182static void m14(int[] src, int[] dest) {183System.arraycopy(src, 0, dest, 0, 0);184}185186// copyOf should compile to loads/stores187@Args(src=ArraySrc.SMALL)188static A[] m15() {189return Arrays.copyOf(small_a_src, 5, A[].class);190}191192static Object[] helper16(int i) {193Object[] arr = null;194if ((i%2) == 0) {195arr = small_a_src;196} else {197arr = small_object_src;198}199return arr;200}201202// CopyOf may need subtype check203@Args(src=ArraySrc.SMALL, dst=ArrayDst.NONE, extra_args={0})204static A[] m16(A[] unused_src, int i) {205Object[] arr = helper16(i);206return Arrays.copyOf(arr, 5, A[].class);207}208209static Object[] helper17_1(int i) {210Object[] arr = null;211if ((i%2) == 0) {212arr = small_a_src;213} else {214arr = small_object_src;215}216return arr;217}218219static A[] helper17_2(Object[] arr) {220return Arrays.copyOf(arr, 5, A[].class);221}222223// CopyOf may leverage type speculation224@Args(src=ArraySrc.SMALL, dst=ArrayDst.NONE, extra_args={0})225static A[] m17(A[] unused_src, int i) {226Object[] arr = helper17_1(i);227return helper17_2(arr);228}229230static Object[] helper18_1(int i) {231Object[] arr = null;232if ((i%2) == 0) {233arr = small_a_src;234} else {235arr = small_object_src;236}237return arr;238}239240static Object[] helper18_2(Object[] arr) {241return Arrays.copyOf(arr, 5, Object[].class);242}243244// CopyOf should not attempt to use type speculation if it's not needed245@Args(src=ArraySrc.SMALL, dst=ArrayDst.NONE, extra_args={0})246static Object[] m18(A[] unused_src, int i) {247Object[] arr = helper18_1(i);248return helper18_2(arr);249}250251static Object[] helper19(int i) {252Object[] arr = null;253if ((i%2) == 0) {254arr = small_a_src;255} else {256arr = small_object_src;257}258return arr;259}260261// CopyOf may need subtype check. Test is run to make type check262// fail and cause deoptimization. Next compilation should not263// compile as loads/stores because the first compilation264// deoptimized.265@Args(src=ArraySrc.SMALL, dst=ArrayDst.NONE, extra_args={0})266static A[] m19(A[] unused_src, int i) {267Object[] arr = helper19(i);268return Arrays.copyOf(arr, 5, A[].class);269}270271// copyOf for large array should not compile to loads/stores272@Args(src=ArraySrc.LARGE)273static A[] m20() {274return Arrays.copyOf(large_a_src, 10, A[].class);275}276277// check zero length copyOf is handled correctly278@Args(src=ArraySrc.ZERO)279static A[] m21() {280return Arrays.copyOf(zero_a_src, 0, A[].class);281}282283// Run with srcPos=0 for a 1st compile, then with incorrect value284// of srcPos to cause deoptimization, then with srcPos=0 for a 2nd285// compile. The 2nd compile shouldn't turn arraycopy into286// loads/stores because input arguments are no longer known to be287// valid.288@Args(src=ArraySrc.SMALL, dst=ArrayDst.NEW, extra_args={0})289static void m22(int[] src, int[] dest, int srcPos) {290System.arraycopy(src, srcPos, dest, 0, 5);291}292293// copyOfRange should compile to loads/stores294@Args(src=ArraySrc.SMALL)295static A[] m23() {296return Arrays.copyOfRange(small_a_src, 1, 4, A[].class);297}298299static boolean m23_check(A[] src, A[] dest) {300boolean failure = false;301for (int i = 0; i < 3; i++) {302if (src[i+1] != dest[i]) {303System.out.println("Test m23 failed for " + i + " src[" + (i+1) +"]=" + dest[i] + ", dest[" + i + "]=" + dest[i]);304failure = true;305}306}307return failure;308}309310// array copy should be compiled as loads/stores. Invoke then with311// incompatible array type to verify we don't allow a forbidden312// arraycopy to happen.313@Args(src=ArraySrc.SMALL)314static A[] m24(Object[] src) {315src[0] = src[0]; // force null check316A[] dest = new A[5];317System.arraycopy(src, 0, dest, 0, 5);318return dest;319}320321// overlapping array region with unknown src/dest offsets but322// length 1: compiled code doesn't need both forward and backward323// copies324@Args(src=ArraySrc.SMALL, dst=ArrayDst.SRC, extra_args={0,1})325static void m25(int[] src, int[] dest, int srcPos, int destPos) {326System.arraycopy(src, srcPos, dest, destPos, 1);327}328329static boolean m25_check(int[] src, int[] dest) {330boolean failure = false;331if (dest[1] != src[0]) {332System.out.println("Test m10 failed for src[0]=" + src[0] + ", dest[1]=" + dest[1]);333return true;334}335return false;336}337338public static void main(String[] args) throws Exception {339TestArrayCopyAsLoadsStores test = new TestArrayCopyAsLoadsStores();340341test.doTest("m1");342test.doTest("m2");343test.doTest("m3");344test.doTest("m4");345test.doTest("m5");346test.doTest("m6");347test.doTest("m7");348test.doTest("m8");349test.doTest("m9");350test.doTest("m10");351test.doTest("m11");352test.doTest("m12");353test.doTest("m13");354test.doTest("m14");355test.doTest("m15");356357// make both branches of the If appear taken358for (int i = 0; i < 20000; i++) {359helper16(i);360}361362test.doTest("m16");363364// load class B so type check in m17 would not be simple comparison365B b = new B();366// make both branches of the If appear taken367for (int i = 0; i < 20000; i++) {368helper17_1(i);369}370371test.doTest("m17");372373// make both branches of the If appear taken374for (int i = 0; i < 20000; i++) {375helper18_1(i);376}377test.doTest("m18");378379// make both branches of the If appear taken380for (int i = 0; i < 20000; i++) {381helper19(i);382}383384// Compile385for (int i = 0; i < 20000; i++) {386m19(null, 0);387}388389// force deopt390boolean m19_exception = false;391for (int i = 0; i < 10; i++) {392try {393m19(null, 1);394} catch(ArrayStoreException ase) {395m19_exception = true;396}397}398399if (!m19_exception) {400System.out.println("Test m19: exception wasn't thrown");401test.success = false;402}403404test.doTest("m19");405406test.doTest("m20");407test.doTest("m21");408409// Compile410int[] dst = new int[small_int_src.length];411for (int i = 0; i < 20000; i++) {412m22(small_int_src, dst, 0);413}414415// force deopt416for (int i = 0; i < 10; i++) {417try {418m22(small_int_src, dst, 5);419} catch(ArrayIndexOutOfBoundsException aioobe) {}420}421422test.doTest("m22");423test.doTest("m23");424425test.doTest("m24");426boolean m24_exception = false;427try {428m24(small_object_src);429} catch(ArrayStoreException ase) {430m24_exception = true;431}432433if (!m24_exception) {434System.out.println("Test m24: exception wasn't thrown");435test.success = false;436}437438test.doTest("m25");439440if (!test.success) {441throw new RuntimeException("some tests failed");442}443}444}445446447