changeset 4412:ccbdd90bf356

Add new arraycopy intrinsics : Object (when no storecheck required), Float and Double
author Gilles Duboscq <duboscq@ssw.jku.at>
date Mon, 30 Jan 2012 15:08:49 +0100
parents cd2b68ef8e23
children c8de52cc672a
files graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java
diffstat 2 files changed, 104 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java	Mon Jan 30 13:06:11 2012 +0100
+++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java	Mon Jan 30 15:08:49 2012 +0100
@@ -154,6 +154,29 @@
     }
 
     @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();
@@ -169,6 +192,37 @@
     }
 
     @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--) {
@@ -204,6 +258,16 @@
         }
     }
 
+    // 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
@@ -255,4 +319,14 @@
             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);
+        }
+    }
 }
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java	Mon Jan 30 13:06:11 2012 +0100
+++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java	Mon Jan 30 15:08:49 2012 +0100
@@ -24,6 +24,7 @@
 
 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.*;
@@ -40,6 +41,9 @@
     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;
@@ -49,6 +53,9 @@
             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();
@@ -78,19 +85,29 @@
                 if (srcDeclaredType != null
                                 && srcDeclaredType.isArrayClass()
                                 && destDeclaredType != null
-                                && destDeclaredType.isArrayClass()
-                                && srcDeclaredType.componentType() == destDeclaredType.componentType()) {
-                    Class<?> componentType = srcDeclaredType.componentType().toJava();
-                    if (componentType.equals(int.class)) {
-                        snippetMethod = intArrayCopy;
-                    } else if (componentType.equals(char.class)) {
-                        snippetMethod = charArrayCopy;
-                    } else if (componentType.equals(long.class)) {
-                        snippetMethod = longArrayCopy;
-                    } else if (componentType.equals(byte.class)) {
-                        snippetMethod = byteArrayCopy;
-                    } else if (componentType.equals(short.class)) {
-                        snippetMethod = shortArrayCopy;
+                                && 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;
                     }
                 }
             }