From a3e66cf3900c11ad2c82847e3a91aeecfc69af56 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 30 Mar 2015 13:51:59 +0200
Subject: [PATCH] CallArgumentsNode.evaluateFlatten to evaluate and flatten in
 one step

---
 .../r/nodes/function/CallArgumentsNode.java   | 59 +++++++++++++++++--
 .../r/nodes/function/GroupDispatchNode.java   | 17 +-----
 2 files changed, 56 insertions(+), 20 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
index 6563d5ff14..f9e95e8bb9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
@@ -25,19 +25,21 @@ package com.oracle.truffle.r.nodes.function;
 import java.util.*;
 
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.r.nodes.instrument.CreateWrapper;
-import com.oracle.truffle.api.instrument.ProbeNode;
+import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.nodes.access.*;
 import com.oracle.truffle.r.nodes.access.variables.*;
+import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode;
+import com.oracle.truffle.r.nodes.instrument.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
-import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.*;
 
 /**
  * This class denotes a list of {@link #getArguments()} together with their names given to a
@@ -52,6 +54,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 public class CallArgumentsNode extends ArgumentsNode implements UnmatchedArguments {
 
     @Child private FrameSlotNode varArgsSlotNode;
+    @Child private PromiseCheckHelperNode promiseHelper;
 
     /**
      * If a supplied argument is a {@link ReadVariableNode} whose name is "...", this field contains
@@ -282,6 +285,54 @@ public class CallArgumentsNode extends ArgumentsNode implements UnmatchedArgumen
         }
     }
 
+    @ExplodeLoop
+    public RArgsValuesAndNames evaluateFlatten(VirtualFrame frame) {
+        int size = arguments.length;
+        RArgsValuesAndNames varArgInfo = null;
+        ArgumentsSignature resultSignature = null;
+        String[] names = null;
+        if (containsVarArgsSymbol()) {
+            varArgInfo = getVarargsAndNames(frame);
+            size += (varArgInfo.length() - 1) * varArgsSymbolIndices.length;
+            names = new String[size];
+        } else {
+            resultSignature = signature;
+        }
+        Object[] values = new Object[size];
+        int vargsSymbolsIndex = 0;
+        int index = 0;
+        for (int i = 0; i < arguments.length; i++) {
+            if (vargsSymbolsIndex < varArgsSymbolIndices.length && varArgsSymbolIndices[vargsSymbolsIndex] == i) {
+                index = flattenVarArgs(frame, varArgInfo, names, values, index);
+                vargsSymbolsIndex++;
+            } else {
+                values[index] = arguments[i] == null ? RMissing.instance : arguments[i].execute(frame);
+                if (names != null) {
+                    names[index] = signature.getName(i);
+                }
+                index++;
+            }
+        }
+        if (resultSignature == null) {
+            resultSignature = ArgumentsSignature.get(names);
+        }
+        return new RArgsValuesAndNames(values, resultSignature);
+    }
+
+    private int flattenVarArgs(VirtualFrame frame, RArgsValuesAndNames varArgInfo, String[] names, Object[] values, int startIndex) {
+        int index = startIndex;
+        for (int j = 0; j < varArgInfo.length(); j++) {
+            if (promiseHelper == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                promiseHelper = insert(new PromiseCheckHelperNode());
+            }
+            values[index] = promiseHelper.checkEvaluate(frame, varArgInfo.getValues()[j]);
+            names[index] = varArgInfo.getSignature().getName(j);
+            index++;
+        }
+        return index;
+    }
+
     @TruffleBoundary
     public static RNode wrapVarArgValue(Object varArgValue, int varArgIndex) {
         if (varArgValue instanceof RPromise) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java
index 28b1c7ad4c..6afdb0f6e4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java
@@ -67,21 +67,6 @@ public final class GroupDispatchNode extends RNode {
         return getSourceSection();
     }
 
-    protected RArgsValuesAndNames evalArgs(VirtualFrame frame) {
-        UnrolledVariadicArguments unrolledArgs = callArgsNode.executeFlatten(frame);
-        RNode[] unevaledArgs = unrolledArgs.getArguments();
-        Object[] evaledArgs = new Object[unevaledArgs.length];
-        for (int i = 0; i < unevaledArgs.length; ++i) {
-            if (unevaledArgs[i] != null) {
-                evaledArgs[i] = unevaledArgs[i].execute(frame);
-            } else {
-                evaledArgs[i] = RMissing.instance;
-            }
-        }
-        // Delay assignment to allow recursion
-        return new RArgsValuesAndNames(evaledArgs, unrolledArgs.getSignature());
-    }
-
     @Override
     public boolean isSyntax() {
         return true;
@@ -115,7 +100,7 @@ public final class GroupDispatchNode extends RNode {
 
     @Override
     public Object execute(VirtualFrame frame) {
-        RArgsValuesAndNames argAndNames = evalArgs(frame);
+        RArgsValuesAndNames argAndNames = callArgsNode.evaluateFlatten(frame);
         Object[] evaluatedArgs = argAndNames.getValues();
 
         RStringVector typeL = evaluatedArgs.length == 0 ? null : getArgClass(evaluatedArgs[0]);
-- 
GitLab