001/* 002 * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.nodes; 024 025import jdk.internal.jvmci.meta.*; 026 027import com.oracle.graal.compiler.common.type.*; 028import com.oracle.graal.graph.*; 029import com.oracle.graal.graph.spi.*; 030import com.oracle.graal.nodeinfo.*; 031import com.oracle.graal.nodes.extended.*; 032 033/** 034 * A guard is a node that deoptimizes based on a conditional expression. Guards are not attached to 035 * a certain frame state, they can move around freely and will always use the correct frame state 036 * when the nodes are scheduled (i.e., the last emitted frame state). The node that is guarded has a 037 * data dependency on the guard and the guard in turn has a data dependency on the condition. A 038 * guard may only be executed if it is guaranteed that the guarded node is executed too (if no 039 * exceptions are thrown). Therefore, an anchor is placed after a control flow split and the guard 040 * has a data dependency to the anchor. The anchor is the most distant node that is post-dominated 041 * by the guarded node and the guard can be scheduled anywhere between those two nodes. This ensures 042 * maximum flexibility for the guard node and guarantees that deoptimization occurs only if the 043 * control flow would have reached the guarded node (without taking exceptions into account). 044 */ 045@NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {InputType.Guard}) 046public class GuardNode extends FloatingAnchoredNode implements Canonicalizable, GuardingNode { 047 048 public static final NodeClass<GuardNode> TYPE = NodeClass.create(GuardNode.class); 049 @Input(InputType.Condition) protected LogicNode condition; 050 protected final DeoptimizationReason reason; 051 protected JavaConstant speculation; 052 protected DeoptimizationAction action; 053 protected boolean negated; 054 055 public GuardNode(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, JavaConstant speculation) { 056 this(TYPE, condition, anchor, reason, action, negated, speculation); 057 } 058 059 protected GuardNode(NodeClass<? extends GuardNode> c, LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, JavaConstant speculation) { 060 super(c, StampFactory.forVoid(), anchor); 061 this.condition = condition; 062 this.reason = reason; 063 this.action = action; 064 this.negated = negated; 065 this.speculation = speculation; 066 } 067 068 /** 069 * The instruction that produces the tested boolean value. 070 */ 071 public LogicNode condition() { 072 return condition; 073 } 074 075 public boolean isNegated() { 076 return negated; 077 } 078 079 public DeoptimizationReason reason() { 080 return reason; 081 } 082 083 public DeoptimizationAction action() { 084 return action; 085 } 086 087 public JavaConstant getSpeculation() { 088 return speculation; 089 } 090 091 public void setSpeculation(JavaConstant speculation) { 092 this.speculation = speculation; 093 } 094 095 @Override 096 public String toString(Verbosity verbosity) { 097 if (verbosity == Verbosity.Name && negated) { 098 return "!" + super.toString(verbosity); 099 } else { 100 return super.toString(verbosity); 101 } 102 } 103 104 @Override 105 public Node canonical(CanonicalizerTool tool) { 106 if (condition() instanceof LogicNegationNode) { 107 LogicNegationNode negation = (LogicNegationNode) condition(); 108 return new GuardNode(negation.getValue(), getAnchor(), reason, action, !negated, speculation); 109 } 110 if (condition() instanceof LogicConstantNode) { 111 LogicConstantNode c = (LogicConstantNode) condition(); 112 if (c.getValue() != negated) { 113 return null; 114 } 115 } 116 return this; 117 } 118 119 public FixedWithNextNode lowerGuard() { 120 return null; 121 } 122 123 public void negate() { 124 negated = !negated; 125 } 126 127 public void setAction(DeoptimizationAction invalidaterecompile) { 128 this.action = invalidaterecompile; 129 } 130}