RawStoreNode.java revision 13083:b9a173f12fe6
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 */
23package org.graalvm.compiler.nodes.extended;
24
25import static org.graalvm.compiler.nodeinfo.InputType.State;
26import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
27import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
28
29import org.graalvm.api.word.LocationIdentity;
30import org.graalvm.compiler.core.common.type.StampFactory;
31import org.graalvm.compiler.graph.NodeClass;
32import org.graalvm.compiler.nodeinfo.NodeInfo;
33import org.graalvm.compiler.nodes.ConstantNode;
34import org.graalvm.compiler.nodes.FrameState;
35import org.graalvm.compiler.nodes.StateSplit;
36import org.graalvm.compiler.nodes.ValueNode;
37import org.graalvm.compiler.nodes.java.StoreFieldNode;
38import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
39import org.graalvm.compiler.nodes.spi.Lowerable;
40import org.graalvm.compiler.nodes.spi.LoweringTool;
41import org.graalvm.compiler.nodes.spi.Virtualizable;
42import org.graalvm.compiler.nodes.spi.VirtualizerTool;
43import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
44
45import jdk.vm.ci.meta.Assumptions;
46import jdk.vm.ci.meta.JavaConstant;
47import jdk.vm.ci.meta.JavaKind;
48import jdk.vm.ci.meta.ResolvedJavaField;
49
50/**
51 * Store of a value at a location specified as an offset relative to an object. No null check is
52 * performed before the store.
53 */
54@NodeInfo(cycles = CYCLES_2, size = SIZE_1)
55public final class RawStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single {
56
57    public static final NodeClass<RawStoreNode> TYPE = NodeClass.create(RawStoreNode.class);
58    @Input ValueNode value;
59    @OptionalInput(State) FrameState stateAfter;
60    private final boolean needsBarrier;
61
62    public RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity) {
63        this(object, offset, value, accessKind, locationIdentity, true);
64    }
65
66    public RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity, boolean needsBarrier) {
67        this(object, offset, value, accessKind, locationIdentity, needsBarrier, null, false);
68    }
69
70    public RawStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity, boolean needsBarrier, FrameState stateAfter,
71                    boolean forceAnyLocation) {
72        super(TYPE, StampFactory.forVoid(), object, offset, accessKind, locationIdentity, forceAnyLocation);
73        this.value = value;
74        this.needsBarrier = needsBarrier;
75        this.stateAfter = stateAfter;
76        assert accessKind != JavaKind.Void && accessKind != JavaKind.Illegal;
77    }
78
79    @NodeIntrinsic
80    public static native Object storeObject(Object object, long offset, Object value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity,
81                    @ConstantNodeParameter boolean needsBarrier);
82
83    @NodeIntrinsic
84    public static native Object storeChar(Object object, long offset, char value, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity);
85
86    public boolean needsBarrier() {
87        return needsBarrier;
88    }
89
90    @Override
91    public FrameState stateAfter() {
92        return stateAfter;
93    }
94
95    @Override
96    public void setStateAfter(FrameState x) {
97        assert x == null || x.isAlive() : "frame state must be in a graph";
98        updateUsages(stateAfter, x);
99        stateAfter = x;
100    }
101
102    @Override
103    public boolean hasSideEffect() {
104        return true;
105    }
106
107    public ValueNode value() {
108        return value;
109    }
110
111    @Override
112    public void lower(LoweringTool tool) {
113        tool.getLowerer().lower(this, tool);
114    }
115
116    @Override
117    public void virtualize(VirtualizerTool tool) {
118        ValueNode alias = tool.getAlias(object());
119        if (alias instanceof VirtualObjectNode) {
120            VirtualObjectNode virtual = (VirtualObjectNode) alias;
121            ValueNode indexValue = tool.getAlias(offset());
122            if (indexValue.isConstant()) {
123                long off = indexValue.asJavaConstant().asLong();
124                int entryIndex = virtual.entryIndexForOffset(off, accessKind());
125                if (entryIndex != -1) {
126                    JavaKind entryKind = virtual.entryKind(entryIndex);
127                    boolean canVirtualize = entryKind == accessKind() || entryKind == accessKind().getStackKind();
128                    if (!canVirtualize) {
129                        /*
130                         * Special case: If the entryKind is long, allow arbitrary kinds as long as
131                         * a value of the same kind is already there. This can only happen if some
132                         * other node initialized the entry with a value of a different kind. One
133                         * example where this happens is the Truffle NewFrameNode.
134                         */
135                        ValueNode entry = tool.getEntry(virtual, entryIndex);
136                        if (entryKind == JavaKind.Long && entry.getStackKind() == value.getStackKind()) {
137                            canVirtualize = true;
138                        }
139                    }
140                    if (canVirtualize) {
141                        tool.setVirtualEntry(virtual, entryIndex, value(), true);
142                        tool.delete();
143                    } else {
144                        /*
145                         * Special case: Allow storing a single long or double value into two
146                         * consecutive int slots.
147                         */
148                        if ((accessKind() == JavaKind.Long || accessKind() == JavaKind.Double) && entryKind == JavaKind.Int) {
149                            int nextIndex = virtual.entryIndexForOffset(off + 4, entryKind);
150                            if (nextIndex != -1) {
151                                JavaKind nextKind = virtual.entryKind(nextIndex);
152                                if (nextKind == JavaKind.Int) {
153                                    tool.setVirtualEntry(virtual, entryIndex, value(), true);
154                                    tool.setVirtualEntry(virtual, nextIndex, ConstantNode.forConstant(JavaConstant.forIllegal(), tool.getMetaAccessProvider(), graph()), true);
155                                    tool.delete();
156                                }
157                            }
158                        }
159                    }
160                }
161            }
162        }
163    }
164
165    @Override
166    protected ValueNode cloneAsFieldAccess(Assumptions assumptions, ResolvedJavaField field) {
167        return new StoreFieldNode(object(), field, value(), stateAfter());
168    }
169
170    @Override
171    protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity) {
172        return new RawStoreNode(object(), location, value, accessKind(), identity, needsBarrier, stateAfter(), isAnyLocationForced());
173    }
174
175    public FrameState getState() {
176        return stateAfter;
177    }
178}
179