LoadFieldNode.java revision 12651:6ef01bd40ce2
1195033Salc/*
2195033Salc * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
3195033Salc * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4195033Salc *
5195033Salc * This code is free software; you can redistribute it and/or modify it
6195033Salc * under the terms of the GNU General Public License version 2 only, as
7195033Salc * published by the Free Software Foundation.
8195033Salc *
9195033Salc * This code is distributed in the hope that it will be useful, but WITHOUT
10195033Salc * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11195033Salc * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12195033Salc * version 2 for more details (a copy is included in the LICENSE file that
13195033Salc * accompanied this code).
14195033Salc *
15195033Salc * You should have received a copy of the GNU General Public License version
16195033Salc * 2 along with this work; if not, write to the Free Software Foundation,
17195033Salc * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18195033Salc *
19195033Salc * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20195033Salc * or visit www.oracle.com if you need additional information or have any
21195033Salc * questions.
22195033Salc */
23195033Salcpackage org.graalvm.compiler.nodes.java;
24195033Salc
25195033Salcimport static org.graalvm.compiler.graph.iterators.NodePredicates.isNotA;
26195033Salc
27195033Salcimport org.graalvm.compiler.core.common.type.Stamp;
28195033Salcimport org.graalvm.compiler.core.common.type.StampFactory;
29195033Salcimport org.graalvm.compiler.core.common.type.StampPair;
30195033Salcimport org.graalvm.compiler.graph.NodeClass;
31195033Salcimport org.graalvm.compiler.graph.spi.Canonicalizable;
32195649Salcimport org.graalvm.compiler.graph.spi.CanonicalizerTool;
33195649Salcimport org.graalvm.compiler.nodeinfo.NodeInfo;
34195033Salcimport org.graalvm.compiler.nodes.ConstantNode;
35195060Salcimport org.graalvm.compiler.nodes.DeoptimizeNode;
36import org.graalvm.compiler.nodes.PhiNode;
37import org.graalvm.compiler.nodes.ValueNode;
38import org.graalvm.compiler.nodes.ValuePhiNode;
39import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider;
40import org.graalvm.compiler.nodes.spi.Virtualizable;
41import org.graalvm.compiler.nodes.spi.VirtualizerTool;
42import org.graalvm.compiler.nodes.type.StampTool;
43import org.graalvm.compiler.nodes.util.ConstantFoldUtil;
44import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode;
45import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
46
47import jdk.vm.ci.meta.Assumptions;
48import jdk.vm.ci.meta.DeoptimizationAction;
49import jdk.vm.ci.meta.DeoptimizationReason;
50import jdk.vm.ci.meta.JavaConstant;
51import jdk.vm.ci.meta.MetaAccessProvider;
52import jdk.vm.ci.meta.ResolvedJavaField;
53
54/**
55 * The {@code LoadFieldNode} represents a read of a static or instance field.
56 */
57@NodeInfo(nameTemplate = "LoadField#{p#field/s}")
58public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable.Unary<ValueNode>, Virtualizable, UncheckedInterfaceProvider {
59
60    public static final NodeClass<LoadFieldNode> TYPE = NodeClass.create(LoadFieldNode.class);
61
62    private final Stamp uncheckedStamp;
63
64    protected LoadFieldNode(StampPair stamp, ValueNode object, ResolvedJavaField field) {
65        super(TYPE, stamp.getTrustedStamp(), object, field);
66        this.uncheckedStamp = stamp.getUncheckedStamp();
67    }
68
69    public static LoadFieldNode create(Assumptions assumptions, ValueNode object, ResolvedJavaField field) {
70        return new LoadFieldNode(StampFactory.forDeclaredType(assumptions, field.getType(), false), object, field);
71    }
72
73    public static LoadFieldNode createOverrideStamp(StampPair stamp, ValueNode object, ResolvedJavaField field) {
74        return new LoadFieldNode(stamp, object, field);
75    }
76
77    @Override
78    public ValueNode getValue() {
79        return object();
80    }
81
82    @Override
83    public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject) {
84        if (tool.allUsagesAvailable() && hasNoUsages() && !isVolatile() && (isStatic() || StampTool.isPointerNonNull(forObject.stamp()))) {
85            return null;
86        }
87        MetaAccessProvider metaAccess = tool.getMetaAccess();
88        if (tool.canonicalizeReads() && metaAccess != null) {
89            ConstantNode constant = asConstant(tool, forObject);
90            if (constant != null) {
91                return constant;
92            }
93            if (tool.allUsagesAvailable()) {
94                PhiNode phi = asPhi(tool, forObject);
95                if (phi != null) {
96                    return phi;
97                }
98            }
99        }
100        if (!isStatic() && forObject.isNullConstant()) {
101            return new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
102        }
103        return this;
104    }
105
106    /**
107     * Gets a constant value for this load if possible.
108     */
109    public ConstantNode asConstant(CanonicalizerTool tool, ValueNode forObject) {
110        if (isStatic()) {
111            return ConstantFoldUtil.tryConstantFold(tool.getConstantFieldProvider(), tool.getConstantReflection(), tool.getMetaAccess(), field(), null);
112        } else if (forObject.isConstant() && !forObject.isNullConstant()) {
113            return ConstantFoldUtil.tryConstantFold(tool.getConstantFieldProvider(), tool.getConstantReflection(), tool.getMetaAccess(), field(), forObject.asJavaConstant());
114        }
115        return null;
116    }
117
118    public ConstantNode asConstant(CanonicalizerTool tool, JavaConstant constant) {
119        return ConstantFoldUtil.tryConstantFold(tool.getConstantFieldProvider(), tool.getConstantReflection(), tool.getMetaAccess(), field(), constant);
120    }
121
122    private PhiNode asPhi(CanonicalizerTool tool, ValueNode forObject) {
123        if (!isStatic() && field.isFinal() && forObject instanceof ValuePhiNode && ((ValuePhiNode) forObject).values().filter(isNotA(ConstantNode.class)).isEmpty()) {
124            PhiNode phi = (PhiNode) forObject;
125            ConstantNode[] constantNodes = new ConstantNode[phi.valueCount()];
126            for (int i = 0; i < phi.valueCount(); i++) {
127                ConstantNode constant = ConstantFoldUtil.tryConstantFold(tool.getConstantFieldProvider(), tool.getConstantReflection(), tool.getMetaAccess(), field(), phi.valueAt(i).asJavaConstant());
128                if (constant == null) {
129                    return null;
130                }
131                constantNodes[i] = constant;
132            }
133            return new ValuePhiNode(stamp(), phi.merge(), constantNodes);
134        }
135        return null;
136    }
137
138    @Override
139    public void virtualize(VirtualizerTool tool) {
140        ValueNode alias = tool.getAlias(object());
141        if (alias instanceof VirtualObjectNode) {
142            int fieldIndex = ((VirtualInstanceNode) alias).fieldIndex(field());
143            if (fieldIndex != -1) {
144                tool.replaceWith(tool.getEntry((VirtualObjectNode) alias, fieldIndex));
145            }
146        }
147    }
148
149    @Override
150    public Stamp uncheckedStamp() {
151        return uncheckedStamp;
152    }
153}
154