1 /* 2 * Copyright (c) 2011, 2016, 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 package org.graalvm.compiler.nodes; 24 25 import static org.graalvm.compiler.nodeinfo.InputType.Extension; 26 import static org.graalvm.compiler.nodeinfo.InputType.Guard; 27 import static org.graalvm.compiler.nodeinfo.InputType.Memory; 28 import static org.graalvm.compiler.nodeinfo.InputType.State; 29 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; 30 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; 31 32 import java.util.Map; 33 34 import org.graalvm.compiler.core.common.LocationIdentity; 35 import org.graalvm.compiler.core.common.type.Stamp; 36 import org.graalvm.compiler.graph.Node; 37 import org.graalvm.compiler.graph.NodeClass; 38 import org.graalvm.compiler.nodeinfo.NodeInfo; 39 import org.graalvm.compiler.nodeinfo.Verbosity; 40 import org.graalvm.compiler.nodes.extended.ForeignCallNode; 41 import org.graalvm.compiler.nodes.extended.GuardingNode; 42 import org.graalvm.compiler.nodes.java.MethodCallTargetNode; 43 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; 44 import org.graalvm.compiler.nodes.spi.LIRLowerable; 45 import org.graalvm.compiler.nodes.spi.LoweringTool; 46 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 47 import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider; 48 import org.graalvm.compiler.nodes.util.GraphUtil; 49 50 import jdk.vm.ci.meta.JavaKind; 51 52 @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}", allowedUsageTypes = {Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) 53 public final class InvokeWithExceptionNode extends ControlSplitNode implements Invoke, MemoryCheckpoint.Single, LIRLowerable, UncheckedInterfaceProvider { 54 public static final NodeClass<InvokeWithExceptionNode> TYPE = NodeClass.create(InvokeWithExceptionNode.class); 55 56 private static final double EXCEPTION_PROBA = 1e-5; 57 58 @Successor AbstractBeginNode next; 59 @Successor AbstractBeginNode exceptionEdge; 60 @OptionalInput ValueNode classInit; 61 @Input(Extension) CallTargetNode callTarget; 62 @OptionalInput(State) FrameState stateDuring; 63 @OptionalInput(State) FrameState stateAfter; 64 @OptionalInput(Guard) GuardingNode guard; 65 protected final int bci; 66 protected boolean polymorphic; 67 protected boolean useForInlining; 68 protected double exceptionProbability; 69 70 public InvokeWithExceptionNode(CallTargetNode callTarget, AbstractBeginNode exceptionEdge, int bci) { 71 super(TYPE, callTarget.returnStamp().getTrustedStamp()); 72 this.exceptionEdge = exceptionEdge; 73 this.bci = bci; 74 this.callTarget = callTarget; 75 this.polymorphic = false; 76 this.useForInlining = true; 77 this.exceptionProbability = EXCEPTION_PROBA; 78 } 79 80 public AbstractBeginNode exceptionEdge() { 81 return exceptionEdge; 82 } 83 84 public void setExceptionEdge(AbstractBeginNode x) { 85 updatePredecessor(exceptionEdge, x); 86 exceptionEdge = x; 87 } 88 89 @Override 90 public AbstractBeginNode next() { 91 return next; 92 } 93 94 public void setNext(AbstractBeginNode x) { 95 updatePredecessor(next, x); 96 next = x; 97 } 98 99 @Override 100 public CallTargetNode callTarget() { 101 return callTarget; 102 } 103 104 void setCallTarget(CallTargetNode callTarget) { 105 updateUsages(this.callTarget, callTarget); 106 this.callTarget = callTarget; 107 } 108 109 public MethodCallTargetNode methodCallTarget() { 110 return (MethodCallTargetNode) callTarget; 111 } 112 113 @Override 114 public boolean isPolymorphic() { 115 return polymorphic; 116 } 117 118 @Override 119 public void setPolymorphic(boolean value) { 120 this.polymorphic = value; 121 } 122 123 @Override 124 public boolean useForInlining() { 125 return useForInlining; 126 } 127 128 @Override 129 public void setUseForInlining(boolean value) { 130 this.useForInlining = value; 131 } 132 133 @Override 134 public String toString(Verbosity verbosity) { 135 if (verbosity == Verbosity.Long) { 136 return super.toString(Verbosity.Short) + "(bci=" + bci() + ")"; 137 } else if (verbosity == Verbosity.Name) { 138 return "Invoke#" + (callTarget == null ? "null" : callTarget().targetName()); 139 } else { 140 return super.toString(verbosity); 141 } 142 } 143 144 @Override 145 public int bci() { 146 return bci; 147 } 148 149 @Override 150 public void setNext(FixedNode x) { 151 if (x != null) { 152 this.setNext(KillingBeginNode.begin(x, getLocationIdentity())); 153 } else { 154 this.setNext(null); 155 } 156 } 157 158 @Override 159 public void lower(LoweringTool tool) { 160 tool.getLowerer().lower(this, tool); 161 } 162 163 @Override 164 public void generate(NodeLIRBuilderTool gen) { 165 gen.emitInvoke(this); 166 } 167 168 @Override 169 public FrameState stateAfter() { 170 return stateAfter; 171 } 172 173 @Override 174 public void setStateAfter(FrameState stateAfter) { 175 updateUsages(this.stateAfter, stateAfter); 176 this.stateAfter = stateAfter; 177 } 178 179 @Override 180 public boolean hasSideEffect() { 181 return true; 182 } 183 184 @Override 185 public LocationIdentity getLocationIdentity() { 186 return LocationIdentity.any(); 187 } 188 189 @Override 190 public Map<Object, Object> getDebugProperties(Map<Object, Object> map) { 191 Map<Object, Object> debugProperties = super.getDebugProperties(map); 192 if (callTarget != null) { 193 debugProperties.put("targetMethod", callTarget.targetName()); 194 } 195 return debugProperties; 196 } 197 198 public void killExceptionEdge() { 199 AbstractBeginNode edge = exceptionEdge(); 200 setExceptionEdge(null); 201 GraphUtil.killCFG(edge); 202 } 203 204 @Override 205 public void intrinsify(Node node) { 206 assert !(node instanceof ValueNode) || (((ValueNode) node).getStackKind() == JavaKind.Void) == (getStackKind() == JavaKind.Void); 207 CallTargetNode call = callTarget; 208 FrameState state = stateAfter(); 209 killExceptionEdge(); 210 if (node instanceof StateSplit) { 211 StateSplit stateSplit = (StateSplit) node; 212 stateSplit.setStateAfter(state); 213 } 214 if (node instanceof ForeignCallNode) { 215 ForeignCallNode foreign = (ForeignCallNode) node; 216 foreign.setBci(bci()); 217 } 218 if (node == null) { 219 assert getStackKind() == JavaKind.Void && hasNoUsages(); 220 graph().removeSplit(this, next()); 221 } else if (node instanceof ControlSinkNode) { 222 this.replaceAtPredecessor(node); 223 this.replaceAtUsages(null); 224 GraphUtil.killCFG(this); 225 return; 226 } else { 227 graph().replaceSplit(this, node, next()); 228 } 229 GraphUtil.killWithUnusedFloatingInputs(call); 230 if (state.hasNoUsages()) { 231 GraphUtil.killWithUnusedFloatingInputs(state); 232 } 233 } 234 235 @Override 236 public double probability(AbstractBeginNode successor) { 237 return successor == next ? 1 - exceptionProbability : exceptionProbability; 238 } 239 240 @Override 241 public boolean canDeoptimize() { 242 return true; 243 } 244 245 @Override 246 public FrameState stateDuring() { 247 return stateDuring; 248 } 249 250 @Override 251 public void setStateDuring(FrameState stateDuring) { 252 updateUsages(this.stateDuring, stateDuring); 253 this.stateDuring = stateDuring; 254 } 255 256 @Override 257 public GuardingNode getGuard() { 258 return guard; 259 } 260 261 @Override 262 public void setGuard(GuardingNode guard) { 263 updateUsagesInterface(this.guard, guard); 264 this.guard = guard; 265 } 266 267 @Override 268 public AbstractBeginNode getPrimarySuccessor() { 269 return this.next(); 270 } 271 272 @Override 273 public Stamp uncheckedStamp() { 274 return this.callTarget.returnStamp().getUncheckedStamp(); 275 } 276 277 @Override 278 public void setClassInit(ValueNode classInit) { 279 this.classInit = classInit; 280 updateUsages(null, classInit); 281 } 282 283 @Override 284 public ValueNode classInit() { 285 return classInit; 286 } 287 }