1 /* 2 * Copyright (c) 2011, 2017, 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 package org.graalvm.compiler.nodes.memory; 24 25 import static org.graalvm.compiler.nodeinfo.InputType.Memory; 26 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; 27 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; 28 29 import org.graalvm.compiler.core.common.LIRKind; 30 import org.graalvm.compiler.core.common.type.ObjectStamp; 31 import org.graalvm.compiler.core.common.type.Stamp; 32 import org.graalvm.compiler.debug.DebugCloseable; 33 import org.graalvm.compiler.graph.Node; 34 import org.graalvm.compiler.graph.NodeClass; 35 import org.graalvm.compiler.graph.spi.Canonicalizable; 36 import org.graalvm.compiler.graph.spi.CanonicalizerTool; 37 import org.graalvm.compiler.nodeinfo.NodeInfo; 38 import org.graalvm.compiler.nodes.ValueNodeUtil; 39 import org.graalvm.compiler.nodes.ValuePhiNode; 40 import org.graalvm.compiler.nodes.extended.GuardingNode; 41 import org.graalvm.compiler.nodes.memory.address.AddressNode; 42 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 43 import org.graalvm.word.LocationIdentity; 44 45 /** 46 * A floating read of a value from memory specified in terms of an object base and an object 47 * relative location. This node does not null check the object. 48 */ 49 @NodeInfo(nameTemplate = "Read#{p#location/s}", cycles = CYCLES_2, size = SIZE_1) 50 public final class FloatingReadNode extends FloatingAccessNode implements LIRLowerableAccess, Canonicalizable { 51 public static final NodeClass<FloatingReadNode> TYPE = NodeClass.create(FloatingReadNode.class); 52 53 @OptionalInput(Memory) MemoryNode lastLocationAccess; 54 55 public FloatingReadNode(AddressNode address, LocationIdentity location, MemoryNode lastLocationAccess, Stamp stamp) { 56 this(address, location, lastLocationAccess, stamp, null, BarrierType.NONE); 57 } 58 59 public FloatingReadNode(AddressNode address, LocationIdentity location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard) { 60 this(address, location, lastLocationAccess, stamp, guard, BarrierType.NONE); 61 } 62 63 public FloatingReadNode(AddressNode address, LocationIdentity location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType) { 64 super(TYPE, address, location, stamp, guard, barrierType); 65 this.lastLocationAccess = lastLocationAccess; 66 67 // The input to floating reads must be always non-null or have at least a guard. 68 assert guard != null || !(address.getBase().stamp() instanceof ObjectStamp) || address.getBase() instanceof ValuePhiNode || 69 ((ObjectStamp) address.getBase().stamp()).nonNull() : address.getBase(); 70 } 71 72 @Override 73 public MemoryNode getLastLocationAccess() { 74 return lastLocationAccess; 75 } 76 77 @Override 78 public void setLastLocationAccess(MemoryNode newlla) { 79 updateUsages(ValueNodeUtil.asNode(lastLocationAccess), ValueNodeUtil.asNode(newlla)); 80 lastLocationAccess = newlla; 81 } 82 83 @Override 84 public void generate(NodeLIRBuilderTool gen) { 85 LIRKind readKind = gen.getLIRGeneratorTool().getLIRKind(stamp()); 86 gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitLoad(readKind, gen.operand(address), null)); 87 } 88 89 @Override 90 public Node canonical(CanonicalizerTool tool) { 91 Node result = ReadNode.canonicalizeRead(this, getAddress(), getLocationIdentity(), tool); 92 if (result != this) { 93 return result; 94 } 95 if (tool.canonicalizeReads() && getAddress().hasMoreThanOneUsage() && lastLocationAccess instanceof WriteNode) { 96 WriteNode write = (WriteNode) lastLocationAccess; 97 if (write.getAddress() == getAddress() && write.getAccessStamp().isCompatible(getAccessStamp())) { 98 // Same memory location with no intervening write 99 return write.value(); 100 } 101 } 102 return this; 103 } 104 105 @SuppressWarnings("try") 106 @Override 107 public FixedAccessNode asFixedNode() { 108 try (DebugCloseable position = withNodeSourcePosition()) { 109 ReadNode result = graph().add(new ReadNode(getAddress(), getLocationIdentity(), stamp(), getBarrierType())); 110 result.setGuard(getGuard()); 111 return result; 112 } 113 } 114 115 @Override 116 public boolean verify() { 117 MemoryNode lla = getLastLocationAccess(); 118 assert lla != null || getLocationIdentity().isImmutable() : "lastLocationAccess of " + this + " shouldn't be null for mutable location identity " + getLocationIdentity(); 119 return super.verify(); 120 } 121 122 @Override 123 public Stamp getAccessStamp() { 124 return stamp(); 125 } 126 }