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 67 public NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { 68 this(elementType, length, fillContents, null); 69 } 70 71 public NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents, FrameState stateBefore) { 72 this(TYPE, elementType, length, fillContents, stateBefore); 73 } 74 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 81 private static native Object newArray(@ConstantNodeParameter Class<?> elementType, int length, @ConstantNodeParameter boolean fillContents); 82 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 */ 92 public ResolvedJavaType elementType() { 93 return elementType; 94 } 95 96 @Override 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 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. */ 119 protected ConstantNode defaultElementValue() { 120 return ConstantNode.defaultForKind(elementType().getJavaKind(), graph()); 121 } 122 123 @Override 124 @SuppressWarnings("try") 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 }