hotspot/test/compiler/arraycopy/TestArrayCopyAsLoadsStores.java
changeset 29337 ef2be52deeaf
child 29345 e8f6ba59748f
equal deleted inserted replaced
29336:b287769dcff1 29337:ef2be52deeaf
       
     1 /*
       
     2  * Copyright (c) 2015, 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  * @bug 6912521
       
    27  * @summary small array copy as loads/stores
       
    28  * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:CompileCommand=dontinline,TestArrayCopyAsLoadsStores::m* -XX:TypeProfileLevel=200 TestArrayCopyAsLoadsStores
       
    29  * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:CompileCommand=dontinline,TestArrayCopyAsLoadsStores::m* -XX:+IgnoreUnrecognizedVMOptions -XX:+StressArrayCopyMacroNode -XX:TypeProfileLevel=200 TestArrayCopyAsLoadsStores
       
    30  *
       
    31  */
       
    32 
       
    33 import java.lang.annotation.*;
       
    34 import java.lang.reflect.*;
       
    35 import java.util.*;
       
    36 
       
    37 public class TestArrayCopyAsLoadsStores {
       
    38 
       
    39     public enum ArraySrc {
       
    40         SMALL,
       
    41         LARGE,
       
    42         ZERO
       
    43     }
       
    44 
       
    45     public enum ArrayDst {
       
    46         NONE,
       
    47         NEW,
       
    48         SRC
       
    49     }
       
    50 
       
    51     static class A {
       
    52     }
       
    53 
       
    54     static class B extends A {
       
    55     }
       
    56 
       
    57     static final A[] small_a_src = new A[5];
       
    58     static final A[] large_a_src = new A[10];
       
    59     static final A[] zero_a_src = new A[0];
       
    60     static final int[] small_int_src = new int[5];
       
    61     static final int[] large_int_src = new int[10];
       
    62     static final int[] zero_int_src = new int[0];
       
    63     static final Object[] small_object_src = new Object[5];
       
    64     static Object src;
       
    65 
       
    66     @Retention(RetentionPolicy.RUNTIME)
       
    67     @interface Args {
       
    68         ArraySrc src();
       
    69         ArrayDst dst() default ArrayDst.NONE;
       
    70         int[] extra_args() default {};
       
    71     }
       
    72 
       
    73     // array clone should be compiled as loads/stores
       
    74     @Args(src=ArraySrc.SMALL)
       
    75     static A[] m1() throws CloneNotSupportedException {
       
    76         return (A[])small_a_src.clone();
       
    77     }
       
    78 
       
    79     @Args(src=ArraySrc.SMALL)
       
    80     static int[] m2() throws CloneNotSupportedException {
       
    81         return (int[])small_int_src.clone();
       
    82     }
       
    83 
       
    84     // new array allocation should be optimized out
       
    85     @Args(src=ArraySrc.SMALL)
       
    86     static int m3() throws CloneNotSupportedException {
       
    87         int[] array_clone = (int[])small_int_src.clone();
       
    88         return array_clone[0] + array_clone[1] + array_clone[2] +
       
    89             array_clone[3] + array_clone[4];
       
    90     }
       
    91 
       
    92     // should not be compiled as loads/stores
       
    93     @Args(src=ArraySrc.LARGE)
       
    94     static int[] m4() throws CloneNotSupportedException {
       
    95         return (int[])large_int_src.clone();
       
    96     }
       
    97 
       
    98     // check that array of length 0 is handled correctly
       
    99     @Args(src=ArraySrc.ZERO)
       
   100     static int[] m5() throws CloneNotSupportedException {
       
   101         return (int[])zero_int_src.clone();
       
   102     }
       
   103 
       
   104     // array copy should be compiled as loads/stores
       
   105     @Args(src=ArraySrc.SMALL, dst=ArrayDst.NEW)
       
   106     static void m6(int[] src, int[] dest) {
       
   107         System.arraycopy(src, 0, dest, 0, 5);
       
   108     }
       
   109 
       
   110     // array copy should not be compiled as loads/stores
       
   111     @Args(src=ArraySrc.LARGE, dst=ArrayDst.NEW)
       
   112     static void m7(int[] src, int[] dest) {
       
   113         System.arraycopy(src, 0, dest, 0, 10);
       
   114     }
       
   115 
       
   116     // array copy should be compiled as loads/stores
       
   117     @Args(src=ArraySrc.SMALL)
       
   118     static A[] m8(A[] src) {
       
   119         src[0] = src[0]; // force null check
       
   120         A[] dest = new A[5];
       
   121         System.arraycopy(src, 0, dest, 0, 5);
       
   122         return dest;
       
   123     }
       
   124 
       
   125     // array copy should not be compiled as loads/stores: we would
       
   126     // need to emit GC barriers
       
   127     @Args(src=ArraySrc.SMALL, dst=ArrayDst.NEW)
       
   128     static void m9(A[] src, A[] dest) {
       
   129         System.arraycopy(src, 0, dest, 0, 5);
       
   130     }
       
   131 
       
   132     // overlapping array regions: copy backward
       
   133     @Args(src=ArraySrc.SMALL, dst=ArrayDst.SRC)
       
   134     static void m10(int[] src, int[] dest) {
       
   135         System.arraycopy(src, 0, dest, 1, 4);
       
   136     }
       
   137 
       
   138     static boolean m10_check(int[] src, int[] dest) {
       
   139         boolean failure = false;
       
   140         for (int i = 0; i < 5; i++) {
       
   141             int j = Math.max(i - 1, 0);
       
   142             if (dest[i] != src[j]) {
       
   143                 System.out.println("Test m10 failed for " + i + " src[" + j +"]=" + src[j] + ", dest[" + i + "]=" + dest[i]);
       
   144                 failure = true;
       
   145             }
       
   146         }
       
   147         return failure;
       
   148     }
       
   149 
       
   150     // overlapping array regions: copy forward
       
   151     @Args(src=ArraySrc.SMALL, dst=ArrayDst.SRC)
       
   152     static void m11(int[] src, int[] dest) {
       
   153         System.arraycopy(src, 1, dest, 0, 4);
       
   154     }
       
   155 
       
   156     static boolean m11_check(int[] src, int[] dest) {
       
   157         boolean failure = false;
       
   158         for (int i = 0; i < 5; i++) {
       
   159             int j = Math.min(i + 1, 4);
       
   160             if (dest[i] != src[j]) {
       
   161                 System.out.println("Test m11 failed for " + i + " src[" + j +"]=" + src[j] + ", dest[" + i + "]=" + dest[i]);
       
   162                 failure = true;
       
   163             }
       
   164         }
       
   165         return failure;
       
   166     }
       
   167 
       
   168     // overlapping array region with unknown src/dest offsets: compiled code must include both forward and backward copies
       
   169     @Args(src=ArraySrc.SMALL, dst=ArrayDst.SRC, extra_args={0,1})
       
   170     static void m12(int[] src, int[] dest, int srcPos, int destPos) {
       
   171         System.arraycopy(src, srcPos, dest, destPos, 4);
       
   172     }
       
   173 
       
   174     static boolean m12_check(int[] src, int[] dest) {
       
   175         boolean failure = false;
       
   176         for (int i = 0; i < 5; i++) {
       
   177             int j = Math.max(i - 1, 0);
       
   178             if (dest[i] != src[j]) {
       
   179                 System.out.println("Test m10 failed for " + i + " src[" + j +"]=" + src[j] + ", dest[" + i + "]=" + dest[i]);
       
   180                 failure = true;
       
   181             }
       
   182         }
       
   183         return failure;
       
   184     }
       
   185 
       
   186     // Array allocation and copy should optimize out
       
   187     @Args(src=ArraySrc.SMALL)
       
   188     static int m13(int[] src) {
       
   189         int[] dest = new int[5];
       
   190         System.arraycopy(src, 0, dest, 0, 5);
       
   191         return dest[0] + dest[1] + dest[2] + dest[3] + dest[4];
       
   192     }
       
   193 
       
   194     // Check that copy of length 0 is handled correctly
       
   195     @Args(src=ArraySrc.ZERO, dst=ArrayDst.NEW)
       
   196     static void m14(int[] src, int[] dest) {
       
   197         System.arraycopy(src, 0, dest, 0, 0);
       
   198     }
       
   199 
       
   200     // copyOf should compile to loads/stores
       
   201     @Args(src=ArraySrc.SMALL)
       
   202     static A[] m15() {
       
   203         return Arrays.copyOf(small_a_src, 5, A[].class);
       
   204     }
       
   205 
       
   206     static Object[] helper16(int i) {
       
   207         Object[] arr = null;
       
   208         if ((i%2) == 0) {
       
   209             arr = small_a_src;
       
   210         } else {
       
   211             arr = small_object_src;
       
   212         }
       
   213         return arr;
       
   214     }
       
   215 
       
   216     // CopyOf may need subtype check
       
   217     @Args(src=ArraySrc.SMALL, dst=ArrayDst.NONE, extra_args={0})
       
   218     static A[] m16(A[] unused_src, int i) {
       
   219         Object[] arr = helper16(i);
       
   220         return Arrays.copyOf(arr, 5, A[].class);
       
   221     }
       
   222 
       
   223     static Object[] helper17_1(int i) {
       
   224         Object[] arr = null;
       
   225         if ((i%2) == 0) {
       
   226             arr = small_a_src;
       
   227         } else {
       
   228             arr = small_object_src;
       
   229         }
       
   230         return arr;
       
   231     }
       
   232 
       
   233     static A[] helper17_2(Object[] arr) {
       
   234         return Arrays.copyOf(arr, 5, A[].class);
       
   235     }
       
   236 
       
   237     // CopyOf may leverage type speculation
       
   238     @Args(src=ArraySrc.SMALL, dst=ArrayDst.NONE, extra_args={0})
       
   239     static A[] m17(A[] unused_src, int i) {
       
   240         Object[] arr = helper17_1(i);
       
   241         return helper17_2(arr);
       
   242     }
       
   243 
       
   244     static Object[] helper18_1(int i) {
       
   245         Object[] arr = null;
       
   246         if ((i%2) == 0) {
       
   247             arr = small_a_src;
       
   248         } else {
       
   249             arr = small_object_src;
       
   250         }
       
   251         return arr;
       
   252     }
       
   253 
       
   254     static Object[] helper18_2(Object[] arr) {
       
   255         return Arrays.copyOf(arr, 5, Object[].class);
       
   256     }
       
   257 
       
   258     // CopyOf should not attempt to use type speculation if it's not needed
       
   259     @Args(src=ArraySrc.SMALL, dst=ArrayDst.NONE, extra_args={0})
       
   260     static Object[] m18(A[] unused_src, int i) {
       
   261         Object[] arr = helper18_1(i);
       
   262         return helper18_2(arr);
       
   263     }
       
   264 
       
   265     static Object[] helper19(int i) {
       
   266         Object[] arr = null;
       
   267         if ((i%2) == 0) {
       
   268             arr = small_a_src;
       
   269         } else {
       
   270             arr = small_object_src;
       
   271         }
       
   272         return arr;
       
   273     }
       
   274 
       
   275     // CopyOf may need subtype check. Test is run to make type check
       
   276     // fail and cause deoptimization. Next compilation should not
       
   277     // compile as loads/stores because the first compilation
       
   278     // deoptimized.
       
   279     @Args(src=ArraySrc.SMALL, dst=ArrayDst.NONE, extra_args={0})
       
   280     static A[] m19(A[] unused_src, int i) {
       
   281         Object[] arr = helper19(i);
       
   282         return Arrays.copyOf(arr, 5, A[].class);
       
   283     }
       
   284 
       
   285     // copyOf for large array should not compile to loads/stores
       
   286     @Args(src=ArraySrc.LARGE)
       
   287     static A[] m20() {
       
   288         return Arrays.copyOf(large_a_src, 10, A[].class);
       
   289     }
       
   290 
       
   291     // check zero length copyOf is handled correctly
       
   292     @Args(src=ArraySrc.ZERO)
       
   293     static A[] m21() {
       
   294         return Arrays.copyOf(zero_a_src, 0, A[].class);
       
   295     }
       
   296 
       
   297     // Run with srcPos=0 for a 1st compile, then with incorrect value
       
   298     // of srcPos to cause deoptimization, then with srcPos=0 for a 2nd
       
   299     // compile. The 2nd compile shouldn't turn arraycopy into
       
   300     // loads/stores because input arguments are no longer known to be
       
   301     // valid.
       
   302     @Args(src=ArraySrc.SMALL, dst=ArrayDst.NEW, extra_args={0})
       
   303     static void m22(int[] src, int[] dest, int srcPos) {
       
   304         System.arraycopy(src, srcPos, dest, 0, 5);
       
   305     }
       
   306 
       
   307     // copyOfRange should compile to loads/stores
       
   308     @Args(src=ArraySrc.SMALL)
       
   309     static A[] m23() {
       
   310         return Arrays.copyOfRange(small_a_src, 1, 4, A[].class);
       
   311     }
       
   312 
       
   313     static boolean m23_check(A[] src, A[] dest) {
       
   314         boolean failure = false;
       
   315         for (int i = 0; i < 3; i++) {
       
   316             if (src[i+1] != dest[i]) {
       
   317                 System.out.println("Test m23 failed for " + i + " src[" + (i+1) +"]=" + dest[i] + ", dest[" + i + "]=" + dest[i]);
       
   318                 failure = true;
       
   319             }
       
   320         }
       
   321         return failure;
       
   322     }
       
   323 
       
   324     // array copy should be compiled as loads/stores. Invoke then with
       
   325     // incompatible array type to verify we don't allow a forbidden
       
   326     // arraycopy to happen.
       
   327     @Args(src=ArraySrc.SMALL)
       
   328     static A[] m24(Object[] src) {
       
   329         src[0] = src[0]; // force null check
       
   330         A[] dest = new A[5];
       
   331         System.arraycopy(src, 0, dest, 0, 5);
       
   332         return dest;
       
   333     }
       
   334 
       
   335     // overlapping array region with unknown src/dest offsets but
       
   336     // length 1: compiled code doesn't need both forward and backward
       
   337     // copies
       
   338     @Args(src=ArraySrc.SMALL, dst=ArrayDst.SRC, extra_args={0,1})
       
   339     static void m25(int[] src, int[] dest, int srcPos, int destPos) {
       
   340         System.arraycopy(src, srcPos, dest, destPos, 1);
       
   341     }
       
   342 
       
   343     static boolean m25_check(int[] src, int[] dest) {
       
   344         boolean failure = false;
       
   345         if (dest[1] != src[0]) {
       
   346             System.out.println("Test m10 failed for src[0]=" + src[0] + ", dest[1]=" + dest[1]);
       
   347             return true;
       
   348         }
       
   349         return false;
       
   350     }
       
   351 
       
   352     final HashMap<String,Method> tests = new HashMap<>();
       
   353     {
       
   354         for (Method m : this.getClass().getDeclaredMethods()) {
       
   355             if (m.getName().matches("m[0-9]+(_check)?")) {
       
   356                 assert(Modifier.isStatic(m.getModifiers())) : m;
       
   357                 tests.put(m.getName(), m);
       
   358             }
       
   359         }
       
   360     }
       
   361 
       
   362     boolean success = true;
       
   363 
       
   364     void doTest(String name) throws Exception {
       
   365         Method m = tests.get(name);
       
   366         Method m_check = tests.get(name + "_check");
       
   367         Class[] paramTypes = m.getParameterTypes();
       
   368         Object[] params = new Object[paramTypes.length];
       
   369         Class retType = m.getReturnType();
       
   370         boolean isIntArray = (retType.isPrimitive() && !retType.equals(Void.TYPE)) ||
       
   371             (retType.equals(Void.TYPE) && paramTypes[0].getComponentType().isPrimitive()) ||
       
   372             (retType.isArray() && retType.getComponentType().isPrimitive());
       
   373 
       
   374         Args args = m.getAnnotation(Args.class);
       
   375 
       
   376         Object src = null;
       
   377         switch(args.src()) {
       
   378         case SMALL: {
       
   379             if (isIntArray) {
       
   380                 src = small_int_src;
       
   381             } else {
       
   382                 src = small_a_src;
       
   383             }
       
   384             break;
       
   385         }
       
   386         case LARGE: {
       
   387             if (isIntArray) {
       
   388                 src = large_int_src;
       
   389             } else {
       
   390                 src = large_a_src;
       
   391             }
       
   392             break;
       
   393         }
       
   394         case ZERO: {
       
   395             assert isIntArray;
       
   396             if (isIntArray) {
       
   397                 src = zero_int_src;
       
   398             } else {
       
   399                 src = zero_a_src;
       
   400             }
       
   401             break;
       
   402         }
       
   403         }
       
   404 
       
   405         for (int i = 0; i < 20000; i++) {
       
   406             boolean failure = false;
       
   407 
       
   408             int p = 0;
       
   409 
       
   410             if (params.length > 0) {
       
   411                 if (isIntArray) {
       
   412                     params[0] = ((int[])src).clone();
       
   413                 } else {
       
   414                     params[0] = ((A[])src).clone();
       
   415                 }
       
   416                 p++;
       
   417             }
       
   418 
       
   419             if (params.length > 1) {
       
   420                 switch(args.dst()) {
       
   421                 case NEW: {
       
   422                     if (isIntArray) {
       
   423                         params[1] = new int[((int[])params[0]).length];
       
   424                     } else {
       
   425                         params[1] = new A[((A[])params[0]).length];
       
   426                     }
       
   427                     p++;
       
   428                     break;
       
   429                 }
       
   430                 case SRC: {
       
   431                     params[1] = params[0];
       
   432                     p++;
       
   433                     break;
       
   434                 }
       
   435                 case NONE: break;
       
   436                 }
       
   437             }
       
   438 
       
   439             for (int j = 0; j < args.extra_args().length; j++) {
       
   440                 params[p+j] = args.extra_args()[j];
       
   441             }
       
   442 
       
   443             Object res = m.invoke(null, params);
       
   444 
       
   445             if (retType.isPrimitive() && !retType.equals(Void.TYPE)) {
       
   446                 int s = (int)res;
       
   447                 int sum = 0;
       
   448                 int[] int_res = (int[])src;
       
   449                 for (int j = 0; j < int_res.length; j++) {
       
   450                     sum += int_res[j];
       
   451                 }
       
   452                 failure = (s != sum);
       
   453                 if (failure) {
       
   454                     System.out.println("Test " + name + " failed: result = " + s + " != " + sum);
       
   455                 }
       
   456             } else {
       
   457                 Object dest = null;
       
   458                 if (!retType.equals(Void.TYPE)) {
       
   459                     dest = res;
       
   460                 } else {
       
   461                     dest = params[1];
       
   462                 }
       
   463 
       
   464                 if (m_check != null) {
       
   465                     failure = (boolean)m_check.invoke(null,  new Object[] { src, dest });
       
   466                 } else {
       
   467                     if (isIntArray) {
       
   468                         int[] int_res = (int[])src;
       
   469                         int[] int_dest = (int[])dest;
       
   470                         for (int j = 0; j < int_res.length; j++) {
       
   471                             if (int_res[j] != int_dest[j]) {
       
   472                                 System.out.println("Test " + name + " failed for " + j + " src[" + j +"]=" + int_res[j] + ", dest[" + j + "]=" + int_dest[j]);
       
   473                                 failure = true;
       
   474                             }
       
   475                         }
       
   476                     } else {
       
   477                         Object[] object_res = (Object[])src;
       
   478                         Object[] object_dest = (Object[])dest;
       
   479                         for (int j = 0; j < object_res.length; j++) {
       
   480                             if (object_res[j] != object_dest[j]) {
       
   481                                 System.out.println("Test " + name + " failed for " + j + " src[" + j +"]=" + object_res[j] + ", dest[" + j + "]=" + object_dest[j]);
       
   482                                 failure = true;
       
   483                             }
       
   484                         }
       
   485                     }
       
   486                 }
       
   487             }
       
   488 
       
   489             if (failure) {
       
   490                 success = false;
       
   491                 break;
       
   492             }
       
   493         }
       
   494     }
       
   495 
       
   496     public static void main(String[] args) throws Exception {
       
   497         for (int i = 0; i < small_a_src.length; i++) {
       
   498             small_a_src[i] = new A();
       
   499         }
       
   500 
       
   501         for (int i = 0; i < small_int_src.length; i++) {
       
   502             small_int_src[i] = i;
       
   503         }
       
   504 
       
   505         for (int i = 0; i < large_int_src.length; i++) {
       
   506             large_int_src[i] = i;
       
   507         }
       
   508 
       
   509         for (int i = 0; i < 5; i++) {
       
   510             small_object_src[i] = new Object();
       
   511         }
       
   512 
       
   513         TestArrayCopyAsLoadsStores test = new TestArrayCopyAsLoadsStores();
       
   514 
       
   515         test.doTest("m1");
       
   516         test.doTest("m2");
       
   517         test.doTest("m3");
       
   518         test.doTest("m4");
       
   519         test.doTest("m5");
       
   520         test.doTest("m6");
       
   521         test.doTest("m7");
       
   522         test.doTest("m8");
       
   523         test.doTest("m9");
       
   524         test.doTest("m10");
       
   525         test.doTest("m11");
       
   526         test.doTest("m12");
       
   527         test.doTest("m13");
       
   528         test.doTest("m14");
       
   529         test.doTest("m15");
       
   530 
       
   531         // make both branches of the If appear taken
       
   532         for (int i = 0; i < 20000; i++) {
       
   533             helper16(i);
       
   534         }
       
   535 
       
   536         test.doTest("m16");
       
   537 
       
   538         // load class B so type check in m17 would not be simple comparison
       
   539         B b = new B();
       
   540         // make both branches of the If appear taken
       
   541         for (int i = 0; i < 20000; i++) {
       
   542             helper17_1(i);
       
   543         }
       
   544 
       
   545         test.doTest("m17");
       
   546 
       
   547         // make both branches of the If appear taken
       
   548         for (int i = 0; i < 20000; i++) {
       
   549             helper18_1(i);
       
   550         }
       
   551         test.doTest("m18");
       
   552 
       
   553         // make both branches of the If appear taken
       
   554         for (int i = 0; i < 20000; i++) {
       
   555             helper19(i);
       
   556         }
       
   557 
       
   558         // Compile
       
   559         for (int i = 0; i < 20000; i++) {
       
   560             m19(null, 0);
       
   561         }
       
   562 
       
   563         // force deopt
       
   564         boolean m19_exception = false;
       
   565         for (int i = 0; i < 10; i++) {
       
   566             try {
       
   567                 m19(null, 1);
       
   568             } catch(ArrayStoreException ase) {
       
   569                 m19_exception = true;
       
   570             }
       
   571         }
       
   572 
       
   573         if (!m19_exception) {
       
   574             System.out.println("Test m19: exception wasn't thrown");
       
   575             test.success = false;
       
   576         }
       
   577 
       
   578         test.doTest("m19");
       
   579 
       
   580         test.doTest("m20");
       
   581         test.doTest("m21");
       
   582 
       
   583         // Compile
       
   584         int[] dst = new int[small_int_src.length];
       
   585         for (int i = 0; i < 20000; i++) {
       
   586             m22(small_int_src, dst, 0);
       
   587         }
       
   588 
       
   589         // force deopt
       
   590         for (int i = 0; i < 10; i++) {
       
   591             try {
       
   592                 m22(small_int_src, dst, 5);
       
   593             } catch(ArrayIndexOutOfBoundsException aioobe) {}
       
   594         }
       
   595 
       
   596         test.doTest("m22");
       
   597         test.doTest("m23");
       
   598 
       
   599         test.doTest("m24");
       
   600         boolean m24_exception = false;
       
   601         try {
       
   602             m24(small_object_src);
       
   603         } catch(ArrayStoreException ase) {
       
   604             m24_exception = true;
       
   605         }
       
   606 
       
   607         if (!m24_exception) {
       
   608             System.out.println("Test m24: exception wasn't thrown");
       
   609             test.success = false;
       
   610         }
       
   611 
       
   612         test.doTest("m25");
       
   613 
       
   614         if (!test.success) {
       
   615             throw new RuntimeException("some tests failed");
       
   616         }
       
   617     }
       
   618 }