1 /*
2  * Copyright (c) 2012, 2018, 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 package org.graalvm.compiler.replacements.test;
26 
27 import java.lang.reflect.Array;
28 import java.lang.reflect.InvocationTargetException;
29 import java.util.List;
30 
31 import org.junit.Test;
32 
33 import org.graalvm.compiler.core.test.GraalCompilerTest;
34 import org.graalvm.compiler.nodes.ConstantNode;
35 import org.graalvm.compiler.nodes.StructuredGraph;
36 import org.graalvm.compiler.nodes.ValueNode;
37 import org.graalvm.compiler.nodes.java.NewMultiArrayNode;
38 import org.graalvm.compiler.options.OptionValues;
39 
40 import jdk.vm.ci.code.InstalledCode;
41 import jdk.vm.ci.meta.ResolvedJavaMethod;
42 import jdk.vm.ci.meta.ResolvedJavaType;
43 
44 /**
45  * Tests the lowering of the MULTIANEWARRAY instruction.
46  */
47 public class NewMultiArrayTest extends GraalCompilerTest {
48 
rank(ResolvedJavaType type)49     private static int rank(ResolvedJavaType type) {
50         String name = type.getName();
51         int dims = 0;
52         while (dims < name.length() && name.charAt(dims) == '[') {
53             dims++;
54         }
55         return dims;
56     }
57 
58     @Override
getCode(ResolvedJavaMethod method, StructuredGraph g, boolean ignore, boolean installAsDefault, OptionValues options)59     protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph g, boolean ignore, boolean installAsDefault, OptionValues options) {
60         StructuredGraph graph = g == null ? parseForCompile(method, options) : g;
61         boolean forceCompile = false;
62         if (bottomType != null) {
63             List<NewMultiArrayNode> snapshot = graph.getNodes().filter(NewMultiArrayNode.class).snapshot();
64             assert snapshot != null;
65             assert snapshot.size() == 1;
66 
67             NewMultiArrayNode node = snapshot.get(0);
68             assert rank(arrayType) == dimensions.length;
69             int rank = dimensions.length;
70             ValueNode[] dimensionNodes = new ValueNode[rank];
71             for (int i = 0; i < rank; i++) {
72                 dimensionNodes[i] = ConstantNode.forInt(dimensions[i], graph);
73             }
74 
75             NewMultiArrayNode repl = graph.add(new NewMultiArrayNode(arrayType, dimensionNodes));
76             graph.replaceFixedWithFixed(node, repl);
77             forceCompile = true;
78         }
79         return super.getCode(method, graph, forceCompile, installAsDefault, options);
80     }
81 
82     @Override
referenceInvoke(ResolvedJavaMethod method, Object receiver, Object... args)83     protected Object referenceInvoke(ResolvedJavaMethod method, Object receiver, Object... args)
84                     throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
85         if (bottomType != null) {
86             try {
87                 return Array.newInstance(bottomClass, dimensions);
88             } catch (Exception e) {
89                 throw new InvocationTargetException(e);
90             }
91         }
92         return super.referenceInvoke(method, receiver, args);
93     }
94 
95     ResolvedJavaType arrayType;
96     ResolvedJavaType bottomType;
97     Class<?> bottomClass;
98     int[] dimensions;
99 
100     @Test
test1()101     public void test1() {
102         for (Class<?> clazz : new Class<?>[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) {
103             bottomClass = clazz;
104             bottomType = getMetaAccess().lookupJavaType(clazz);
105             arrayType = bottomType;
106             for (int rank : new int[]{1, 2, 10, 50, 100, 200, 254, 255}) {
107                 while (rank(arrayType) != rank) {
108                     arrayType = arrayType.getArrayClass();
109                 }
110 
111                 dimensions = new int[rank];
112                 for (int i = 0; i < rank; i++) {
113                     dimensions[i] = 1;
114                 }
115 
116                 test("newMultiArray");
117             }
118         }
119         bottomType = null;
120         arrayType = null;
121     }
122 
newMultiArray()123     public static Object newMultiArray() {
124         // This is merely a template - the NewMultiArrayNode is replaced in getCode() above.
125         // This also means we need a separate test for correct handling of negative dimensions
126         // as deoptimization won't do what we want for a graph modified to be different from the
127         // source bytecode.
128         return new Object[10][9][8];
129     }
130 
131     @Test
test2()132     public void test2() {
133         test("newMultiArrayException");
134     }
135 
newMultiArrayException()136     public static Object newMultiArrayException() {
137         return new Object[10][9][-8];
138     }
139 }
140