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}