001/*
002 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.nodes.extended;
024
025import jdk.internal.jvmci.meta.*;
026
027import com.oracle.graal.compiler.common.type.*;
028import com.oracle.graal.graph.*;
029import com.oracle.graal.nodeinfo.*;
030import com.oracle.graal.nodes.*;
031import com.oracle.graal.nodes.java.*;
032import com.oracle.graal.nodes.memory.*;
033import com.oracle.graal.nodes.spi.*;
034import com.oracle.graal.nodes.virtual.*;
035
036/**
037 * Store of a value at a location specified as an offset relative to an object. No null check is
038 * performed before the store.
039 */
040@NodeInfo
041public final class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single {
042
043    public static final NodeClass<UnsafeStoreNode> TYPE = NodeClass.create(UnsafeStoreNode.class);
044    @Input ValueNode value;
045    @OptionalInput(InputType.State) FrameState stateAfter;
046
047    public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) {
048        this(object, offset, value, accessKind, locationIdentity, null);
049    }
050
051    public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity, FrameState stateAfter) {
052        super(TYPE, StampFactory.forVoid(), object, offset, accessKind, locationIdentity);
053        this.value = value;
054        this.stateAfter = stateAfter;
055        assert accessKind != Kind.Void && accessKind != Kind.Illegal;
056    }
057
058    public FrameState stateAfter() {
059        return stateAfter;
060    }
061
062    public void setStateAfter(FrameState x) {
063        assert x == null || x.isAlive() : "frame state must be in a graph";
064        updateUsages(stateAfter, x);
065        stateAfter = x;
066    }
067
068    public boolean hasSideEffect() {
069        return true;
070    }
071
072    public ValueNode value() {
073        return value;
074    }
075
076    @Override
077    public void lower(LoweringTool tool) {
078        tool.getLowerer().lower(this, tool);
079    }
080
081    @Override
082    public void virtualize(VirtualizerTool tool) {
083        ValueNode alias = tool.getAlias(object());
084        if (alias instanceof VirtualObjectNode) {
085            VirtualObjectNode virtual = (VirtualObjectNode) alias;
086            ValueNode indexValue = tool.getAlias(offset());
087            if (indexValue.isConstant()) {
088                long off = indexValue.asJavaConstant().asLong();
089                int entryIndex = virtual.entryIndexForOffset(off, accessKind());
090                if (entryIndex != -1) {
091                    Kind entryKind = virtual.entryKind(entryIndex);
092                    ValueNode entry = tool.getEntry(virtual, entryIndex);
093                    if (entry.getKind() == value.getKind() || entryKind == accessKind()) {
094                        tool.setVirtualEntry(virtual, entryIndex, value(), true);
095                        tool.delete();
096                    } else {
097                        if ((accessKind() == Kind.Long || accessKind() == Kind.Double) && entryKind == Kind.Int) {
098                            int nextIndex = virtual.entryIndexForOffset(off + 4, entryKind);
099                            if (nextIndex != -1) {
100                                Kind nextKind = virtual.entryKind(nextIndex);
101                                if (nextKind == Kind.Int) {
102                                    tool.setVirtualEntry(virtual, entryIndex, value(), true);
103                                    tool.setVirtualEntry(virtual, nextIndex, ConstantNode.forConstant(JavaConstant.forIllegal(), tool.getMetaAccessProvider(), graph()), true);
104                                    tool.delete();
105                                }
106                            }
107                        }
108                    }
109                }
110            }
111        }
112    }
113
114    @Override
115    protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) {
116        return new StoreFieldNode(object(), field, value(), stateAfter());
117    }
118
119    @Override
120    protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity) {
121        return new UnsafeStoreNode(object(), location, value, accessKind(), identity, stateAfter());
122    }
123
124    public FrameState getState() {
125        return stateAfter;
126    }
127}