1 /*
   2  * Copyright (c) 2013, 2018, 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
  55     public LogicNode getCondition() {
  56         return condition;
  57     }
  58 
  59     public LogicNode condition() {
  60         return getCondition();
  61     }
  62 
  63     @Override
  64     public void setCondition(LogicNode x, boolean negated) {
  65         updateUsages(condition, x);
  66         condition = x;
  67         this.negated = negated;
  68     }
  69 
  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 
  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
  88     public DeoptimizationReason getReason() {
  89         return reason;
  90     }
  91 
  92     @Override
  93     public DeoptimizationAction getAction() {
  94         return action;
  95     }
  96 
  97     @Override
  98     public Speculation getSpeculation() {
  99         return speculation;
 100     }
 101 
 102     @Override
 103     public boolean isNegated() {
 104         return negated;
 105     }
 106 
 107     @Override
 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
 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")
 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
 150     public boolean canDeoptimize() {
 151         return true;
 152     }
 153 
 154     @Override
 155     public void setAction(DeoptimizationAction action) {
 156         this.action = action;
 157     }
 158 
 159     @Override
 160     public void setReason(DeoptimizationReason reason) {
 161         this.reason = reason;
 162     }
 163 
 164     @Override
 165     public NodeSourcePosition getNoDeoptSuccessorPosition() {
 166         return noDeoptSuccessorPosition;
 167     }
 168 
 169     @Override
 170     public void setNoDeoptSuccessorPosition(NodeSourcePosition noDeoptSuccessorPosition) {
 171         this.noDeoptSuccessorPosition = noDeoptSuccessorPosition;
 172     }
 173 }