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