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 */ 023package com.oracle.graal.truffle.nodes.frame; 024 025import java.util.*; 026 027import jdk.internal.jvmci.common.*; 028import jdk.internal.jvmci.meta.*; 029 030import com.oracle.graal.api.replacements.*; 031import com.oracle.graal.api.runtime.*; 032import com.oracle.graal.compiler.common.type.*; 033import com.oracle.graal.graph.*; 034import com.oracle.graal.graph.spi.*; 035import com.oracle.graal.nodeinfo.*; 036import com.oracle.graal.nodes.*; 037import com.oracle.graal.nodes.java.*; 038import com.oracle.graal.nodes.spi.*; 039import com.oracle.graal.nodes.util.*; 040import com.oracle.graal.nodes.virtual.*; 041import com.oracle.graal.truffle.*; 042import com.oracle.graal.truffle.nodes.*; 043import com.oracle.truffle.api.frame.*; 044 045/** 046 * Intrinsic node representing the call for creating a frame in the {@link OptimizedCallTarget} 047 * class. 048 */ 049@NodeInfo 050public final class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable { 051 052 public static final NodeClass<NewFrameNode> TYPE = NodeClass.create(NewFrameNode.class); 053 @Input ValueNode descriptor; 054 @Input ValueNode arguments; 055 056 public NewFrameNode(Stamp stamp, ValueNode descriptor, ValueNode arguments) { 057 super(TYPE, stamp); 058 this.descriptor = descriptor; 059 this.arguments = arguments; 060 } 061 062 public NewFrameNode(ResolvedJavaType frameType, ValueNode descriptor, ValueNode arguments) { 063 this(StampFactory.exactNonNull(frameType), descriptor, arguments); 064 } 065 066 public ValueNode getDescriptor() { 067 return descriptor; 068 } 069 070 public ValueNode getArguments() { 071 return arguments; 072 } 073 074 private static SnippetReflectionProvider getSnippetReflection() { 075 /* 076 * This class requires access to the objects encapsulated in Constants, and therefore breaks 077 * the compiler-VM separation of object constants. 078 */ 079 return Graal.getRequiredCapability(SnippetReflectionProvider.class); 080 } 081 082 private FrameDescriptor getConstantFrameDescriptor() { 083 assert descriptor.isConstant() && !descriptor.isNullConstant(); 084 return getSnippetReflection().asObject(FrameDescriptor.class, descriptor.asJavaConstant()); 085 } 086 087 private int getFrameSize() { 088 return getConstantFrameDescriptor().getSize(); 089 } 090 091 private static ResolvedJavaField findField(ResolvedJavaField[] fields, String fieldName) { 092 for (ResolvedJavaField field : fields) { 093 if (field.getName().equals(fieldName)) { 094 return field; 095 } 096 } 097 return null; 098 } 099 100 @NodeInfo 101 public static final class VirtualOnlyInstanceNode extends VirtualInstanceNode { 102 103 public static final NodeClass<VirtualOnlyInstanceNode> TYPE = NodeClass.create(VirtualOnlyInstanceNode.class); 104 protected boolean allowMaterialization; 105 106 public VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) { 107 super(TYPE, type, fields, true); 108 } 109 110 @Override 111 public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks) { 112 if (allowMaterialization) { 113 return super.getMaterializedRepresentation(fixed, entries, locks); 114 } 115 return getMaterializedRepresentationHelper(this, fixed); 116 } 117 118 public void setAllowMaterialization(boolean b) { 119 this.allowMaterialization = b; 120 } 121 } 122 123 public static ValueNode getMaterializedRepresentationHelper(VirtualObjectNode virtualNode, FixedNode fixed) { 124 if (fixed instanceof MaterializeFrameNode || fixed instanceof AbstractEndNode || fixed instanceof ForceMaterializeNode) { 125 // We need to conservatively assume that a materialization of a virtual frame can also 126 // happen at a merge point. 127 return new AllocatedObjectNode(virtualNode); 128 } 129 String escapeReason; 130 if (fixed instanceof StoreFieldNode) { 131 escapeReason = "Must not store virtual frame object into a field."; 132 } else if (fixed instanceof Invoke) { 133 escapeReason = "Must not pass virtual frame object into an invoke that cannot be inlined."; 134 } else { 135 escapeReason = "Must not let virtual frame object escape at node " + fixed + "."; 136 } 137 138 Throwable exception = new JVMCIError(escapeReason + 139 " Insert a call to VirtualFrame.materialize() to convert the instance to a materialized frame object (source position of following stack trace is approximate)"); 140 throw GraphUtil.approxSourceException(fixed, exception); 141 } 142 143 @Override 144 public void virtualize(VirtualizerTool tool) { 145 if (!descriptor.isConstant()) { 146 return; 147 } 148 149 int frameSize = getFrameSize(); 150 151 ResolvedJavaType frameType = stamp().javaType(tool.getMetaAccessProvider()); 152 ResolvedJavaField[] frameFields = frameType.getInstanceFields(true); 153 154 ResolvedJavaField descriptorField = findField(frameFields, "descriptor"); 155 ResolvedJavaField argumentsField = findField(frameFields, "arguments"); 156 ResolvedJavaField localsField = findField(frameFields, "locals"); 157 ResolvedJavaField primitiveLocalsField = findField(frameFields, "primitiveLocals"); 158 ResolvedJavaField tagsField = findField(frameFields, "tags"); 159 160 VirtualObjectNode virtualFrame = new VirtualOnlyInstanceNode(frameType, frameFields); 161 VirtualObjectNode virtualFrameObjectArray = new VirtualArrayNode((ResolvedJavaType) localsField.getType().getComponentType(), frameSize); 162 VirtualObjectNode virtualFramePrimitiveArray = (primitiveLocalsField == null ? null : new VirtualArrayNode((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize)); 163 VirtualObjectNode virtualFrameTagArray = (primitiveLocalsField == null ? null : new VirtualArrayNode((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize)); 164 165 ValueNode[] objectArrayEntryState = new ValueNode[frameSize]; 166 ValueNode[] primitiveArrayEntryState = new ValueNode[frameSize]; 167 ValueNode[] tagArrayEntryState = new ValueNode[frameSize]; 168 169 if (frameSize > 0) { 170 FrameDescriptor frameDescriptor = getConstantFrameDescriptor(); 171 ConstantNode objectDefault = ConstantNode.forConstant(getSnippetReflection().forObject(frameDescriptor.getDefaultValue()), tool.getMetaAccessProvider(), graph()); 172 ConstantNode tagDefault = ConstantNode.forByte((byte) 0, graph()); 173 Arrays.fill(objectArrayEntryState, objectDefault); 174 if (virtualFrameTagArray != null) { 175 Arrays.fill(tagArrayEntryState, tagDefault); 176 } 177 if (virtualFramePrimitiveArray != null) { 178 for (int i = 0; i < frameSize; i++) { 179 primitiveArrayEntryState[i] = initialPrimitiveValue(frameDescriptor.getSlots().get(i).getKind()); 180 } 181 } 182 graph().getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) frameDescriptor.getVersion())); 183 } 184 185 tool.createVirtualObject(virtualFrameObjectArray, objectArrayEntryState, Collections.<MonitorIdNode> emptyList(), false); 186 if (virtualFramePrimitiveArray != null) { 187 tool.createVirtualObject(virtualFramePrimitiveArray, primitiveArrayEntryState, Collections.<MonitorIdNode> emptyList(), false); 188 } 189 if (virtualFrameTagArray != null) { 190 tool.createVirtualObject(virtualFrameTagArray, tagArrayEntryState, Collections.<MonitorIdNode> emptyList(), false); 191 } 192 193 assert frameFields.length == 5 || frameFields.length == 3; 194 ValueNode[] frameEntryState = new ValueNode[frameFields.length]; 195 List<ResolvedJavaField> frameFieldList = Arrays.asList(frameFields); 196 frameEntryState[frameFieldList.indexOf(descriptorField)] = getDescriptor(); 197 frameEntryState[frameFieldList.indexOf(argumentsField)] = getArguments(); 198 frameEntryState[frameFieldList.indexOf(localsField)] = virtualFrameObjectArray; 199 if (primitiveLocalsField != null) { 200 frameEntryState[frameFieldList.indexOf(primitiveLocalsField)] = virtualFramePrimitiveArray; 201 } 202 if (tagsField != null) { 203 frameEntryState[frameFieldList.indexOf(tagsField)] = virtualFrameTagArray; 204 } 205 tool.createVirtualObject(virtualFrame, frameEntryState, Collections.<MonitorIdNode> emptyList(), false); 206 tool.replaceWithVirtual(virtualFrame); 207 } 208 209 private ValueNode initialPrimitiveValue(FrameSlotKind kind) { 210 Kind graalKind = null; 211 switch (kind) { 212 case Boolean: 213 case Byte: 214 case Int: 215 graalKind = Kind.Int; 216 break; 217 case Double: 218 graalKind = Kind.Double; 219 break; 220 case Float: 221 graalKind = Kind.Float; 222 break; 223 case Long: 224 graalKind = Kind.Long; 225 break; 226 case Object: 227 case Illegal: 228 // won't be stored in the primitive array, so default to long 229 graalKind = Kind.Long; 230 break; 231 default: 232 throw new IllegalStateException("Unexpected frame slot kind: " + kind); 233 } 234 235 return ConstantNode.defaultForKind(graalKind, graph()); 236 } 237 238 @Override 239 public Node canonical(CanonicalizerTool tool) { 240 if (tool.allUsagesAvailable() && hasNoUsages()) { 241 return null; 242 } else { 243 return this; 244 } 245 } 246 247 @NodeIntrinsic 248 public static native VirtualFrame allocate(@ConstantNodeParameter Class<? extends VirtualFrame> frameType, FrameDescriptor descriptor, Object[] args); 249}