IsNullNode.java revision 12651:6ef01bd40ce2
1283766Sgrembo/*
2283766Sgrembo * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
3283766Sgrembo * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4283766Sgrembo *
5283766Sgrembo * This code is free software; you can redistribute it and/or modify it
6283766Sgrembo * under the terms of the GNU General Public License version 2 only, as
7283766Sgrembo * published by the Free Software Foundation.
8283766Sgrembo *
9283766Sgrembo * This code is distributed in the hope that it will be useful, but WITHOUT
10283766Sgrembo * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11283766Sgrembo * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12283766Sgrembo * version 2 for more details (a copy is included in the LICENSE file that
13283766Sgrembo * accompanied this code).
14283766Sgrembo *
15283766Sgrembo * You should have received a copy of the GNU General Public License version
16283766Sgrembo * 2 along with this work; if not, write to the Free Software Foundation,
17283766Sgrembo * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18283766Sgrembo *
19283766Sgrembo * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20283766Sgrembo * or visit www.oracle.com if you need additional information or have any
21283766Sgrembo * questions.
22283766Sgrembo */
23283766Sgrembopackage org.graalvm.compiler.nodes.calc;
24283766Sgrembo
25283766Sgremboimport org.graalvm.compiler.core.common.type.AbstractPointerStamp;
26283766Sgremboimport org.graalvm.compiler.core.common.type.ObjectStamp;
27283766Sgremboimport org.graalvm.compiler.core.common.type.Stamp;
28283766Sgremboimport org.graalvm.compiler.core.common.type.StampFactory;
29283766Sgremboimport org.graalvm.compiler.graph.NodeClass;
30283766Sgremboimport org.graalvm.compiler.graph.spi.CanonicalizerTool;
31283766Sgremboimport org.graalvm.compiler.nodeinfo.NodeCycles;
32283766Sgremboimport org.graalvm.compiler.nodeinfo.NodeInfo;
33283766Sgremboimport org.graalvm.compiler.nodes.LogicConstantNode;
34283766Sgremboimport org.graalvm.compiler.nodes.LogicNode;
35283766Sgremboimport org.graalvm.compiler.nodes.PiNode;
36283766Sgremboimport org.graalvm.compiler.nodes.UnaryOpLogicNode;
37283766Sgremboimport org.graalvm.compiler.nodes.ValueNode;
38283766Sgremboimport org.graalvm.compiler.nodes.spi.LIRLowerable;
39283766Sgremboimport org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
40283766Sgremboimport org.graalvm.compiler.nodes.spi.PiPushable;
41283766Sgremboimport org.graalvm.compiler.nodes.spi.Virtualizable;
42283766Sgremboimport org.graalvm.compiler.nodes.spi.VirtualizerTool;
43283766Sgremboimport org.graalvm.compiler.nodes.type.StampTool;
44283766Sgrembo
45283766Sgremboimport jdk.vm.ci.meta.TriState;
46283766Sgrembo
47283766Sgrembo/**
48283766Sgrembo * An IsNullNode will be true if the supplied value is null, and false if it is non-null.
49283766Sgrembo */
50310517Savg@NodeInfo(cycles = NodeCycles.CYCLES_2)
51310517Savgpublic final class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, Virtualizable, PiPushable {
52310517Savg
53310517Savg    public static final NodeClass<IsNullNode> TYPE = NodeClass.create(IsNullNode.class);
54283766Sgrembo
55283766Sgrembo    public IsNullNode(ValueNode object) {
56310517Savg        super(TYPE, object);
57310517Savg        assert object != null;
58283766Sgrembo    }
59283766Sgrembo
60283766Sgrembo    public static LogicNode create(ValueNode forValue) {
61283766Sgrembo        LogicNode result = tryCanonicalize(forValue);
62283766Sgrembo        return result == null ? new IsNullNode(forValue) : result;
63283766Sgrembo    }
64283766Sgrembo
65283766Sgrembo    public static LogicNode tryCanonicalize(ValueNode forValue) {
66283766Sgrembo        if (StampTool.isPointerAlwaysNull(forValue)) {
67283766Sgrembo            return LogicConstantNode.tautology();
68283766Sgrembo        } else if (StampTool.isPointerNonNull(forValue)) {
69283766Sgrembo            return LogicConstantNode.contradiction();
70283766Sgrembo        }
71283766Sgrembo        return null;
72283766Sgrembo    }
73283766Sgrembo
74283766Sgrembo    @Override
75283766Sgrembo    public void generate(NodeLIRBuilderTool gen) {
76283766Sgrembo        // Nothing to do.
77283766Sgrembo    }
78283766Sgrembo
79283766Sgrembo    @Override
80339029Sgonzo    public boolean verify() {
81283766Sgrembo        assertTrue(getValue() != null, "is null input must not be null");
82283766Sgrembo        assertTrue(getValue().stamp() instanceof AbstractPointerStamp, "input must be a pointer not %s", getValue().stamp());
83283766Sgrembo        return super.verify();
84283766Sgrembo    }
85283766Sgrembo
86283766Sgrembo    @Override
87283766Sgrembo    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
88283766Sgrembo        LogicNode result = tryCanonicalize(forValue);
89283766Sgrembo        return result == null ? this : result;
90283766Sgrembo    }
91283766Sgrembo
92283766Sgrembo    @Override
93283766Sgrembo    public void virtualize(VirtualizerTool tool) {
94283766Sgrembo        ValueNode alias = tool.getAlias(getValue());
95339029Sgonzo        TriState fold = tryFold(alias.stamp());
96283766Sgrembo        if (fold != TriState.UNKNOWN) {
97339029Sgonzo            tool.replaceWithValue(LogicConstantNode.forBoolean(fold.isTrue(), graph()));
98283766Sgrembo        }
99283766Sgrembo    }
100283766Sgrembo
101283766Sgrembo    @Override
102283766Sgrembo    public boolean push(PiNode parent) {
103283766Sgrembo        if (parent.stamp() instanceof ObjectStamp && parent.object().stamp() instanceof ObjectStamp) {
104283766Sgrembo            ObjectStamp piStamp = (ObjectStamp) parent.stamp();
105283766Sgrembo            ObjectStamp piValueStamp = (ObjectStamp) parent.object().stamp();
106283766Sgrembo            if (piStamp.nonNull() == piValueStamp.nonNull() && piStamp.alwaysNull() == piValueStamp.alwaysNull()) {
107283766Sgrembo                replaceFirstInput(parent, parent.object());
108283766Sgrembo                return true;
109283766Sgrembo            }
110283766Sgrembo        }
111283766Sgrembo        return false;
112283766Sgrembo    }
113339029Sgonzo
114283766Sgrembo    @NodeIntrinsic
115331834Sgonzo    public static native IsNullNode isNull(Object object);
116283766Sgrembo
117283766Sgrembo    @Override
118331834Sgonzo    public Stamp getSucceedingStampForValue(boolean negated) {
119283766Sgrembo        return negated ? getValue().stamp().join(StampFactory.objectNonNull()) : StampFactory.alwaysNull();
120331834Sgonzo    }
121331834Sgonzo
122331834Sgonzo    @Override
123331834Sgonzo    public TriState tryFold(Stamp valueStamp) {
124339029Sgonzo        if (valueStamp instanceof ObjectStamp) {
125339029Sgonzo            ObjectStamp objectStamp = (ObjectStamp) valueStamp;
126339029Sgonzo            if (objectStamp.alwaysNull()) {
127331834Sgonzo                return TriState.TRUE;
128283766Sgrembo            } else if (objectStamp.nonNull()) {
129331834Sgonzo                return TriState.FALSE;
130331834Sgonzo            }
131283766Sgrembo        }
132331834Sgonzo        return TriState.UNKNOWN;
133283766Sgrembo    }
134283766Sgrembo}
135283766Sgrembo