001/* 002 * Copyright (c) 2011, 2013, 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; 024 025import jdk.internal.jvmci.code.*; 026import jdk.internal.jvmci.common.*; 027import jdk.internal.jvmci.meta.*; 028 029import com.oracle.graal.compiler.common.type.*; 030import com.oracle.graal.graphbuilderconf.*; 031import com.oracle.graal.graphbuilderconf.InvocationPlugin.Receiver; 032import com.oracle.graal.nodes.CallTargetNode.InvokeKind; 033import com.oracle.graal.nodes.*; 034import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; 035import com.oracle.graal.nodes.calc.*; 036import com.oracle.graal.nodes.spi.*; 037 038/** 039 * Implementation of {@link GraphBuilderContext} used to produce a graph for a method based on an 040 * {@link InvocationPlugin} for the method. 041 */ 042public class IntrinsicGraphBuilder implements GraphBuilderContext, Receiver { 043 044 private final MetaAccessProvider metaAccess; 045 private final ConstantReflectionProvider constantReflection; 046 private final StampProvider stampProvider; 047 private final StructuredGraph graph; 048 private final ResolvedJavaMethod method; 049 private final int invokeBci; 050 private FixedWithNextNode lastInstr; 051 private ValueNode[] arguments; 052 private ValueNode returnValue; 053 054 public IntrinsicGraphBuilder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider, ResolvedJavaMethod method, int invokeBci) { 055 this.metaAccess = metaAccess; 056 this.constantReflection = constantReflection; 057 this.stampProvider = stampProvider; 058 this.graph = new StructuredGraph(method, AllowAssumptions.YES); 059 this.method = method; 060 this.invokeBci = invokeBci; 061 this.lastInstr = graph.start(); 062 063 Signature sig = method.getSignature(); 064 int max = sig.getParameterCount(false); 065 this.arguments = new ValueNode[max + (method.isStatic() ? 0 : 1)]; 066 067 int javaIndex = 0; 068 int index = 0; 069 if (!method.isStatic()) { 070 // add the receiver 071 Stamp receiverStamp = StampFactory.declaredNonNull(method.getDeclaringClass()); 072 FloatingNode receiver = graph.addWithoutUnique(new ParameterNode(javaIndex, receiverStamp)); 073 arguments[index] = receiver; 074 javaIndex = 1; 075 index = 1; 076 } 077 ResolvedJavaType accessingClass = method.getDeclaringClass(); 078 for (int i = 0; i < max; i++) { 079 JavaType type = sig.getParameterType(i, accessingClass).resolve(accessingClass); 080 Kind kind = type.getKind(); 081 Stamp stamp; 082 if (kind == Kind.Object && type instanceof ResolvedJavaType) { 083 stamp = StampFactory.declared((ResolvedJavaType) type); 084 } else { 085 stamp = StampFactory.forKind(kind); 086 } 087 FloatingNode param = graph.addWithoutUnique(new ParameterNode(index, stamp)); 088 arguments[index] = param; 089 javaIndex += kind.getSlotCount(); 090 index++; 091 } 092 } 093 094 private <T extends ValueNode> void updateLastInstruction(T v) { 095 if (v instanceof FixedNode) { 096 FixedNode fixedNode = (FixedNode) v; 097 lastInstr.setNext(fixedNode); 098 if (fixedNode instanceof FixedWithNextNode) { 099 FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) fixedNode; 100 assert fixedWithNextNode.next() == null : "cannot append instruction to instruction which isn't end"; 101 lastInstr = fixedWithNextNode; 102 } else { 103 lastInstr = null; 104 } 105 } 106 } 107 108 public <T extends ValueNode> T append(T v) { 109 if (v.graph() != null) { 110 return v; 111 } 112 T added = graph.addOrUnique(v); 113 if (added == v) { 114 updateLastInstruction(v); 115 } 116 return added; 117 } 118 119 public <T extends ValueNode> T recursiveAppend(T v) { 120 if (v.graph() != null) { 121 return v; 122 } 123 T added = graph.addOrUniqueWithInputs(v); 124 if (added == v) { 125 updateLastInstruction(v); 126 } 127 return added; 128 } 129 130 public void push(Kind kind, ValueNode value) { 131 assert kind != Kind.Void; 132 assert returnValue == null; 133 returnValue = value; 134 } 135 136 public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean forceInlineEverything) { 137 throw JVMCIError.shouldNotReachHere(); 138 } 139 140 public StampProvider getStampProvider() { 141 return stampProvider; 142 } 143 144 public MetaAccessProvider getMetaAccess() { 145 return metaAccess; 146 } 147 148 public ConstantReflectionProvider getConstantReflection() { 149 return constantReflection; 150 } 151 152 public StructuredGraph getGraph() { 153 return graph; 154 } 155 156 public void setStateAfter(StateSplit sideEffect) { 157 assert sideEffect.hasSideEffect(); 158 FrameState stateAfter = getGraph().add(new FrameState(BytecodeFrame.BEFORE_BCI)); 159 sideEffect.setStateAfter(stateAfter); 160 } 161 162 public GraphBuilderContext getParent() { 163 return null; 164 } 165 166 public ResolvedJavaMethod getMethod() { 167 return method; 168 } 169 170 public int bci() { 171 return invokeBci; 172 } 173 174 public InvokeKind getInvokeKind() { 175 return method.isStatic() ? InvokeKind.Static : InvokeKind.Virtual; 176 } 177 178 public JavaType getInvokeReturnType() { 179 return method.getSignature().getReturnType(method.getDeclaringClass()); 180 } 181 182 public int getDepth() { 183 return 0; 184 } 185 186 public boolean parsingIntrinsic() { 187 return true; 188 } 189 190 public IntrinsicContext getIntrinsic() { 191 throw JVMCIError.shouldNotReachHere(); 192 } 193 194 public BailoutException bailout(String string) { 195 throw JVMCIError.shouldNotReachHere(); 196 } 197 198 public ValueNode get() { 199 return arguments[0]; 200 } 201 202 public StructuredGraph buildGraph(InvocationPlugin plugin) { 203 Receiver receiver = method.isStatic() ? null : this; 204 if (plugin.execute(this, method, receiver, arguments)) { 205 assert (returnValue != null) == (method.getSignature().getReturnKind() != Kind.Void) : method; 206 append(new ReturnNode(returnValue)); 207 return graph; 208 } 209 return null; 210 } 211 212 public void intrinsify(ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, ValueNode[] args) { 213 throw JVMCIError.shouldNotReachHere(); 214 } 215 216 @Override 217 public String toString() { 218 return String.format("%s:intrinsic", method.format("%H.%n(%p)")); 219 } 220}