001/* 002 * Copyright (c) 2011, 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.nodes; 024 025import java.util.*; 026 027import jdk.internal.jvmci.meta.*; 028 029import com.oracle.graal.graph.*; 030import com.oracle.graal.nodeinfo.*; 031import com.oracle.graal.nodes.extended.*; 032import com.oracle.graal.nodes.java.*; 033import com.oracle.graal.nodes.memory.*; 034import com.oracle.graal.nodes.spi.*; 035import com.oracle.graal.nodes.util.*; 036 037@NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}", allowedUsageTypes = {InputType.Memory}) 038public final class InvokeWithExceptionNode extends ControlSplitNode implements Invoke, MemoryCheckpoint.Single, LIRLowerable { 039 public static final NodeClass<InvokeWithExceptionNode> TYPE = NodeClass.create(InvokeWithExceptionNode.class); 040 041 private static final double EXCEPTION_PROBA = 1e-5; 042 043 @Successor AbstractBeginNode next; 044 @Successor AbstractBeginNode exceptionEdge; 045 @Input(InputType.Extension) CallTargetNode callTarget; 046 @OptionalInput(InputType.State) FrameState stateDuring; 047 @OptionalInput(InputType.State) FrameState stateAfter; 048 @OptionalInput(InputType.Guard) GuardingNode guard; 049 protected final int bci; 050 protected boolean polymorphic; 051 protected boolean useForInlining; 052 protected double exceptionProbability; 053 054 public InvokeWithExceptionNode(CallTargetNode callTarget, AbstractBeginNode exceptionEdge, int bci) { 055 super(TYPE, callTarget.returnStamp()); 056 this.exceptionEdge = exceptionEdge; 057 this.bci = bci; 058 this.callTarget = callTarget; 059 this.polymorphic = false; 060 this.useForInlining = true; 061 this.exceptionProbability = EXCEPTION_PROBA; 062 } 063 064 public AbstractBeginNode exceptionEdge() { 065 return exceptionEdge; 066 } 067 068 public void setExceptionEdge(AbstractBeginNode x) { 069 updatePredecessor(exceptionEdge, x); 070 exceptionEdge = x; 071 } 072 073 public AbstractBeginNode next() { 074 return next; 075 } 076 077 public void setNext(AbstractBeginNode x) { 078 updatePredecessor(next, x); 079 next = x; 080 } 081 082 public CallTargetNode callTarget() { 083 return callTarget; 084 } 085 086 void setCallTarget(CallTargetNode callTarget) { 087 updateUsages(this.callTarget, callTarget); 088 this.callTarget = callTarget; 089 } 090 091 public MethodCallTargetNode methodCallTarget() { 092 return (MethodCallTargetNode) callTarget; 093 } 094 095 @Override 096 public boolean isPolymorphic() { 097 return polymorphic; 098 } 099 100 @Override 101 public void setPolymorphic(boolean value) { 102 this.polymorphic = value; 103 } 104 105 @Override 106 public boolean useForInlining() { 107 return useForInlining; 108 } 109 110 @Override 111 public void setUseForInlining(boolean value) { 112 this.useForInlining = value; 113 } 114 115 @Override 116 public String toString(Verbosity verbosity) { 117 if (verbosity == Verbosity.Long) { 118 return super.toString(Verbosity.Short) + "(bci=" + bci() + ")"; 119 } else if (verbosity == Verbosity.Name) { 120 return "Invoke#" + (callTarget == null ? "null" : callTarget().targetName()); 121 } else { 122 return super.toString(verbosity); 123 } 124 } 125 126 public int bci() { 127 return bci; 128 } 129 130 @Override 131 public void setNext(FixedNode x) { 132 if (x != null) { 133 this.setNext(KillingBeginNode.begin(x, getLocationIdentity())); 134 } else { 135 this.setNext(null); 136 } 137 } 138 139 @Override 140 public void lower(LoweringTool tool) { 141 tool.getLowerer().lower(this, tool); 142 } 143 144 @Override 145 public void generate(NodeLIRBuilderTool gen) { 146 gen.emitInvoke(this); 147 } 148 149 public FrameState stateAfter() { 150 return stateAfter; 151 } 152 153 public void setStateAfter(FrameState stateAfter) { 154 updateUsages(this.stateAfter, stateAfter); 155 this.stateAfter = stateAfter; 156 } 157 158 public boolean hasSideEffect() { 159 return true; 160 } 161 162 @Override 163 public LocationIdentity getLocationIdentity() { 164 return LocationIdentity.any(); 165 } 166 167 @Override 168 public Map<Object, Object> getDebugProperties(Map<Object, Object> map) { 169 Map<Object, Object> debugProperties = super.getDebugProperties(map); 170 if (callTarget != null) { 171 debugProperties.put("targetMethod", callTarget.targetName()); 172 } 173 return debugProperties; 174 } 175 176 public void killExceptionEdge() { 177 AbstractBeginNode edge = exceptionEdge(); 178 setExceptionEdge(null); 179 GraphUtil.killCFG(edge); 180 } 181 182 @Override 183 public void intrinsify(Node node) { 184 assert !(node instanceof ValueNode) || (((ValueNode) node).getKind() == Kind.Void) == (getKind() == Kind.Void); 185 CallTargetNode call = callTarget; 186 FrameState state = stateAfter(); 187 killExceptionEdge(); 188 if (node instanceof StateSplit) { 189 StateSplit stateSplit = (StateSplit) node; 190 stateSplit.setStateAfter(state); 191 } 192 if (node instanceof ForeignCallNode) { 193 ForeignCallNode foreign = (ForeignCallNode) node; 194 foreign.setBci(bci()); 195 } 196 if (node == null) { 197 assert getKind() == Kind.Void && hasNoUsages(); 198 graph().removeSplit(this, next()); 199 } else if (node instanceof ControlSinkNode) { 200 this.replaceAtPredecessor(node); 201 this.replaceAtUsages(null); 202 GraphUtil.killCFG(this); 203 return; 204 } else { 205 graph().replaceSplit(this, node, next()); 206 } 207 GraphUtil.killWithUnusedFloatingInputs(call); 208 if (state.hasNoUsages()) { 209 GraphUtil.killWithUnusedFloatingInputs(state); 210 } 211 } 212 213 @Override 214 public double probability(AbstractBeginNode successor) { 215 return successor == next ? 1 - exceptionProbability : exceptionProbability; 216 } 217 218 @Override 219 public boolean canDeoptimize() { 220 return true; 221 } 222 223 @Override 224 public FrameState stateDuring() { 225 return stateDuring; 226 } 227 228 @Override 229 public void setStateDuring(FrameState stateDuring) { 230 updateUsages(this.stateDuring, stateDuring); 231 this.stateDuring = stateDuring; 232 } 233 234 @Override 235 public GuardingNode getGuard() { 236 return guard; 237 } 238 239 @Override 240 public void setGuard(GuardingNode guard) { 241 updateUsagesInterface(this.guard, guard); 242 this.guard = guard; 243 } 244 245 @Override 246 public AbstractBeginNode getPrimarySuccessor() { 247 return this.next(); 248 } 249}