changeset 22318:a016a0239ad9

Optimize argument access for foreign access functions.
author Christian Humer <christian.humer@oracle.com>
date Tue, 20 Oct 2015 18:21:19 +0200
parents 7005216255fa
children d0c672a6e632
files truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/CachedObjectAccessNode.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GenericObjectAccessNode.java
diffstat 3 files changed, 36 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/CachedObjectAccessNode.java	Tue Oct 20 18:21:19 2015 +0200
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/CachedObjectAccessNode.java	Tue Oct 20 18:21:19 2015 +0200
@@ -32,6 +32,8 @@
     @Child private ObjectAccessNode next;
     private final ForeignAccess languageCheck;
 
+    @Child private ForeignAccessArguments accessArguments = new ForeignAccessArguments();
+
     protected CachedObjectAccessNode(DirectCallNode callTarget, ObjectAccessNode next, ForeignAccess languageCheck) {
         this.callTarget = callTarget;
         this.next = next;
@@ -50,7 +52,7 @@
 
     private Object doAccess(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
         if (languageCheck.canHandle(receiver)) {
-            return callTarget.call(frame, ForeignAccessArguments.create(receiver, arguments));
+            return callTarget.call(frame, accessArguments.executeCreate(receiver, arguments));
         } else {
             return doNext(frame, receiver, arguments);
         }
--- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java	Tue Oct 20 18:21:19 2015 +0200
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java	Tue Oct 20 18:21:19 2015 +0200
@@ -24,19 +24,41 @@
  */
 package com.oracle.truffle.api.interop;
 
-final class ForeignAccessArguments {
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.nodes.Node;
+
+final class ForeignAccessArguments extends Node {
+
     static final Object[] EMPTY_ARGUMENTS_ARRAY = new Object[0];
     static final int RECEIVER_INDEX = 0;
     static final int RUNTIME_ARGUMENT_COUNT = 1;
 
-    static Object[] create(Object receiver, Object... arguments) {
-        if (arguments.length == 0) {
-            return new Object[]{receiver};
+    @CompilationFinal private int previousLength = -2;
+
+    public Object[] executeCreate(Object receiver, Object... arguments) {
+        int length = profileLength(arguments.length);
+        Object[] objectArguments = new Object[RUNTIME_ARGUMENT_COUNT + length];
+        objectArguments[RECEIVER_INDEX] = receiver;
+        arraycopy(arguments, 0, objectArguments, RUNTIME_ARGUMENT_COUNT, length);
+        return objectArguments;
+    }
+
+    private int profileLength(int length) {
+        int returnLength = length;
+        if (previousLength != -1) {
+            if (previousLength == length) {
+                returnLength = previousLength;
+            } else {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                if (previousLength == -2) {
+                    previousLength = length;
+                } else {
+                    previousLength = -1;
+                }
+            }
         }
-        Object[] objectArguments = new Object[RUNTIME_ARGUMENT_COUNT + arguments.length];
-        objectArguments[RECEIVER_INDEX] = receiver;
-        arraycopy(arguments, 0, objectArguments, RUNTIME_ARGUMENT_COUNT, arguments.length);
-        return objectArguments;
+        return returnLength;
     }
 
     private static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
--- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GenericObjectAccessNode.java	Tue Oct 20 18:21:19 2015 +0200
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GenericObjectAccessNode.java	Tue Oct 20 18:21:19 2015 +0200
@@ -34,6 +34,8 @@
     private final Message access;
     @Child private IndirectCallNode indirectCallNode;
 
+    @Child private ForeignAccessArguments accessArguments = new ForeignAccessArguments();
+
     public GenericObjectAccessNode(Message access) {
         this.access = access;
         indirectCallNode = Truffle.getRuntime().createIndirectCallNode();
@@ -50,7 +52,7 @@
         if (ct == null) {
             throw messageNotRecognizedException(fa);
         }
-        return indirectCallNode.call(frame, ct, ForeignAccessArguments.create(truffleObject, arguments));
+        return indirectCallNode.call(frame, ct, accessArguments.executeCreate(truffleObject, arguments));
     }
 
     @CompilerDirectives.TruffleBoundary