# HG changeset patch # User Christian Wimmer # Date 1410918219 25200 # Node ID f396d15ddce221abe2634c8320423808d187b628 # Parent f2a87467d41a4ff44b72b3bcb9c5b08b2ca712a8 Factor out HotSpot-independent parts of ArrayCopy and ObjectClone nodes diff -r f2a87467d41a -r f396d15ddce2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Tue Sep 16 18:42:23 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Tue Sep 16 18:43:39 2014 -0700 @@ -185,6 +185,10 @@ return uninitialized; } + static boolean isHeapWordAligned(Constant value, Kind kind) { + return (arrayBaseOffset(kind) + (long) value.asInt() * arrayIndexScale(kind)) % heapWordSize() == 0; + } + public void updateAlignedDisjoint() { Kind componentKind = elementKind; if (srcPos == destPos) { @@ -195,7 +199,7 @@ Constant constantDst = destPos.stamp().asConstant(); if (constantSrc != null && constantDst != null) { if (!aligned) { - aligned = ArrayCopyNode.isHeapWordAligned(constantSrc, componentKind) && ArrayCopyNode.isHeapWordAligned(constantDst, componentKind); + aligned = isHeapWordAligned(constantSrc, componentKind) && isHeapWordAligned(constantDst, componentKind); } if (constantSrc.asInt() >= constantDst.asInt()) { // low to high copy so treat as disjoint diff -r f2a87467d41a -r f396d15ddce2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Tue Sep 16 18:42:23 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Tue Sep 16 18:43:39 2014 -0700 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.compiler.GraalCompiler.*; -import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; @@ -34,13 +33,12 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.nodes.*; @NodeInfo -public class ArrayCopyNode extends MacroStateSplitNode implements Virtualizable, Lowerable { +public class ArrayCopyNode extends BasicArrayCopyNode implements Virtualizable, Lowerable { public static ArrayCopyNode create(Invoke invoke) { return USE_GENERATED_NODES ? new ArrayCopyNodeGen(invoke) : new ArrayCopyNode(invoke); @@ -50,30 +48,6 @@ super(invoke); } - private ValueNode getSource() { - return arguments.get(0); - } - - private ValueNode getSourcePosition() { - return arguments.get(1); - } - - private ValueNode getDestination() { - return arguments.get(2); - } - - private ValueNode getDestinationPosition() { - return arguments.get(3); - } - - private ValueNode getLength() { - return arguments.get(4); - } - - static boolean isHeapWordAligned(Constant value, Kind kind) { - return (arrayBaseOffset(kind) + (long) value.asInt() * arrayIndexScale(kind)) % heapWordSize() == 0; - } - private StructuredGraph selectSnippet(LoweringTool tool, final Replacements replacements) { ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp()); ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp()); @@ -162,67 +136,4 @@ } return false; } - - private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) { - return position >= 0 && position + length <= virtualObject.entryCount(); - } - - private static boolean checkEntryTypes(int srcPos, int length, State srcState, ResolvedJavaType destComponentType, VirtualizerTool tool) { - if (destComponentType.getKind() == Kind.Object) { - for (int i = 0; i < length; i++) { - ValueNode entry = srcState.getEntry(srcPos + i); - State state = tool.getObjectState(entry); - ResolvedJavaType type; - if (state != null) { - if (state.getState() == EscapeState.Virtual) { - type = state.getVirtualObject().type(); - } else { - type = StampTool.typeOrNull(state.getMaterializedValue()); - } - } else { - type = StampTool.typeOrNull(entry); - } - if (type == null || !destComponentType.isAssignableFrom(type)) { - return false; - } - } - } - return true; - } - - @Override - public void virtualize(VirtualizerTool tool) { - if (getSourcePosition().isConstant() && getDestinationPosition().isConstant() && getLength().isConstant()) { - int srcPos = getSourcePosition().asConstant().asInt(); - int destPos = getDestinationPosition().asConstant().asInt(); - int length = getLength().asConstant().asInt(); - State srcState = tool.getObjectState(getSource()); - State destState = tool.getObjectState(getDestination()); - - if (srcState != null && srcState.getState() == EscapeState.Virtual && destState != null && destState.getState() == EscapeState.Virtual) { - VirtualObjectNode srcVirtual = srcState.getVirtualObject(); - VirtualObjectNode destVirtual = destState.getVirtualObject(); - if (!(srcVirtual instanceof VirtualArrayNode) || !(destVirtual instanceof VirtualArrayNode)) { - return; - } - if (((VirtualArrayNode) srcVirtual).componentType().getKind() != Kind.Object || ((VirtualArrayNode) destVirtual).componentType().getKind() != Kind.Object) { - return; - } - if (length < 0 || !checkBounds(srcPos, length, srcVirtual) || !checkBounds(destPos, length, destVirtual)) { - return; - } - if (!checkEntryTypes(srcPos, length, srcState, destVirtual.type().getComponentType(), tool)) { - return; - } - for (int i = 0; i < length; i++) { - tool.setVirtualEntry(destState, destPos + i, srcState.getEntry(srcPos + i), false); - } - tool.delete(); - if (Debug.isLogEnabled()) { - Debug.log("virtualized arraycopyf(%s, %d, %s, %d, %d)", getSource(), srcPos, getDestination(), destPos, length); - } - } - } - } - } diff -r f2a87467d41a -r f396d15ddce2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Tue Sep 16 18:42:23 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Tue Sep 16 18:43:39 2014 -0700 @@ -25,11 +25,8 @@ import static com.oracle.graal.compiler.GraalCompiler.*; import java.lang.reflect.*; -import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.nodeinfo.*; @@ -37,11 +34,10 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.replacements.nodes.*; @NodeInfo -public class ObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider { +public class ObjectCloneNode extends BasicObjectCloneNode implements VirtualizableAllocation, ArrayLengthProvider { public static ObjectCloneNode create(Invoke invoke) { return USE_GENERATED_NODES ? new ObjectCloneNodeGen(invoke) : new ObjectCloneNode(invoke); @@ -52,15 +48,6 @@ } @Override - public boolean inferStamp() { - return updateStamp(getObject().stamp()); - } - - private ValueNode getObject() { - return arguments.get(0); - } - - @Override protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) { if (!shouldIntrinsify(getTargetMethod())) { return null; @@ -105,81 +92,4 @@ } return null; } - - private static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) { - return metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type); - } - - /* - * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an - * exact type) and if it is a cloneable type. - * - * If yes, then the exact type is returned, otherwise it returns null. - */ - private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) { - if (!(stamp instanceof ObjectStamp)) { - return null; - } - ObjectStamp objectStamp = (ObjectStamp) stamp; - if (objectStamp.type() == null) { - return null; - } else if (objectStamp.isExactType()) { - return isCloneableType(objectStamp.type(), metaAccess) ? objectStamp.type() : null; - } else { - ResolvedJavaType type = objectStamp.type().findUniqueConcreteSubtype(); - if (type != null && isCloneableType(type, metaAccess)) { - assumptions.recordConcreteSubtype(objectStamp.type(), type); - return type; - } else { - return null; - } - } - } - - @Override - public void virtualize(VirtualizerTool tool) { - State originalState = tool.getObjectState(getObject()); - if (originalState != null && originalState.getState() == EscapeState.Virtual) { - VirtualObjectNode originalVirtual = originalState.getVirtualObject(); - if (isCloneableType(originalVirtual.type(), tool.getMetaAccessProvider())) { - ValueNode[] newEntryState = new ValueNode[originalVirtual.entryCount()]; - for (int i = 0; i < newEntryState.length; i++) { - newEntryState[i] = originalState.getEntry(i); - } - VirtualObjectNode newVirtual = originalVirtual.duplicate(); - tool.createVirtualObject(newVirtual, newEntryState, Collections. emptyList()); - tool.replaceWithVirtual(newVirtual); - } - } else { - ValueNode obj; - if (originalState != null) { - obj = originalState.getMaterializedValue(); - } else { - obj = tool.getReplacedValue(getObject()); - } - ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions(), tool.getMetaAccessProvider()); - if (type != null && !type.isArray()) { - VirtualInstanceNode newVirtual = VirtualInstanceNode.create(type, true); - ResolvedJavaField[] fields = newVirtual.getFields(); - - ValueNode[] state = new ValueNode[fields.length]; - final LoadFieldNode[] loads = new LoadFieldNode[fields.length]; - for (int i = 0; i < fields.length; i++) { - state[i] = loads[i] = LoadFieldNode.create(obj, fields[i]); - tool.addNode(loads[i]); - } - tool.createVirtualObject(newVirtual, state, Collections. emptyList()); - tool.replaceWithVirtual(newVirtual); - } - } - } - - @Override - public ValueNode length() { - if (getObject() instanceof ArrayLengthProvider) { - return ((ArrayLengthProvider) getObject()).length(); - } else { - return null; - } - } } diff -r f2a87467d41a -r f396d15ddce2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java Tue Sep 16 18:43:39 2014 -0700 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.virtual.*; + +@NodeInfo +public class BasicArrayCopyNode extends MacroStateSplitNode implements Virtualizable { + + public static BasicArrayCopyNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new BasicArrayCopyNodeGen(invoke) : new BasicArrayCopyNode(invoke); + } + + protected BasicArrayCopyNode(Invoke invoke) { + super(invoke); + } + + protected ValueNode getSource() { + return arguments.get(0); + } + + protected ValueNode getSourcePosition() { + return arguments.get(1); + } + + protected ValueNode getDestination() { + return arguments.get(2); + } + + protected ValueNode getDestinationPosition() { + return arguments.get(3); + } + + protected ValueNode getLength() { + return arguments.get(4); + } + + private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) { + return position >= 0 && position + length <= virtualObject.entryCount(); + } + + private static boolean checkEntryTypes(int srcPos, int length, State srcState, ResolvedJavaType destComponentType, VirtualizerTool tool) { + if (destComponentType.getKind() == Kind.Object) { + for (int i = 0; i < length; i++) { + ValueNode entry = srcState.getEntry(srcPos + i); + State state = tool.getObjectState(entry); + ResolvedJavaType type; + if (state != null) { + if (state.getState() == EscapeState.Virtual) { + type = state.getVirtualObject().type(); + } else { + type = StampTool.typeOrNull(state.getMaterializedValue()); + } + } else { + type = StampTool.typeOrNull(entry); + } + if (type == null || !destComponentType.isAssignableFrom(type)) { + return false; + } + } + } + return true; + } + + @Override + public void virtualize(VirtualizerTool tool) { + if (getSourcePosition().isConstant() && getDestinationPosition().isConstant() && getLength().isConstant()) { + int srcPos = getSourcePosition().asConstant().asInt(); + int destPos = getDestinationPosition().asConstant().asInt(); + int length = getLength().asConstant().asInt(); + State srcState = tool.getObjectState(getSource()); + State destState = tool.getObjectState(getDestination()); + + if (srcState != null && srcState.getState() == EscapeState.Virtual && destState != null && destState.getState() == EscapeState.Virtual) { + VirtualObjectNode srcVirtual = srcState.getVirtualObject(); + VirtualObjectNode destVirtual = destState.getVirtualObject(); + if (!(srcVirtual instanceof VirtualArrayNode) || !(destVirtual instanceof VirtualArrayNode)) { + return; + } + if (((VirtualArrayNode) srcVirtual).componentType().getKind() != Kind.Object || ((VirtualArrayNode) destVirtual).componentType().getKind() != Kind.Object) { + return; + } + if (length < 0 || !checkBounds(srcPos, length, srcVirtual) || !checkBounds(destPos, length, destVirtual)) { + return; + } + if (!checkEntryTypes(srcPos, length, srcState, destVirtual.type().getComponentType(), tool)) { + return; + } + for (int i = 0; i < length; i++) { + tool.setVirtualEntry(destState, destPos + i, srcState.getEntry(srcPos + i), false); + } + tool.delete(); + if (Debug.isLogEnabled()) { + Debug.log("virtualized arraycopyf(%s, %d, %s, %d, %d)", getSource(), srcPos, getDestination(), destPos, length); + } + } + } + } + +} diff -r f2a87467d41a -r f396d15ddce2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java Tue Sep 16 18:43:39 2014 -0700 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.nodes; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.virtual.*; + +@NodeInfo +public class BasicObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider { + + public static BasicObjectCloneNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new BasicObjectCloneNodeGen(invoke) : new BasicObjectCloneNode(invoke); + } + + protected BasicObjectCloneNode(Invoke invoke) { + super(invoke); + } + + @Override + public boolean inferStamp() { + return updateStamp(getObject().stamp()); + } + + public ValueNode getObject() { + return arguments.get(0); + } + + protected static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) { + return metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type); + } + + /* + * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an + * exact type) and if it is a cloneable type. + * + * If yes, then the exact type is returned, otherwise it returns null. + */ + protected static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) { + if (!(stamp instanceof ObjectStamp)) { + return null; + } + ObjectStamp objectStamp = (ObjectStamp) stamp; + if (objectStamp.type() == null) { + return null; + } else if (objectStamp.isExactType()) { + return isCloneableType(objectStamp.type(), metaAccess) ? objectStamp.type() : null; + } else { + ResolvedJavaType type = objectStamp.type().findUniqueConcreteSubtype(); + if (type != null && isCloneableType(type, metaAccess)) { + assumptions.recordConcreteSubtype(objectStamp.type(), type); + return type; + } else { + return null; + } + } + } + + @Override + public void virtualize(VirtualizerTool tool) { + State originalState = tool.getObjectState(getObject()); + if (originalState != null && originalState.getState() == EscapeState.Virtual) { + VirtualObjectNode originalVirtual = originalState.getVirtualObject(); + if (isCloneableType(originalVirtual.type(), tool.getMetaAccessProvider())) { + ValueNode[] newEntryState = new ValueNode[originalVirtual.entryCount()]; + for (int i = 0; i < newEntryState.length; i++) { + newEntryState[i] = originalState.getEntry(i); + } + VirtualObjectNode newVirtual = originalVirtual.duplicate(); + tool.createVirtualObject(newVirtual, newEntryState, Collections. emptyList()); + tool.replaceWithVirtual(newVirtual); + } + } else { + ValueNode obj; + if (originalState != null) { + obj = originalState.getMaterializedValue(); + } else { + obj = tool.getReplacedValue(getObject()); + } + ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions(), tool.getMetaAccessProvider()); + if (type != null && !type.isArray()) { + VirtualInstanceNode newVirtual = createVirtualInstanceNode(type, true); + ResolvedJavaField[] fields = newVirtual.getFields(); + + ValueNode[] state = new ValueNode[fields.length]; + final LoadFieldNode[] loads = new LoadFieldNode[fields.length]; + for (int i = 0; i < fields.length; i++) { + state[i] = loads[i] = LoadFieldNode.create(obj, fields[i]); + tool.addNode(loads[i]); + } + tool.createVirtualObject(newVirtual, state, Collections. emptyList()); + tool.replaceWithVirtual(newVirtual); + } + } + } + + protected VirtualInstanceNode createVirtualInstanceNode(ResolvedJavaType type, boolean hasIdentity) { + return VirtualInstanceNode.create(type, hasIdentity); + } + + @Override + public ValueNode length() { + if (getObject() instanceof ArrayLengthProvider) { + return ((ArrayLengthProvider) getObject()).length(); + } else { + return null; + } + } +}