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