UnsafeStoreNode.java revision 12651:6ef01bd40ce2
1/*
2 * Copyright (c) 2011, 2016, 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_3;
27import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
28
29import org.graalvm.compiler.core.common.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_3, size = SIZE_1)
55public final class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single {
56
57    public static final NodeClass<UnsafeStoreNode> TYPE = NodeClass.create(UnsafeStoreNode.class);
58    @Input ValueNode value;
59    @OptionalInput(State) FrameState stateAfter;
60
61    public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity) {
62        this(object, offset, value, accessKind, locationIdentity, null);
63    }
64
65    public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, JavaKind accessKind, LocationIdentity locationIdentity, FrameState stateAfter) {
66        super(TYPE, StampFactory.forVoid(), object, offset, accessKind, locationIdentity);
67        this.value = value;
68        this.stateAfter = stateAfter;
69        assert accessKind != JavaKind.Void && accessKind != JavaKind.Illegal;
70    }
71
72    @Override
73    public FrameState stateAfter() {
74        return stateAfter;
75    }
76
77    @Override
78    public void setStateAfter(FrameState x) {
79        assert x == null || x.isAlive() : "frame state must be in a graph";
80        updateUsages(stateAfter, x);
81        stateAfter = x;
82    }
83
84    @Override
85    public boolean hasSideEffect() {
86        return true;
87    }
88
89    public ValueNode value() {
90        return value;
91    }
92
93    @Override
94    public void lower(LoweringTool tool) {
95        tool.getLowerer().lower(this, tool);
96    }
97
98    @Override
99    public void virtualize(VirtualizerTool tool) {
100        ValueNode alias = tool.getAlias(object());
101        if (alias instanceof VirtualObjectNode) {
102            VirtualObjectNode virtual = (VirtualObjectNode) alias;
103            ValueNode indexValue = tool.getAlias(offset());
104            if (indexValue.isConstant()) {
105                long off = indexValue.asJavaConstant().asLong();
106                int entryIndex = virtual.entryIndexForOffset(off, accessKind());
107                if (entryIndex != -1) {
108                    JavaKind entryKind = virtual.entryKind(entryIndex);
109                    ValueNode entry = tool.getEntry(virtual, entryIndex);
110                    if (entry.getStackKind() == value.getStackKind() || entryKind == accessKind()) {
111                        tool.setVirtualEntry(virtual, entryIndex, value(), true);
112                        tool.delete();
113                    } else {
114                        if ((accessKind() == JavaKind.Long || accessKind() == JavaKind.Double) && entryKind == JavaKind.Int) {
115                            int nextIndex = virtual.entryIndexForOffset(off + 4, entryKind);
116                            if (nextIndex != -1) {
117                                JavaKind nextKind = virtual.entryKind(nextIndex);
118                                if (nextKind == JavaKind.Int) {
119                                    tool.setVirtualEntry(virtual, entryIndex, value(), true);
120                                    tool.setVirtualEntry(virtual, nextIndex, ConstantNode.forConstant(JavaConstant.forIllegal(), tool.getMetaAccessProvider(), graph()), true);
121                                    tool.delete();
122                                }
123                            }
124                        }
125                    }
126                }
127            }
128        }
129    }
130
131    @Override
132    protected ValueNode cloneAsFieldAccess(Assumptions assumptions, ResolvedJavaField field) {
133        return new StoreFieldNode(object(), field, value(), stateAfter());
134    }
135
136    @Override
137    protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity) {
138        return new UnsafeStoreNode(object(), location, value, accessKind(), identity, stateAfter());
139    }
140
141    public FrameState getState() {
142        return stateAfter;
143    }
144}
145