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}