ReadNode.java revision 12968:4d8a004e5c6d
11573Srgrimes/*
21573Srgrimes * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
31573Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41573Srgrimes *
51573Srgrimes * This code is free software; you can redistribute it and/or modify it
61573Srgrimes * under the terms of the GNU General Public License version 2 only, as
71573Srgrimes * published by the Free Software Foundation.
81573Srgrimes *
91573Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT
101573Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
111573Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
121573Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
131573Srgrimes * accompanied this code).
141573Srgrimes *
151573Srgrimes * You should have received a copy of the GNU General Public License version
161573Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
171573Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
181573Srgrimes *
191573Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
201573Srgrimes * or visit www.oracle.com if you need additional information or have any
211573Srgrimes * questions.
221573Srgrimes */
231573Srgrimespackage org.graalvm.compiler.nodes.memory;
241573Srgrimes
251573Srgrimesimport static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
261573Srgrimesimport static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
271573Srgrimesimport static org.graalvm.compiler.nodes.NamedLocationIdentity.ARRAY_LENGTH_LOCATION;
281573Srgrimes
2950476Speterimport org.graalvm.compiler.core.common.LIRKind;
301573Srgrimesimport org.graalvm.compiler.core.common.LocationIdentity;
31268857Sjillesimport org.graalvm.compiler.core.common.type.Stamp;
321573Srgrimesimport org.graalvm.compiler.debug.DebugCloseable;
331573Srgrimesimport org.graalvm.compiler.debug.GraalError;
341573Srgrimesimport org.graalvm.compiler.graph.Node;
351573Srgrimesimport org.graalvm.compiler.graph.NodeClass;
36146186Sdelphijimport org.graalvm.compiler.graph.spi.Canonicalizable;
37202274Sedimport org.graalvm.compiler.graph.spi.CanonicalizerTool;
381573Srgrimesimport org.graalvm.compiler.nodeinfo.InputType;
3959460Sphantomimport org.graalvm.compiler.nodeinfo.NodeInfo;
4059460Sphantomimport org.graalvm.compiler.nodes.CanonicalizableLocation;
411573Srgrimesimport org.graalvm.compiler.nodes.ConstantNode;
4284306Sruimport org.graalvm.compiler.nodes.FrameState;
431573Srgrimesimport org.graalvm.compiler.nodes.ValueNode;
441573Srgrimesimport org.graalvm.compiler.nodes.extended.GuardingNode;
45146186Sdelphijimport org.graalvm.compiler.nodes.memory.address.AddressNode;
46143305Sphkimport org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
471573Srgrimesimport org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
481573Srgrimesimport org.graalvm.compiler.nodes.spi.Virtualizable;
491573Srgrimesimport org.graalvm.compiler.nodes.spi.VirtualizerTool;
50202930Sedimport org.graalvm.compiler.nodes.util.GraphUtil;
511573Srgrimes
521573Srgrimesimport jdk.vm.ci.meta.Constant;
531573Srgrimesimport jdk.vm.ci.meta.MetaAccessProvider;
541573Srgrimes
551573Srgrimes/**
561573Srgrimes * Reads an {@linkplain FixedAccessNode accessed} value.
571573Srgrimes */
581573Srgrimes@NodeInfo(nameTemplate = "Read#{p#location/s}", cycles = CYCLES_2, size = SIZE_1)
591573Srgrimespublic class ReadNode extends FloatableAccessNode implements LIRLowerableAccess, Canonicalizable, Virtualizable, GuardingNode {
601573Srgrimes
611573Srgrimes    public static final NodeClass<ReadNode> TYPE = NodeClass.create(ReadNode.class);
621573Srgrimes
631573Srgrimes    public ReadNode(AddressNode address, LocationIdentity location, Stamp stamp, BarrierType barrierType) {
641573Srgrimes        this(TYPE, address, location, stamp, null, barrierType, false, null);
651573Srgrimes    }
66146186Sdelphij
671573Srgrimes    protected ReadNode(NodeClass<? extends ReadNode> c, AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck,
68147402Sru                    FrameState stateBefore) {
69146186Sdelphij        super(c, address, location, stamp, guard, barrierType, nullCheck, stateBefore);
70147402Sru    }
71146186Sdelphij
72146186Sdelphij    @Override
73147402Sru    public void generate(NodeLIRBuilderTool gen) {
74146186Sdelphij        LIRKind readKind = gen.getLIRGeneratorTool().getLIRKind(getAccessStamp());
75147402Sru        gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitLoad(readKind, gen.operand(address), gen.state(this)));
76146186Sdelphij    }
771573Srgrimes
781573Srgrimes    @Override
79268857Sjilles    public Node canonical(CanonicalizerTool tool) {
80268857Sjilles        if (tool.allUsagesAvailable() && hasNoUsages()) {
81268857Sjilles            // Read without usages or guard can be safely removed.
82268857Sjilles            return null;
83268857Sjilles        }
84268857Sjilles        if (!getNullCheck()) {
85268857Sjilles            return canonicalizeRead(this, getAddress(), getLocationIdentity(), tool);
86268857Sjilles        } else {
871573Srgrimes            // if this read is a null check, then replacing it with the value is incorrect for
881573Srgrimes            // guard-type usages
891573Srgrimes            return this;
901573Srgrimes        }
9167967Sasmodai    }
921573Srgrimes
931573Srgrimes    @SuppressWarnings("try")
941573Srgrimes    @Override
95146186Sdelphij    public FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess) {
96146186Sdelphij        try (DebugCloseable position = withNodeSourcePosition()) {
97147402Sru            return graph().unique(new FloatingReadNode(getAddress(), getLocationIdentity(), lastLocationAccess, stamp(), getGuard(), getBarrierType()));
98147402Sru        }
99146186Sdelphij    }
100268857Sjilles
101146186Sdelphij    @Override
102268857Sjilles    public boolean isAllowedUsageType(InputType type) {
103147402Sru        return (getNullCheck() && type == InputType.Guard) ? true : super.isAllowedUsageType(type);
104146186Sdelphij    }
105147402Sru
106146186Sdelphij    public static ValueNode canonicalizeRead(ValueNode read, AddressNode address, LocationIdentity locationIdentity, CanonicalizerTool tool) {
107268857Sjilles        MetaAccessProvider metaAccess = tool.getMetaAccess();
108268857Sjilles        if (tool.canonicalizeReads() && address instanceof OffsetAddressNode) {
109268857Sjilles            OffsetAddressNode objAddress = (OffsetAddressNode) address;
110268857Sjilles            ValueNode object = objAddress.getBase();
111268857Sjilles            if (metaAccess != null && object.isConstant() && !object.isNullConstant() && objAddress.getOffset().isConstant()) {
112268857Sjilles                long displacement = objAddress.getOffset().asJavaConstant().asLong();
113268857Sjilles                int stableDimension = ((ConstantNode) object).getStableDimension();
114268857Sjilles                if (locationIdentity.isImmutable() || stableDimension > 0) {
115268857Sjilles                    Constant constant = read.stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), object.asConstant(), displacement);
116268857Sjilles                    boolean isDefaultStable = locationIdentity.isImmutable() || ((ConstantNode) object).isDefaultStable();
117146186Sdelphij                    if (constant != null && (isDefaultStable || !constant.isDefaultForKind())) {
118147402Sru                        return ConstantNode.forConstant(read.stamp(), constant, Math.max(stableDimension - 1, 0), isDefaultStable, metaAccess);
119146186Sdelphij                    }
120147402Sru                }
121146186Sdelphij            }
1221573Srgrimes            if (locationIdentity.equals(ARRAY_LENGTH_LOCATION)) {
1231573Srgrimes                ValueNode length = GraphUtil.arrayLength(object);
124202930Sed                if (length != null) {
125202930Sed                    return length;
126202930Sed                }
127202930Sed            }
1281573Srgrimes            if (locationIdentity instanceof CanonicalizableLocation) {
129147402Sru                CanonicalizableLocation canonicalize = (CanonicalizableLocation) locationIdentity;
130202274Sed                ValueNode result = canonicalize.canonicalizeRead(read, address, object, tool);
1311573Srgrimes                assert result != null && result.stamp().isCompatible(read.stamp());
132202274Sed                return result;
133147402Sru            }
1341573Srgrimes
1351573Srgrimes        }
136147402Sru        return read;
137146186Sdelphij    }
138147402Sru
139146186Sdelphij    @Override
140146186Sdelphij    public void virtualize(VirtualizerTool tool) {
141        throw GraalError.shouldNotReachHere("unexpected ReadNode before PEA");
142    }
143
144    @Override
145    public boolean canNullCheck() {
146        return true;
147    }
148
149    @Override
150    public Stamp getAccessStamp() {
151        return stamp();
152    }
153}
154