1 /*
2  * Copyright (c) 2009, 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.nodes.java;
26 
27 import java.util.Collections;
28 
29 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
30 import org.graalvm.compiler.core.common.type.IntegerStamp;
31 import org.graalvm.compiler.core.common.type.Stamp;
32 import org.graalvm.compiler.core.common.type.StampFactory;
33 import org.graalvm.compiler.core.common.type.TypeReference;
34 import org.graalvm.compiler.debug.DebugCloseable;
35 import org.graalvm.compiler.graph.NodeClass;
36 import org.graalvm.compiler.graph.spi.Simplifiable;
37 import org.graalvm.compiler.graph.spi.SimplifierTool;
38 import org.graalvm.compiler.nodeinfo.NodeInfo;
39 import org.graalvm.compiler.nodes.ConstantNode;
40 import org.graalvm.compiler.nodes.FixedGuardNode;
41 import org.graalvm.compiler.nodes.FrameState;
42 import org.graalvm.compiler.nodes.LogicNode;
43 import org.graalvm.compiler.nodes.NodeView;
44 import org.graalvm.compiler.nodes.ValueNode;
45 import org.graalvm.compiler.nodes.calc.CompareNode;
46 import org.graalvm.compiler.nodes.spi.VirtualizableAllocation;
47 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
48 import org.graalvm.compiler.nodes.util.GraphUtil;
49 import org.graalvm.compiler.nodes.virtual.VirtualArrayNode;
50 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
51 
52 import jdk.vm.ci.meta.DeoptimizationAction;
53 import jdk.vm.ci.meta.DeoptimizationReason;
54 import jdk.vm.ci.meta.ResolvedJavaType;
55 
56 /**
57  * The {@code NewArrayNode} is used for all array allocations where the element type is know at
58  * compile time.
59  */
60 // JaCoCo Exclude
61 @NodeInfo
62 public class NewArrayNode extends AbstractNewArrayNode implements VirtualizableAllocation, Simplifiable {
63 
64     public static final NodeClass<NewArrayNode> TYPE = NodeClass.create(NewArrayNode.class);
65     private final ResolvedJavaType elementType;
66 
NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents)67     public NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents) {
68         this(elementType, length, fillContents, null);
69     }
70 
NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents, FrameState stateBefore)71     public NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents, FrameState stateBefore) {
72         this(TYPE, elementType, length, fillContents, stateBefore);
73     }
74 
NewArrayNode(NodeClass<? extends NewArrayNode> c, ResolvedJavaType elementType, ValueNode length, boolean fillContents, FrameState stateBefore)75     protected NewArrayNode(NodeClass<? extends NewArrayNode> c, ResolvedJavaType elementType, ValueNode length, boolean fillContents, FrameState stateBefore) {
76         super(c, StampFactory.objectNonNull(TypeReference.createExactTrusted(elementType.getArrayClass())), length, fillContents, stateBefore);
77         this.elementType = elementType;
78     }
79 
80     @NodeIntrinsic
newArray(@onstantNodeParameter Class<?> elementType, int length, @ConstantNodeParameter boolean fillContents)81     private static native Object newArray(@ConstantNodeParameter Class<?> elementType, int length, @ConstantNodeParameter boolean fillContents);
82 
newUninitializedArray(Class<?> elementType, int length)83     public static Object newUninitializedArray(Class<?> elementType, int length) {
84         return newArray(elementType, length, false);
85     }
86 
87     /**
88      * Gets the element type of the array.
89      *
90      * @return the element type of the array
91      */
elementType()92     public ResolvedJavaType elementType() {
93         return elementType;
94     }
95 
96     @Override
virtualize(VirtualizerTool tool)97     public void virtualize(VirtualizerTool tool) {
98         ValueNode lengthAlias = tool.getAlias(length());
99         if (lengthAlias.asConstant() != null) {
100             int constantLength = lengthAlias.asJavaConstant().asInt();
101             if (constantLength >= 0 && constantLength < tool.getMaximumEntryCount()) {
102                 ValueNode[] state = new ValueNode[constantLength];
103                 ConstantNode defaultForKind = constantLength == 0 ? null : defaultElementValue();
104                 for (int i = 0; i < constantLength; i++) {
105                     state[i] = defaultForKind;
106                 }
107                 VirtualObjectNode virtualObject = createVirtualArrayNode(constantLength);
108                 tool.createVirtualObject(virtualObject, state, Collections.<MonitorIdNode> emptyList(), false);
109                 tool.replaceWithVirtual(virtualObject);
110             }
111         }
112     }
113 
createVirtualArrayNode(int constantLength)114     protected VirtualArrayNode createVirtualArrayNode(int constantLength) {
115         return new VirtualArrayNode(elementType(), constantLength);
116     }
117 
118     /* Factored out in a separate method so that subclasses can override it. */
defaultElementValue()119     protected ConstantNode defaultElementValue() {
120         return ConstantNode.defaultForKind(elementType().getJavaKind(), graph());
121     }
122 
123     @Override
124     @SuppressWarnings("try")
simplify(SimplifierTool tool)125     public void simplify(SimplifierTool tool) {
126         if (hasNoUsages()) {
127             NodeView view = NodeView.from(tool);
128             Stamp lengthStamp = length().stamp(view);
129             if (lengthStamp instanceof IntegerStamp) {
130                 IntegerStamp lengthIntegerStamp = (IntegerStamp) lengthStamp;
131                 if (lengthIntegerStamp.isPositive()) {
132                     GraphUtil.removeFixedWithUnusedInputs(this);
133                     return;
134                 }
135             }
136             // Should be areFrameStatesAtSideEffects but currently SVM will complain about
137             // RuntimeConstraint
138             if (graph().getGuardsStage().allowsFloatingGuards()) {
139                 try (DebugCloseable context = this.withNodeSourcePosition()) {
140                     LogicNode lengthNegativeCondition = CompareNode.createCompareNode(graph(), CanonicalCondition.LT, length(), ConstantNode.forInt(0, graph()), tool.getConstantReflection(), view);
141                     // we do not have a non-deopting path for that at the moment so action=None.
142                     FixedGuardNode guard = graph().add(new FixedGuardNode(lengthNegativeCondition, DeoptimizationReason.RuntimeConstraint, DeoptimizationAction.None, true));
143                     graph().replaceFixedWithFixed(this, guard);
144                 }
145             }
146         }
147     }
148 }
149