1 /*
2  * Copyright (c) 2011, 2014, 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 static org.graalvm.compiler.nodeinfo.InputType.Condition;
28 import static org.graalvm.compiler.nodeinfo.InputType.Guard;
29 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
30 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
31 
32 import org.graalvm.compiler.core.common.type.StampFactory;
33 import org.graalvm.compiler.graph.IterableNodeType;
34 import org.graalvm.compiler.graph.Node;
35 import org.graalvm.compiler.graph.NodeClass;
36 import org.graalvm.compiler.graph.NodeSourcePosition;
37 import org.graalvm.compiler.graph.spi.Canonicalizable;
38 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
39 import org.graalvm.compiler.nodeinfo.NodeInfo;
40 import org.graalvm.compiler.nodeinfo.Verbosity;
41 import org.graalvm.compiler.nodes.extended.AnchoringNode;
42 import org.graalvm.compiler.nodes.extended.GuardingNode;
43 
44 import jdk.vm.ci.meta.DeoptimizationAction;
45 import jdk.vm.ci.meta.DeoptimizationReason;
46 import jdk.vm.ci.meta.SpeculationLog.Speculation;
47 
48 /**
49  * A guard is a node that deoptimizes based on a conditional expression. Guards are not attached to
50  * a certain frame state, they can move around freely and will always use the correct frame state
51  * when the nodes are scheduled (i.e., the last emitted frame state). The node that is guarded has a
52  * data dependency on the guard and the guard in turn has a data dependency on the condition. A
53  * guard may only be executed if it is guaranteed that the guarded node is executed too (if no
54  * exceptions are thrown). Therefore, an anchor is placed after a control flow split and the guard
55  * has a data dependency to the anchor. The anchor is the most distant node that is post-dominated
56  * by the guarded node and the guard can be scheduled anywhere between those two nodes. This ensures
57  * maximum flexibility for the guard node and guarantees that deoptimization occurs only if the
58  * control flow would have reached the guarded node (without taking exceptions into account).
59  */
60 @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {Guard}, size = SIZE_2, cycles = CYCLES_2)
61 public class GuardNode extends FloatingAnchoredNode implements Canonicalizable, GuardingNode, DeoptimizingGuard, IterableNodeType {
62 
63     public static final NodeClass<GuardNode> TYPE = NodeClass.create(GuardNode.class);
64     @Input(Condition) protected LogicNode condition;
65     protected DeoptimizationReason reason;
66     protected DeoptimizationAction action;
67     protected Speculation speculation;
68     protected boolean negated;
69     protected NodeSourcePosition noDeoptSuccessorPosition;
70 
GuardNode(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, Speculation speculation, NodeSourcePosition noDeoptSuccessorPosition)71     public GuardNode(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, Speculation speculation,
72                     NodeSourcePosition noDeoptSuccessorPosition) {
73         this(TYPE, condition, anchor, reason, action, negated, speculation, noDeoptSuccessorPosition);
74     }
75 
GuardNode(NodeClass<? extends GuardNode> c, LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, Speculation speculation, NodeSourcePosition noDeoptSuccessorPosition)76     protected GuardNode(NodeClass<? extends GuardNode> c, LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated,
77                     Speculation speculation, NodeSourcePosition noDeoptSuccessorPosition) {
78         super(c, StampFactory.forVoid(), anchor);
79         this.condition = condition;
80         this.reason = reason;
81         this.action = action;
82         this.negated = negated;
83         this.speculation = speculation;
84         this.noDeoptSuccessorPosition = noDeoptSuccessorPosition;
85     }
86 
87     /**
88      * The instruction that produces the tested boolean value.
89      */
90     @Override
getCondition()91     public LogicNode getCondition() {
92         return condition;
93     }
94 
95     @Override
setCondition(LogicNode x, boolean negated)96     public void setCondition(LogicNode x, boolean negated) {
97         updateUsages(condition, x);
98         condition = x;
99         this.negated = negated;
100     }
101 
102     @Override
isNegated()103     public boolean isNegated() {
104         return negated;
105     }
106 
107     @Override
getReason()108     public DeoptimizationReason getReason() {
109         return reason;
110     }
111 
112     @Override
getAction()113     public DeoptimizationAction getAction() {
114         return action;
115     }
116 
117     @Override
getSpeculation()118     public Speculation getSpeculation() {
119         return speculation;
120     }
121 
setSpeculation(Speculation speculation)122     public void setSpeculation(Speculation speculation) {
123         this.speculation = speculation;
124     }
125 
126     @Override
toString(Verbosity verbosity)127     public String toString(Verbosity verbosity) {
128         if (verbosity == Verbosity.Name && negated) {
129             return "!" + super.toString(verbosity);
130         } else {
131             return super.toString(verbosity);
132         }
133     }
134 
135     @Override
canonical(CanonicalizerTool tool)136     public Node canonical(CanonicalizerTool tool) {
137         if (getCondition() instanceof LogicNegationNode) {
138             LogicNegationNode negation = (LogicNegationNode) getCondition();
139             return new GuardNode(negation.getValue(), getAnchor(), reason, action, !negated, speculation, noDeoptSuccessorPosition);
140         }
141         if (getCondition() instanceof LogicConstantNode) {
142             LogicConstantNode c = (LogicConstantNode) getCondition();
143             if (c.getValue() != negated) {
144                 return null;
145             }
146         }
147         return this;
148     }
149 
lowerGuard()150     public FixedWithNextNode lowerGuard() {
151         return null;
152     }
153 
negate()154     public void negate() {
155         negated = !negated;
156     }
157 
158     @Override
setAction(DeoptimizationAction invalidaterecompile)159     public void setAction(DeoptimizationAction invalidaterecompile) {
160         this.action = invalidaterecompile;
161     }
162 
163     @Override
setReason(DeoptimizationReason reason)164     public void setReason(DeoptimizationReason reason) {
165         this.reason = reason;
166     }
167 
168     @Override
getNoDeoptSuccessorPosition()169     public NodeSourcePosition getNoDeoptSuccessorPosition() {
170         return noDeoptSuccessorPosition;
171     }
172 
173     @Override
setNoDeoptSuccessorPosition(NodeSourcePosition noDeoptSuccessorPosition)174     public void setNoDeoptSuccessorPosition(NodeSourcePosition noDeoptSuccessorPosition) {
175         this.noDeoptSuccessorPosition = noDeoptSuccessorPosition;
176     }
177 }
178