001/*
002 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.replacements.test;
024
025import java.lang.reflect.*;
026import java.util.*;
027
028import jdk.internal.jvmci.code.*;
029import jdk.internal.jvmci.meta.*;
030
031import org.junit.*;
032
033import com.oracle.graal.compiler.test.*;
034import com.oracle.graal.nodes.*;
035import com.oracle.graal.nodes.java.*;
036
037/**
038 * Tests the lowering of the MULTIANEWARRAY instruction.
039 */
040public class NewMultiArrayTest extends GraalCompilerTest {
041
042    private static int rank(ResolvedJavaType type) {
043        String name = type.getName();
044        int dims = 0;
045        while (dims < name.length() && name.charAt(dims) == '[') {
046            dims++;
047        }
048        return dims;
049    }
050
051    @Override
052    protected InstalledCode getCode(final ResolvedJavaMethod method, StructuredGraph g) {
053        StructuredGraph graph = g == null ? parseForCompile(method) : g;
054        boolean forceCompile = false;
055        if (bottomType != null) {
056            List<NewMultiArrayNode> snapshot = graph.getNodes().filter(NewMultiArrayNode.class).snapshot();
057            assert snapshot != null;
058            assert snapshot.size() == 1;
059
060            NewMultiArrayNode node = snapshot.get(0);
061            assert rank(arrayType) == dimensions.length;
062            int rank = dimensions.length;
063            ValueNode[] dimensionNodes = new ValueNode[rank];
064            for (int i = 0; i < rank; i++) {
065                dimensionNodes[i] = ConstantNode.forInt(dimensions[i], graph);
066            }
067
068            NewMultiArrayNode repl = graph.add(new NewMultiArrayNode(arrayType, dimensionNodes));
069            graph.replaceFixedWithFixed(node, repl);
070            forceCompile = true;
071        }
072        return super.getCode(method, graph, forceCompile);
073    }
074
075    @Override
076    protected Object referenceInvoke(ResolvedJavaMethod method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
077        if (bottomType != null) {
078            try {
079                return Array.newInstance(bottomClass, dimensions);
080            } catch (Exception e) {
081                throw new InvocationTargetException(e);
082            }
083        }
084        return super.referenceInvoke(method, receiver, args);
085    }
086
087    ResolvedJavaType arrayType;
088    ResolvedJavaType bottomType;
089    Class<?> bottomClass;
090    int[] dimensions;
091
092    @Test
093    public void test1() {
094        for (Class<?> clazz : new Class[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) {
095            bottomClass = clazz;
096            bottomType = getMetaAccess().lookupJavaType(clazz);
097            arrayType = bottomType;
098            for (int rank : new int[]{1, 2, 10, 50, 100, 200, 254, 255}) {
099                while (rank(arrayType) != rank) {
100                    arrayType = arrayType.getArrayClass();
101                }
102
103                dimensions = new int[rank];
104                for (int i = 0; i < rank; i++) {
105                    dimensions[i] = 1;
106                }
107
108                test("newMultiArray");
109            }
110        }
111        bottomType = null;
112        arrayType = null;
113    }
114
115    public static Object newMultiArray() {
116        // This is merely a template - the NewMultiArrayNode is replaced in getCode() above.
117        // This also means we need a separate test for correct handling of negative dimensions
118        // as deoptimization won't do what we want for a graph modified to be different from the
119        // source bytecode.
120        return new Object[10][9][8];
121    }
122
123    @Test
124    public void test2() {
125        test("newMultiArrayException");
126    }
127
128    public static Object newMultiArrayException() {
129        return new Object[10][9][-8];
130    }
131}