# HG changeset patch # User Gilles Duboscq # Date 1328111684 -3600 # Node ID e8ce691d7923e056a59bae6964efcf1621645a2c # Parent e952b6c6949b67600f5d4c2a684314e5bf82e450 Move Array copy, Unsafe and System snippets to hotspot specific project since they are hotspot specific. object array copy does bulk post write barrier diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java Wed Feb 01 11:36:50 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java Wed Feb 01 16:54:44 2012 +0100 @@ -156,6 +156,7 @@ Constructor< ? > constructor; try { constructor = nodeClass.getDeclaredConstructor(parameterTypes); + constructor.setAccessible(true); } catch (Exception e) { throw new RuntimeException(e); } diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Wed Feb 01 11:36:50 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Wed Feb 01 16:54:44 2012 +0100 @@ -39,6 +39,7 @@ import com.oracle.max.graal.hotspot.Compiler; import com.oracle.max.graal.hotspot.ri.*; import com.oracle.max.graal.hotspot.server.*; +import com.oracle.max.graal.hotspot.snippets.*; import com.oracle.max.graal.java.*; import com.oracle.max.graal.snippets.*; @@ -115,6 +116,7 @@ GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget(), PhasePlan.DEFAULT); Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets(), PhasePlan.DEFAULT); Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets(), PhasePlan.DEFAULT); + Snippets.install(runtime, runtime.getCompiler().getTarget(), new ArrayCopySnippets(), PhasePlan.DEFAULT); } // Create compilation queue. diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/ArrayCopySnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/ArrayCopySnippets.java Wed Feb 01 16:54:44 2012 +0100 @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.snippets; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.hotspot.*; +import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.nodes.extended.*; +import com.oracle.max.graal.nodes.spi.*; +import com.oracle.max.graal.nodes.type.*; +import com.oracle.max.graal.snippets.*; +import com.oracle.max.graal.snippets.nodes.*; + + +public class ArrayCopySnippets implements SnippetsInterface{ + + @Snippet + public static void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + if ((length & 0x04) == 0) { + copyLongsDown(src, srcPos, dest, destPos, length >> 3); + } else { + copyIntsDown(src, srcPos, dest, destPos, length >> 2); + } + } else { + copyShortsDown(src, srcPos, dest, destPos, length >> 1); + } + } else { + copyBytesDown(src, srcPos, dest, destPos, length); + } + } else { + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + if ((length & 0x04) == 0) { + copyLongsUp(src, srcPos, dest, destPos, length >> 3); + } else { + copyIntsUp(src, srcPos, dest, destPos, length >> 2); + } + } else { + copyShortsUp(src, srcPos, dest, destPos, length >> 1); + } + } else { + copyBytesUp(src, srcPos, dest, destPos, length); + } + } + } + + @Snippet + public static void arraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2); + } else { + copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1); + } + } else { + copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length); + } + } else { + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2); + } else { + copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1); + } + } else { + copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length); + } + } + } + + @Snippet + public static void arraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2); + } else { + copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1); + } + } else { + copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length); + } + } else { + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2); + } else { + copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1); + } + } else { + copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length); + } + } + } + + @Snippet + public static void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + if ((length & 0x01) == 0) { + copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1); + } else { + copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length); + } + } else { + if ((length & 0x01) == 0) { + copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1); + } else { + copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length); + } + } + } + + @Snippet + public static void arraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + if ((length & 0x01) == 0) { + copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1); + } else { + copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length); + } + } else { + if ((length & 0x01) == 0) { + copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1); + } else { + copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length); + } + } + } + + @Snippet + public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length); + } else { + copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length); + } + } + + @Snippet + public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length); + } else { + copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length); + } + } + + // Does NOT perform store checks + @Snippet + public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + copyObjectsDown(src, srcPos * 8L, dest, destPos * 8L, length); + } else { + copyObjectsUp(src, srcPos * 8L, dest, destPos * 8L, length); + } + } + + @Snippet + public static void copyBytesDown(Object src, int srcPos, Object dest, int destPos, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte); + for (long i = length - 1; i >= 0; i--) { + Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte); + UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte); + } + } + + @Snippet + public static void copyShortsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); + for (long i = (length - 1) * 2; i >= 0; i -= 2) { + Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short); + } + } + + @Snippet + public static void copyIntsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); + for (long i = (length - 1) * 4; i >= 0; i -= 4) { + Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int); + } + } + + @Snippet + public static void copyLongsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); + for (long i = (length - 1) * 8; i >= 0; i -= 8) { + Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long); + } + } + + // Does NOT perform store checks + @Snippet + public static void copyObjectsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object); + for (long i = (length - 1) * 8; i >= 0; i -= 8) { + Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object); + UnsafeStoreNode.store(dest, i + (destOffset + header), a, CiKind.Object); + } + } + + /** + * Copies {@code length} bytes from {@code src} starting at {@code srcPos} to {@code dest} starting at {@code destPos}. + * @param src source object + * @param srcPos source offset + * @param dest destination object + * @param destPos destination offset + * @param length number of bytes to copy + */ + @Snippet + public static void copyBytesUp(Object src, int srcPos, Object dest, int destPos, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte); + for (long i = 0; i < length; i++) { + Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte); + UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte); + } + } + + /** + * Copies {@code length} shorts from {@code src} starting at offset {@code srcOffset} (in bytes) to {@code dest} starting at offset {@code destOffset} (in bytes). + * @param src + * @param srcOffset (in bytes) + * @param dest + * @param destOffset (in bytes) + * @param length (in shorts) + */ + @Snippet + public static void copyShortsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); + for (long i = 0; i < length * 2L; i += 2) { + Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short); + } + } + + @Snippet + public static void copyIntsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Int); + for (long i = 0; i < length * 4L; i += 4) { + Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int); + } + } + + @Snippet + public static void copyLongsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Long); + for (long i = 0; i < length * 8L; i += 8) { + Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long); + } + } + + // Does NOT perform store checks + @Snippet + public static void copyObjectsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object); + for (long i = 0; i < length * 8L; i += 8) { + Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object); + UnsafeStoreNode.store(dest, i + (destOffset + header), a, CiKind.Object); + } + if (length > 0) { + long cardShift = CardTableShiftNode.get(); + long cardStart = CardTableStartNode.get(); + long dstAddr = GetObjectAddressNode.get(dest); + long count = (8 * (length - 1)) >>> cardShift; + long start = ((dstAddr + header + destOffset) >>> cardShift) + cardStart; + + while (count-- > 0) { + DirectStoreNode.store(start + count, false); + } + } + + } + + private static class GetObjectAddressNode extends FixedWithNextNode implements LIRLowerable { + @Input private ValueNode object; + + public GetObjectAddressNode(ValueNode obj) { + super(StampFactory.forKind(CiKind.Long)); + this.object = obj; + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static long get(Object array) { + throw new UnsupportedOperationException(); + } + + @Override + public void generate(LIRGeneratorTool gen) { + CiValue obj = gen.newVariable(gen.target().wordKind); + gen.emitMove(gen.operand(object), obj); + gen.setResult(this, obj); + } + } + + private static class DirectStoreNode extends FixedWithNextNode implements LIRLowerable { + @Input private ValueNode address; + @Input private ValueNode value; + + public DirectStoreNode(ValueNode address, ValueNode value) { + super(StampFactory.illegal()); + this.address = address; + this.value = value; + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void store(long address, long value) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void store(long address, boolean value) { + throw new UnsupportedOperationException(); + } + + @Override + public void generate(LIRGeneratorTool gen) { + CiValue v = gen.operand(value); + gen.emitStore(new CiAddress(v.kind, gen.operand(address)), v, false); + } + } + + private static class CardTableShiftNode extends ConstantNode { + public CardTableShiftNode() { + super(CiConstant.forInt(CompilerImpl.getInstance().getConfig().cardtableShift)); + } + + @NodeIntrinsic + public static int get() { + throw new UnsupportedOperationException(); + } + } + + private static class CardTableStartNode extends ConstantNode { + public CardTableStartNode() { + super(CiConstant.forLong(CompilerImpl.getInstance().getConfig().cardtableStartAddress)); + } + + @NodeIntrinsic + public static long get() { + throw new UnsupportedOperationException(); + } + } +} diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java Wed Feb 01 16:54:44 2012 +0100 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.snippets; + +import java.lang.reflect.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.compiler.phases.*; +import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.cri.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.nodes.java.*; + +public class IntrinsifyArrayCopyPhase extends Phase { + private final GraalRuntime runtime; + private RiResolvedMethod arrayCopy; + private RiResolvedMethod byteArrayCopy; + private RiResolvedMethod shortArrayCopy; + private RiResolvedMethod charArrayCopy; + private RiResolvedMethod intArrayCopy; + private RiResolvedMethod longArrayCopy; + private RiResolvedMethod floatArrayCopy; + private RiResolvedMethod doubleArrayCopy; + private RiResolvedMethod objectArrayCopy; + + public IntrinsifyArrayCopyPhase(GraalRuntime runtime) { + this.runtime = runtime; + try { + byteArrayCopy = getArrayCopySnippet(runtime, byte.class); + charArrayCopy = getArrayCopySnippet(runtime, char.class); + shortArrayCopy = getArrayCopySnippet(runtime, short.class); + intArrayCopy = getArrayCopySnippet(runtime, int.class); + longArrayCopy = getArrayCopySnippet(runtime, long.class); + floatArrayCopy = getArrayCopySnippet(runtime, float.class); + doubleArrayCopy = getArrayCopySnippet(runtime, double.class); + objectArrayCopy = getArrayCopySnippet(runtime, Object.class); + arrayCopy = runtime.getRiMethod(System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class)); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + + private static RiResolvedMethod getArrayCopySnippet(RiRuntime runtime, Class componentClass) throws NoSuchMethodException { + Class arrayClass = Array.newInstance(componentClass, 0).getClass(); + return runtime.getRiMethod(ArrayCopySnippets.class.getDeclaredMethod("arraycopy", arrayClass, int.class, arrayClass, int.class, int.class)); + } + + @Override + protected void run(StructuredGraph graph) { + boolean hits = false; + for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { + RiResolvedMethod targetMethod = methodCallTarget.targetMethod(); + RiResolvedMethod snippetMethod = null; + if (targetMethod == arrayCopy) { + ValueNode src = methodCallTarget.arguments().get(0); + ValueNode dest = methodCallTarget.arguments().get(2); + if (src == null || dest == null) { //TODO (gd) this should never be null : check + return; + } + RiResolvedType srcDeclaredType = src.declaredType(); + RiResolvedType destDeclaredType = dest.declaredType(); + if (srcDeclaredType != null + && srcDeclaredType.isArrayClass() + && destDeclaredType != null + && destDeclaredType.isArrayClass()) { + CiKind componentKind = srcDeclaredType.componentType().kind(false); + if (srcDeclaredType.componentType() == destDeclaredType.componentType()) { + if (componentKind == CiKind.Int) { + snippetMethod = intArrayCopy; + } else if (componentKind == CiKind.Char) { + snippetMethod = charArrayCopy; + } else if (componentKind == CiKind.Long) { + snippetMethod = longArrayCopy; + } else if (componentKind == CiKind.Byte) { + snippetMethod = byteArrayCopy; + } else if (componentKind == CiKind.Short) { + snippetMethod = shortArrayCopy; + } else if (componentKind == CiKind.Float) { + snippetMethod = floatArrayCopy; + } else if (componentKind == CiKind.Double) { + snippetMethod = doubleArrayCopy; + } else if (componentKind == CiKind.Object) { + snippetMethod = objectArrayCopy; + } + } else if (componentKind == CiKind.Object + && srcDeclaredType.componentType().isSubtypeOf(destDeclaredType.componentType())) { + snippetMethod = objectArrayCopy; + } + } + } + + if (snippetMethod != null) { + StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.compilerStorage().get(Graph.class); + assert snippetGraph != null : "ArrayCopySnippets should be installed"; + hits = true; + Debug.log("%s > Intinsify (%s)", Debug.currentScope(), snippetMethod.signature().argumentTypeAt(0, snippetMethod.holder()).componentType()); + InliningUtil.inline(methodCallTarget.invoke(), snippetGraph, false); + } + } + if (hits) { + new CanonicalizerPhase(null, runtime, null).apply(graph); + } + } +} diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/SystemSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/SystemSnippets.java Wed Feb 01 16:54:44 2012 +0100 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.snippets; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.nodes.extended.*; +import com.oracle.max.graal.snippets.*; + +/** + * Snippets for {@link java.lang.System} methods. + */ +@ClassSubstitution(java.lang.System.class) +public class SystemSnippets implements SnippetsInterface { + + public static long currentTimeMillis() { + return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeMillis); + } + + public static long nanoTime() { + return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeNanos); + } + +} diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/UnsafeSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/UnsafeSnippets.java Wed Feb 01 16:54:44 2012 +0100 @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.snippets; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.util.*; +import com.oracle.max.graal.nodes.extended.*; +import com.oracle.max.graal.nodes.java.*; +import com.oracle.max.graal.snippets.*; + +/** + * Snippets for {@link sun.misc.Unsafe} methods. + */ +@ClassSubstitution(sun.misc.Unsafe.class) +public class UnsafeSnippets implements SnippetsInterface { + + public boolean compareAndSwapObject(Object o, long offset, Object expected, Object x) { + return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); + } + + public boolean compareAndSwapInt(Object o, long offset, int expected, int x) { + return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); + } + + public boolean compareAndSwapLong(Object o, long offset, long expected, long x) { + return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); + } + + public Object getObject(Object o, long offset) { + return UnsafeLoadNode.load(o, offset, CiKind.Object); + } + + public Object getObjectVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + Object result = getObject(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putObject(Object o, long offset, Object x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Object); + } + + public void putObjectVolatile(Object o, long offset, Object x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putObject(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public int getInt(Object o, long offset) { + Integer value = UnsafeLoadNode.load(o, offset, CiKind.Int); + return value; + } + + public int getIntVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + int result = getInt(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putInt(Object o, long offset, int x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Int); + } + + public void putIntVolatile(Object o, long offset, int x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putInt(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public boolean getBoolean(Object o, long offset) { + @JavacBug(id = 6995200) + Boolean result = UnsafeLoadNode.load(o, offset, CiKind.Boolean); + return result; + } + + public boolean getBooleanVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + boolean result = getBoolean(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putBoolean(Object o, long offset, boolean x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Boolean); + } + + public void putBooleanVolatile(Object o, long offset, boolean x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putBoolean(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public byte getByte(Object o, long offset) { + @JavacBug(id = 6995200) + Byte result = UnsafeLoadNode.load(o, offset, CiKind.Byte); + return result; + } + + public byte getByteVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + byte result = getByte(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putByte(Object o, long offset, byte x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Byte); + } + + public void putByteVolatile(Object o, long offset, byte x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putByte(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public short getShort(Object o, long offset) { + @JavacBug(id = 6995200) + Short result = UnsafeLoadNode.load(o, offset, CiKind.Short); + return result; + } + + public short getShortVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + short result = getShort(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putShort(Object o, long offset, short x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Short); + } + + public void putShortVolatile(Object o, long offset, short x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putShort(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public char getChar(Object o, long offset) { + @JavacBug(id = 6995200) + Character result = UnsafeLoadNode.load(o, offset, CiKind.Char); + return result; + } + + public char getCharVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + char result = getChar(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putChar(Object o, long offset, char x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Char); + } + + public void putCharVolatile(Object o, long offset, char x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putChar(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public long getLong(Object o, long offset) { + @JavacBug(id = 6995200) + Long result = UnsafeLoadNode.load(o, offset, CiKind.Long); + return result; + } + + public long getLongVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + long result = getLong(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putLong(Object o, long offset, long x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Long); + } + + public void putLongVolatile(Object o, long offset, long x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putLong(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public float getFloat(Object o, long offset) { + @JavacBug(id = 6995200) + Float result = UnsafeLoadNode.load(o, offset, CiKind.Float); + return result; + } + + public float getFloatVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + float result = getFloat(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putFloat(Object o, long offset, float x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Float); + } + + public void putFloatVolatile(Object o, long offset, float x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putFloat(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public double getDouble(Object o, long offset) { + @JavacBug(id = 6995200) + Double result = UnsafeLoadNode.load(o, offset, CiKind.Double); + return result; + } + + public double getDoubleVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + double result = getDouble(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putDouble(Object o, long offset, double x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Double); + } + + public void putDoubleVolatile(Object o, long offset, double x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putDouble(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } +} diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java --- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java Wed Feb 01 11:36:50 2012 +0100 +++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java Wed Feb 01 16:54:44 2012 +0100 @@ -581,7 +581,7 @@ throw new CiBailout("Loop formed by an exception handler"); } if (nextLoop >= Long.SIZE) { - // This restriction can be removed by using a fall-back to a BitSet in case we have more than 32 loops + // This restriction can be removed by using a fall-back to a BitSet in case we have more than 64 loops // Don't compile such methods for now, until we see a concrete case that allows checking for correctness. throw new CiBailout("Too many loops in method"); } diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/ConstantNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/ConstantNode.java Wed Feb 01 11:36:50 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/ConstantNode.java Wed Feb 01 16:54:44 2012 +0100 @@ -33,11 +33,11 @@ * long, float, object reference, address, etc. */ @NodeInfo(shortName = "Const") -public final class ConstantNode extends BooleanNode implements LIRLowerable { +public class ConstantNode extends BooleanNode implements LIRLowerable { @Data public final CiConstant value; - private ConstantNode(CiConstant value) { + protected ConstantNode(CiConstant value) { this(value, null); } @@ -45,7 +45,7 @@ * Constructs a new ConstantNode representing the specified constant. * @param value the constant */ - private ConstantNode(CiConstant value, RiRuntime runtime) { + protected ConstantNode(CiConstant value, RiRuntime runtime) { super(StampFactory.forConstant(value, runtime)); this.value = value; } diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java Wed Feb 01 11:36:50 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.snippets; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.nodes.extended.*; -import com.oracle.max.graal.snippets.nodes.*; - - -public class ArrayCopySnippets implements SnippetsInterface{ - - @Snippet - public static void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - if ((length & 0x04) == 0) { - copyLongsDown(src, srcPos, dest, destPos, length >> 3); - } else { - copyIntsDown(src, srcPos, dest, destPos, length >> 2); - } - } else { - copyShortsDown(src, srcPos, dest, destPos, length >> 1); - } - } else { - copyBytesDown(src, srcPos, dest, destPos, length); - } - } else { - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - if ((length & 0x04) == 0) { - copyLongsUp(src, srcPos, dest, destPos, length >> 3); - } else { - copyIntsUp(src, srcPos, dest, destPos, length >> 2); - } - } else { - copyShortsUp(src, srcPos, dest, destPos, length >> 1); - } - } else { - copyBytesUp(src, srcPos, dest, destPos, length); - } - } - } - - @Snippet - public static void arraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2); - } else { - copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1); - } - } else { - copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length); - } - } else { - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2); - } else { - copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1); - } - } else { - copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length); - } - } - } - - @Snippet - public static void arraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2); - } else { - copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1); - } - } else { - copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length); - } - } else { - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2); - } else { - copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1); - } - } else { - copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length); - } - } - } - - @Snippet - public static void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - if ((length & 0x01) == 0) { - copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1); - } else { - copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length); - } - } else { - if ((length & 0x01) == 0) { - copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1); - } else { - copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length); - } - } - } - - @Snippet - public static void arraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - if ((length & 0x01) == 0) { - copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1); - } else { - copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length); - } - } else { - if ((length & 0x01) == 0) { - copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1); - } else { - copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length); - } - } - } - - @Snippet - public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length); - } else { - copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length); - } - } - - @Snippet - public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length); - } else { - copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length); - } - } - - // Does NOT perform store checks - @Snippet - public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - copyObjectsDown(src, srcPos * 8L, dest, destPos * 8L, length); - } else { - copyObjectsUp(src, srcPos * 8L, dest, destPos * 8L, length); - } - } - - @Snippet - public static void copyBytesDown(Object src, int srcPos, Object dest, int destPos, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte); - for (long i = length - 1; i >= 0; i--) { - Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte); - UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte); - } - } - - @Snippet - public static void copyShortsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); - for (long i = (length - 1) * 2; i >= 0; i -= 2) { - Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short); - } - } - - @Snippet - public static void copyIntsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); - for (long i = (length - 1) * 4; i >= 0; i -= 4) { - Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int); - } - } - - @Snippet - public static void copyLongsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); - for (long i = (length - 1) * 8; i >= 0; i -= 8) { - Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long); - } - } - - // Does NOT perform store checks - @Snippet - public static void copyObjectsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object); - for (long i = (length - 1) * 8; i >= 0; i -= 8) { - Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object); - UnsafeStoreNode.store(dest, i + (destOffset + header), a, CiKind.Object); - } - } - - /** - * Copies {@code length} bytes from {@code src} starting at {@code srcPos} to {@code dest} starting at {@code destPos}. - * @param src source object - * @param srcPos source offset - * @param dest destination object - * @param destPos destination offset - * @param length number of bytes to copy - */ - @Snippet - public static void copyBytesUp(Object src, int srcPos, Object dest, int destPos, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte); - for (long i = 0; i < length; i++) { - Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte); - UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte); - } - } - - /** - * Copies {@code length} shorts from {@code src} starting at offset {@code srcOffset} (in bytes) to {@code dest} starting at offset {@code destOffset} (in bytes). - * @param src - * @param srcOffset (in bytes) - * @param dest - * @param destOffset (in bytes) - * @param length (in shorts) - */ - @Snippet - public static void copyShortsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); - for (long i = 0; i < length * 2L; i += 2) { - Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short); - } - } - - @Snippet - public static void copyIntsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Int); - for (long i = 0; i < length * 4L; i += 4) { - Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int); - } - } - - @Snippet - public static void copyLongsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Long); - for (long i = 0; i < length * 8L; i += 8) { - Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long); - } - } - - // Does NOT perform store checks - @Snippet - public static void copyObjectsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object); - for (long i = 0; i < length * 8L; i += 8) { - Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object); - UnsafeStoreNode.store(dest, i + (destOffset + header), a, CiKind.Object); - } - } -} diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/GraalIntrinsics.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/GraalIntrinsics.java Wed Feb 01 11:36:50 2012 +0100 +++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/GraalIntrinsics.java Wed Feb 01 16:54:44 2012 +0100 @@ -37,7 +37,6 @@ Snippets.install(runtime, target, new DoubleSnippets(), plan); Snippets.install(runtime, target, new FloatSnippets(), plan); Snippets.install(runtime, target, new NodeClassSnippets(), plan); - Snippets.install(runtime, target, new ArrayCopySnippets(), plan); } } } diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java Wed Feb 01 11:36:50 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.snippets; - -import java.lang.reflect.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.compiler.phases.*; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.cri.*; -import com.oracle.max.graal.debug.*; -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.nodes.*; -import com.oracle.max.graal.nodes.java.*; - -public class IntrinsifyArrayCopyPhase extends Phase { - private final GraalRuntime runtime; - private RiResolvedMethod arrayCopy; - private RiResolvedMethod byteArrayCopy; - private RiResolvedMethod shortArrayCopy; - private RiResolvedMethod charArrayCopy; - private RiResolvedMethod intArrayCopy; - private RiResolvedMethod longArrayCopy; - private RiResolvedMethod floatArrayCopy; - private RiResolvedMethod doubleArrayCopy; - private RiResolvedMethod objectArrayCopy; - - public IntrinsifyArrayCopyPhase(GraalRuntime runtime) { - this.runtime = runtime; - try { - byteArrayCopy = getArrayCopySnippet(runtime, byte.class); - charArrayCopy = getArrayCopySnippet(runtime, char.class); - shortArrayCopy = getArrayCopySnippet(runtime, short.class); - intArrayCopy = getArrayCopySnippet(runtime, int.class); - longArrayCopy = getArrayCopySnippet(runtime, long.class); - floatArrayCopy = getArrayCopySnippet(runtime, float.class); - doubleArrayCopy = getArrayCopySnippet(runtime, double.class); - objectArrayCopy = getArrayCopySnippet(runtime, Object.class); - arrayCopy = runtime.getRiMethod(System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class)); - } catch (SecurityException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - } - - private static RiResolvedMethod getArrayCopySnippet(RiRuntime runtime, Class componentClass) throws NoSuchMethodException { - Class arrayClass = Array.newInstance(componentClass, 0).getClass(); - return runtime.getRiMethod(ArrayCopySnippets.class.getDeclaredMethod("arraycopy", arrayClass, int.class, arrayClass, int.class, int.class)); - } - - @Override - protected void run(StructuredGraph graph) { - boolean hits = false; - for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { - RiResolvedMethod targetMethod = methodCallTarget.targetMethod(); - RiResolvedMethod snippetMethod = null; - if (targetMethod == arrayCopy) { - ValueNode src = methodCallTarget.arguments().get(0); - ValueNode dest = methodCallTarget.arguments().get(2); - if (src == null || dest == null) { //TODO (gd) this should never be null : check - return; - } - RiResolvedType srcDeclaredType = src.declaredType(); - RiResolvedType destDeclaredType = dest.declaredType(); - if (srcDeclaredType != null - && srcDeclaredType.isArrayClass() - && destDeclaredType != null - && destDeclaredType.isArrayClass()) { - CiKind componentKind = srcDeclaredType.componentType().kind(false); - if (srcDeclaredType.componentType() == destDeclaredType.componentType()) { - if (componentKind == CiKind.Int) { - snippetMethod = intArrayCopy; - } else if (componentKind == CiKind.Char) { - snippetMethod = charArrayCopy; - } else if (componentKind == CiKind.Long) { - snippetMethod = longArrayCopy; - } else if (componentKind == CiKind.Byte) { - snippetMethod = byteArrayCopy; - } else if (componentKind == CiKind.Short) { - snippetMethod = shortArrayCopy; - } else if (componentKind == CiKind.Float) { - snippetMethod = floatArrayCopy; - } else if (componentKind == CiKind.Double) { - snippetMethod = doubleArrayCopy; - } else if (componentKind == CiKind.Object) { - snippetMethod = objectArrayCopy; - } - } else if (componentKind == CiKind.Object - && srcDeclaredType.componentType().isSubtypeOf(destDeclaredType.componentType())) { - snippetMethod = objectArrayCopy; - } - } - } - - if (snippetMethod != null) { - StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.compilerStorage().get(Graph.class); - assert snippetGraph != null : "ArrayCopySnippets should be installed"; - hits = true; - Debug.log(" > Intinsify (%s)", snippetMethod.signature().argumentTypeAt(0, snippetMethod.holder()).componentType()); - InliningUtil.inline(methodCallTarget.invoke(), snippetGraph, false); - } - } - if (hits) { - new CanonicalizerPhase(null, runtime, null).apply(graph); - } - } -} diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/SystemSnippets.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/SystemSnippets.java Wed Feb 01 11:36:50 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.snippets; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.nodes.extended.*; - -/** - * Snippets for {@link java.lang.System} methods. - */ -@ClassSubstitution(java.lang.System.class) -public class SystemSnippets implements SnippetsInterface { - - // TODO: public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) { } - - public static long currentTimeMillis() { - return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeMillis); - } - - public static long nanoTime() { - return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeNanos); - } - -} diff -r e952b6c6949b -r e8ce691d7923 graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/UnsafeSnippets.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/UnsafeSnippets.java Wed Feb 01 11:36:50 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.snippets; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.util.*; -import com.oracle.max.graal.nodes.extended.*; -import com.oracle.max.graal.nodes.java.*; - -/** - * Snippets for {@link sun.misc.Unsafe} methods. - */ -@ClassSubstitution(sun.misc.Unsafe.class) -public class UnsafeSnippets implements SnippetsInterface { - - public boolean compareAndSwapObject(Object o, long offset, Object expected, Object x) { - return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); - } - - public boolean compareAndSwapInt(Object o, long offset, int expected, int x) { - return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); - } - - public boolean compareAndSwapLong(Object o, long offset, long expected, long x) { - return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); - } - - public Object getObject(Object o, long offset) { - return UnsafeLoadNode.load(o, offset, CiKind.Object); - } - - public Object getObjectVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - Object result = getObject(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putObject(Object o, long offset, Object x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Object); - } - - public void putObjectVolatile(Object o, long offset, Object x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putObject(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public int getInt(Object o, long offset) { - Integer value = UnsafeLoadNode.load(o, offset, CiKind.Int); - return value; - } - - public int getIntVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - int result = getInt(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putInt(Object o, long offset, int x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Int); - } - - public void putIntVolatile(Object o, long offset, int x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putInt(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public boolean getBoolean(Object o, long offset) { - @JavacBug(id = 6995200) - Boolean result = UnsafeLoadNode.load(o, offset, CiKind.Boolean); - return result; - } - - public boolean getBooleanVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - boolean result = getBoolean(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putBoolean(Object o, long offset, boolean x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Boolean); - } - - public void putBooleanVolatile(Object o, long offset, boolean x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putBoolean(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public byte getByte(Object o, long offset) { - @JavacBug(id = 6995200) - Byte result = UnsafeLoadNode.load(o, offset, CiKind.Byte); - return result; - } - - public byte getByteVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - byte result = getByte(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putByte(Object o, long offset, byte x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Byte); - } - - public void putByteVolatile(Object o, long offset, byte x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putByte(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public short getShort(Object o, long offset) { - @JavacBug(id = 6995200) - Short result = UnsafeLoadNode.load(o, offset, CiKind.Short); - return result; - } - - public short getShortVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - short result = getShort(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putShort(Object o, long offset, short x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Short); - } - - public void putShortVolatile(Object o, long offset, short x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putShort(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public char getChar(Object o, long offset) { - @JavacBug(id = 6995200) - Character result = UnsafeLoadNode.load(o, offset, CiKind.Char); - return result; - } - - public char getCharVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - char result = getChar(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putChar(Object o, long offset, char x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Char); - } - - public void putCharVolatile(Object o, long offset, char x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putChar(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public long getLong(Object o, long offset) { - @JavacBug(id = 6995200) - Long result = UnsafeLoadNode.load(o, offset, CiKind.Long); - return result; - } - - public long getLongVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - long result = getLong(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putLong(Object o, long offset, long x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Long); - } - - public void putLongVolatile(Object o, long offset, long x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putLong(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public float getFloat(Object o, long offset) { - @JavacBug(id = 6995200) - Float result = UnsafeLoadNode.load(o, offset, CiKind.Float); - return result; - } - - public float getFloatVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - float result = getFloat(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putFloat(Object o, long offset, float x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Float); - } - - public void putFloatVolatile(Object o, long offset, float x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putFloat(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public double getDouble(Object o, long offset) { - @JavacBug(id = 6995200) - Double result = UnsafeLoadNode.load(o, offset, CiKind.Double); - return result; - } - - public double getDoubleVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - double result = getDouble(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putDouble(Object o, long offset, double x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Double); - } - - public void putDoubleVolatile(Object o, long offset, double x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putDouble(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } -}