1 /*
2  * Copyright (c) 2013, 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 
24 
25 package org.graalvm.compiler.nodes;
26 
27 import org.graalvm.compiler.core.common.type.StampFactory;
28 import org.graalvm.compiler.debug.DebugCloseable;
29 import org.graalvm.compiler.graph.NodeClass;
30 import org.graalvm.compiler.graph.NodeSourcePosition;
31 import org.graalvm.compiler.graph.spi.Simplifiable;
32 import org.graalvm.compiler.graph.spi.SimplifierTool;
33 import org.graalvm.compiler.nodeinfo.InputType;
34 import org.graalvm.compiler.nodeinfo.NodeInfo;
35 import org.graalvm.compiler.nodeinfo.Verbosity;
36 import org.graalvm.compiler.nodes.extended.GuardingNode;
37 import org.graalvm.compiler.nodes.util.GraphUtil;
38 
39 import jdk.vm.ci.meta.DeoptimizationAction;
40 import jdk.vm.ci.meta.DeoptimizationReason;
41 import jdk.vm.ci.meta.SpeculationLog.Speculation;
42 
43 @NodeInfo
44 public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode, DeoptimizingGuard {
45 
46     public static final NodeClass<AbstractFixedGuardNode> TYPE = NodeClass.create(AbstractFixedGuardNode.class);
47     @Input(InputType.Condition) protected LogicNode condition;
48     protected DeoptimizationReason reason;
49     protected DeoptimizationAction action;
50     protected Speculation speculation;
51     protected boolean negated;
52     protected NodeSourcePosition noDeoptSuccessorPosition;
53 
54     @Override
getCondition()55     public LogicNode getCondition() {
56         return condition;
57     }
58 
condition()59     public LogicNode condition() {
60         return getCondition();
61     }
62 
63     @Override
setCondition(LogicNode x, boolean negated)64     public void setCondition(LogicNode x, boolean negated) {
65         updateUsages(condition, x);
66         condition = x;
67         this.negated = negated;
68     }
69 
AbstractFixedGuardNode(NodeClass<? extends AbstractFixedGuardNode> c, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, Speculation speculation, boolean negated)70     protected AbstractFixedGuardNode(NodeClass<? extends AbstractFixedGuardNode> c, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, Speculation speculation,
71                     boolean negated) {
72         super(c, StampFactory.forVoid());
73         this.action = action;
74         assert speculation != null;
75         this.speculation = speculation;
76         this.negated = negated;
77         this.condition = condition;
78         this.reason = deoptReason;
79     }
80 
AbstractFixedGuardNode(NodeClass<? extends AbstractFixedGuardNode> c, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, Speculation speculation, boolean negated, NodeSourcePosition noDeoptSuccessorPosition)81     protected AbstractFixedGuardNode(NodeClass<? extends AbstractFixedGuardNode> c, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, Speculation speculation,
82                     boolean negated, NodeSourcePosition noDeoptSuccessorPosition) {
83         this(c, condition, deoptReason, action, speculation, negated);
84         this.noDeoptSuccessorPosition = noDeoptSuccessorPosition;
85     }
86 
87     @Override
getReason()88     public DeoptimizationReason getReason() {
89         return reason;
90     }
91 
92     @Override
getAction()93     public DeoptimizationAction getAction() {
94         return action;
95     }
96 
97     @Override
getSpeculation()98     public Speculation getSpeculation() {
99         return speculation;
100     }
101 
102     @Override
isNegated()103     public boolean isNegated() {
104         return negated;
105     }
106 
107     @Override
toString(Verbosity verbosity)108     public String toString(Verbosity verbosity) {
109         if (verbosity == Verbosity.Name && negated) {
110             return "!" + super.toString(verbosity);
111         } else {
112             return super.toString(verbosity);
113         }
114     }
115 
116     @Override
simplify(SimplifierTool tool)117     public void simplify(SimplifierTool tool) {
118         while (condition instanceof LogicNegationNode) {
119             LogicNegationNode negation = (LogicNegationNode) condition;
120             setCondition(negation.getValue(), !negated);
121         }
122     }
123 
124     @SuppressWarnings("try")
lowerToIf()125     public DeoptimizeNode lowerToIf() {
126         try (DebugCloseable position = this.withNodeSourcePosition()) {
127             FixedNode currentNext = next();
128             setNext(null);
129             DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason, speculation));
130             deopt.setStateBefore(stateBefore());
131             IfNode ifNode;
132             AbstractBeginNode noDeoptSuccessor;
133             if (negated) {
134                 ifNode = graph().add(new IfNode(condition, deopt, currentNext, 0));
135                 noDeoptSuccessor = ifNode.falseSuccessor();
136             } else {
137                 ifNode = graph().add(new IfNode(condition, currentNext, deopt, 1));
138                 noDeoptSuccessor = ifNode.trueSuccessor();
139             }
140             noDeoptSuccessor.setNodeSourcePosition(getNoDeoptSuccessorPosition());
141             ((FixedWithNextNode) predecessor()).setNext(ifNode);
142             this.replaceAtUsages(noDeoptSuccessor);
143             GraphUtil.killWithUnusedFloatingInputs(this);
144 
145             return deopt;
146         }
147     }
148 
149     @Override
canDeoptimize()150     public boolean canDeoptimize() {
151         return true;
152     }
153 
154     @Override
setAction(DeoptimizationAction action)155     public void setAction(DeoptimizationAction action) {
156         this.action = action;
157     }
158 
159     @Override
setReason(DeoptimizationReason reason)160     public void setReason(DeoptimizationReason reason) {
161         this.reason = reason;
162     }
163 
164     @Override
getNoDeoptSuccessorPosition()165     public NodeSourcePosition getNoDeoptSuccessorPosition() {
166         return noDeoptSuccessorPosition;
167     }
168 
169     @Override
setNoDeoptSuccessorPosition(NodeSourcePosition noDeoptSuccessorPosition)170     public void setNoDeoptSuccessorPosition(NodeSourcePosition noDeoptSuccessorPosition) {
171         this.noDeoptSuccessorPosition = noDeoptSuccessorPosition;
172     }
173 }
174