1 /* 2 * Copyright (c) 2011, 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.Guard; 26 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; 27 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; 28 29 import org.graalvm.compiler.graph.IterableNodeType; 30 import org.graalvm.compiler.graph.NodeClass; 31 import org.graalvm.compiler.graph.spi.SimplifierTool; 32 import org.graalvm.compiler.nodeinfo.NodeInfo; 33 import org.graalvm.compiler.nodes.extended.ValueAnchorNode; 34 import org.graalvm.compiler.nodes.spi.Lowerable; 35 import org.graalvm.compiler.nodes.spi.LoweringTool; 36 37 import jdk.vm.ci.meta.DeoptimizationAction; 38 import jdk.vm.ci.meta.DeoptimizationReason; 39 import jdk.vm.ci.meta.JavaConstant; 40 41 @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}", allowedUsageTypes = Guard, size = SIZE_2, cycles = CYCLES_2) 42 public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType { 43 public static final NodeClass<FixedGuardNode> TYPE = NodeClass.create(FixedGuardNode.class); 44 45 public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) { 46 this(condition, deoptReason, action, JavaConstant.NULL_POINTER, false); 47 } 48 49 public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { 50 this(condition, deoptReason, action, JavaConstant.NULL_POINTER, negated); 51 } 52 53 public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, JavaConstant speculation, boolean negated) { 54 super(TYPE, condition, deoptReason, action, speculation, negated); 55 } 56 57 @Override 58 public void simplify(SimplifierTool tool) { 59 super.simplify(tool); 60 61 if (getCondition() instanceof LogicConstantNode) { 62 LogicConstantNode c = (LogicConstantNode) getCondition(); 63 if (c.getValue() == isNegated()) { 64 FixedNode currentNext = this.next(); 65 if (currentNext != null) { 66 tool.deleteBranch(currentNext); 67 } 68 69 DeoptimizeNode deopt = graph().add(new DeoptimizeNode(getAction(), getReason(), getSpeculation())); 70 deopt.setStateBefore(stateBefore()); 71 setNext(deopt); 72 } 73 this.replaceAtUsages(null); 74 graph().removeFixed(this); 75 } else if (getCondition() instanceof ShortCircuitOrNode) { 76 ShortCircuitOrNode shortCircuitOr = (ShortCircuitOrNode) getCondition(); 77 if (isNegated() && hasNoUsages()) { 78 graph().addAfterFixed(this, graph().add(new FixedGuardNode(shortCircuitOr.getY(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isYNegated()))); 79 graph().replaceFixedWithFixed(this, graph().add(new FixedGuardNode(shortCircuitOr.getX(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isXNegated()))); 80 } 81 } 82 } 83 84 @Override 85 public void lower(LoweringTool tool) { 86 if (graph().getGuardsStage().allowsFloatingGuards()) { 87 /* 88 * Don't allow guards with action None and reason RuntimeConstraint to float. In cases 89 * where 2 guards are testing equivalent conditions they might be lowered at the same 90 * location. If the guard with the None action is lowered before the the other guard 91 * then the code will be stuck repeatedly deoptimizing without invalidating the code. 92 * Conditional elimination will eliminate the guard if it's truly redundant in this 93 * case. 94 */ 95 if (getAction() != DeoptimizationAction.None || getReason() != DeoptimizationReason.RuntimeConstraint) { 96 ValueNode guard = tool.createGuard(this, getCondition(), getReason(), getAction(), getSpeculation(), isNegated()).asNode(); 97 this.replaceAtUsages(guard); 98 ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(guard.asNode())); 99 graph().replaceFixedWithFixed(this, newAnchor); 100 } 101 } else { 102 lowerToIf().lower(tool); 103 } 104 } 105 106 @Override 107 public boolean canDeoptimize() { 108 return true; 109 } 110 }