1 /*
2  * Copyright (c) 2011, 2020, 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 
24 
25 package org.graalvm.compiler.nodes.extended;
26 
27 import static org.graalvm.compiler.nodeinfo.InputType.State;
28 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
29 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
30 
31 import org.graalvm.compiler.core.common.type.StampFactory;
32 import org.graalvm.compiler.graph.NodeClass;
33 import org.graalvm.compiler.nodeinfo.NodeInfo;
34 import org.graalvm.compiler.nodes.FrameState;
35 import org.graalvm.compiler.nodes.StateSplit;
36 import org.graalvm.compiler.nodes.ValueNode;
37 import org.graalvm.compiler.nodes.java.StoreFieldNode;
38 import org.graalvm.compiler.nodes.memory.SingleMemoryKill;
39 import org.graalvm.compiler.nodes.spi.Lowerable;
40 import org.graalvm.compiler.nodes.spi.Virtualizable;
41 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
42 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
43 import jdk.internal.vm.compiler.word.LocationIdentity;
44 
45 import jdk.vm.ci.meta.Assumptions;
46 import jdk.vm.ci.meta.JavaKind;
47 import jdk.vm.ci.meta.ResolvedJavaField;
48 
49 /**
50  * Store of a value at a location specified as an offset relative to an object. No null check is
51  * performed before the store.
52  */
53 @NodeInfo(cycles = CYCLES_2, size = SIZE_1)
54 public final class RawStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, SingleMemoryKill {
55 
56     public static final NodeClass<RawStoreNode> TYPE = NodeClass.create(RawStoreNode.class);
57     @Input ValueNode value;
58     @OptionalInput(State) FrameState stateAfter;
59     private final boolean needsBarrier;
60     private boolean isVolatile;
61 
RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity)62     public RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity) {
63         this(object, offset, value, accessKind, locationIdentity, true, false, null, false);
64     }
65 
RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity, boolean needsBarrier)66     public RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity, boolean needsBarrier) {
67         this(object, offset, value, accessKind, locationIdentity, needsBarrier, false, null, false);
68     }
69 
RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity, boolean needsBarrier, boolean isVolatile)70     public RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity, boolean needsBarrier, boolean isVolatile) {
71         this(object, offset, value, accessKind, locationIdentity, needsBarrier, isVolatile, null, false);
72     }
73 
RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity, boolean needsBarrier, FrameState stateAfter, boolean forceAnyLocation)74     public RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity, boolean needsBarrier, FrameState stateAfter,
75                     boolean forceAnyLocation) {
76         this(object, offset, value, accessKind, locationIdentity, needsBarrier, false, stateAfter, forceAnyLocation);
77     }
78 
RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity, boolean needsBarrier, boolean isVolatile, FrameState stateAfter, boolean forceAnyLocation)79     public RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity, boolean needsBarrier, boolean isVolatile, FrameState stateAfter,
80                     boolean forceAnyLocation) {
81         super(TYPE, StampFactory.forVoid(), object, offset, accessKind, locationIdentity, forceAnyLocation);
82         this.value = value;
83         this.needsBarrier = needsBarrier;
84         this.stateAfter = stateAfter;
85         this.isVolatile = isVolatile;
86         assert accessKind != JavaKind.Void && accessKind != JavaKind.Illegal;
87     }
88 
89     @NodeIntrinsic
storeObject(Object object, long offset, Object value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter boolean needsBarrier)90     public static native Object storeObject(Object object, long offset, Object value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity,
91                     @ConstantNodeParameter boolean needsBarrier);
92 
93     @NodeIntrinsic
storeChar(Object object, long offset, char value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity)94     public static native Object storeChar(Object object, long offset, char value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity);
95 
96     @NodeIntrinsic
storeByte(Object object, long offset, byte value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity)97     public static native Object storeByte(Object object, long offset, byte value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity);
98 
needsBarrier()99     public boolean needsBarrier() {
100         return needsBarrier;
101     }
102 
103     @Override
stateAfter()104     public FrameState stateAfter() {
105         return stateAfter;
106     }
107 
108     @Override
setStateAfter(FrameState x)109     public void setStateAfter(FrameState x) {
110         assert x == null || x.isAlive() : "frame state must be in a graph";
111         updateUsages(stateAfter, x);
112         stateAfter = x;
113     }
114 
115     @Override
hasSideEffect()116     public boolean hasSideEffect() {
117         return true;
118     }
119 
value()120     public ValueNode value() {
121         return value;
122     }
123 
124     @Override
virtualize(VirtualizerTool tool)125     public void virtualize(VirtualizerTool tool) {
126         ValueNode alias = tool.getAlias(object());
127         if (alias instanceof VirtualObjectNode) {
128             VirtualObjectNode virtual = (VirtualObjectNode) alias;
129             ValueNode indexValue = tool.getAlias(offset());
130             if (indexValue.isConstant()) {
131                 long off = indexValue.asJavaConstant().asLong();
132                 int entryIndex = virtual.entryIndexForOffset(tool.getMetaAccess(), off, accessKind());
133                 if (entryIndex != -1 && tool.setVirtualEntry(virtual, entryIndex, value(), accessKind(), off)) {
134                     tool.delete();
135                 }
136             }
137         }
138     }
139 
140     @Override
isVolatile()141     public boolean isVolatile() {
142         return isVolatile;
143     }
144 
145     @Override
cloneAsFieldAccess(Assumptions assumptions, ResolvedJavaField field, boolean volatileAccess)146     protected ValueNode cloneAsFieldAccess(Assumptions assumptions, ResolvedJavaField field, boolean volatileAccess) {
147         return new StoreFieldNode(field.isStatic() ? null : object(), field, value(), stateAfter(), volatileAccess);
148     }
149 
150     @Override
cloneAsArrayAccess(ValueNode location, LocationIdentity identity, boolean volatileAccess)151     protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity, boolean volatileAccess) {
152         return new RawStoreNode(object(), location, value, accessKind(), identity, needsBarrier, volatileAccess, stateAfter(), isAnyLocationForced());
153     }
154 
getState()155     public FrameState getState() {
156         return stateAfter;
157     }
158 
159     @Override
getKilledLocationIdentity()160     public LocationIdentity getKilledLocationIdentity() {
161         if (isVolatile()) {
162             return LocationIdentity.any();
163         }
164         return getLocationIdentity();
165     }
166 }
167