001/* 002 * Copyright (c) 2013, 2015, 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 */ 023//JaCoCo Exclude 024package com.oracle.graal.nodes.java; 025 026import jdk.internal.jvmci.meta.*; 027 028import com.oracle.graal.compiler.common.type.*; 029import com.oracle.graal.graph.*; 030import com.oracle.graal.graph.spi.*; 031import com.oracle.graal.nodeinfo.*; 032import com.oracle.graal.nodes.*; 033 034/** 035 * The {@code DynamicNewArrayNode} is used for allocation of arrays when the type is not a 036 * compile-time constant. 037 */ 038@NodeInfo 039public class DynamicNewArrayNode extends AbstractNewArrayNode implements Canonicalizable { 040 public static final NodeClass<DynamicNewArrayNode> TYPE = NodeClass.create(DynamicNewArrayNode.class); 041 042 @Input ValueNode elementType; 043 044 /** 045 * A non-null value indicating the worst case element type. Mainly useful for distinguishing 046 * Object arrays from primitive arrays. 047 */ 048 protected final Kind knownElementKind; 049 050 public DynamicNewArrayNode(ValueNode elementType, ValueNode length, boolean fillContents) { 051 this(TYPE, elementType, length, fillContents, null, null, null); 052 } 053 054 public DynamicNewArrayNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ValueNode elementType, ValueNode length, boolean fillContents, Kind knownElementKind) { 055 this(TYPE, elementType, length, fillContents, knownElementKind, null, metaAccess); 056 } 057 058 private static Stamp computeStamp(Kind knownElementKind, MetaAccessProvider metaAccess) { 059 if (knownElementKind != null && metaAccess != null) { 060 ResolvedJavaType arrayType = metaAccess.lookupJavaType(knownElementKind == Kind.Object ? Object.class : knownElementKind.toJavaClass()).getArrayClass(); 061 return StampFactory.declaredNonNull(arrayType); 062 } 063 return StampFactory.objectNonNull(); 064 } 065 066 protected DynamicNewArrayNode(NodeClass<? extends DynamicNewArrayNode> c, ValueNode elementType, ValueNode length, boolean fillContents, Kind knownElementKind, FrameState stateBefore, 067 MetaAccessProvider metaAccess) { 068 super(c, computeStamp(knownElementKind, metaAccess), length, fillContents, stateBefore); 069 this.elementType = elementType; 070 this.knownElementKind = knownElementKind; 071 assert knownElementKind != Kind.Void && knownElementKind != Kind.Illegal; 072 } 073 074 public ValueNode getElementType() { 075 return elementType; 076 } 077 078 public Kind getKnownElementKind() { 079 return knownElementKind; 080 } 081 082 @Override 083 public void simplify(SimplifierTool tool) { 084 /* 085 * Do not call the super implementation: we must not eliminate unused allocations because 086 * throwing a NullPointerException or IllegalArgumentException is a possible side effect of 087 * an unused allocation. 088 */ 089 } 090 091 @Override 092 public Node canonical(CanonicalizerTool tool) { 093 if (elementType.isConstant()) { 094 ResolvedJavaType type = tool.getConstantReflection().asJavaType(elementType.asConstant()); 095 if (type != null && !throwsIllegalArgumentException(type)) { 096 return createNewArrayNode(type); 097 } 098 } 099 return this; 100 } 101 102 /** Hook for subclasses to instantiate a subclass of {@link NewArrayNode}. */ 103 protected NewArrayNode createNewArrayNode(ResolvedJavaType type) { 104 return new NewArrayNode(type, length(), fillContents(), stateBefore()); 105 } 106 107 public static boolean throwsIllegalArgumentException(Class<?> elementType) { 108 return elementType == void.class; 109 } 110 111 public static boolean throwsIllegalArgumentException(ResolvedJavaType elementType) { 112 return elementType.getKind() == Kind.Void; 113 } 114 115 @NodeIntrinsic 116 private static native Object newArray(Class<?> componentType, int length, @ConstantNodeParameter boolean fillContents, @ConstantNodeParameter Kind knownElementKind); 117 118 public static Object newArray(Class<?> componentType, int length, Kind knownElementKind) { 119 return newArray(componentType, length, true, knownElementKind); 120 } 121 122 public static Object newUninitializedArray(Class<?> componentType, int length, Kind knownElementKind) { 123 return newArray(componentType, length, false, knownElementKind); 124 } 125 126}