From 3939299de13cf578d54b3d1c987e8da6e566565b Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 13 Feb 2018 12:19:21 +0100
Subject: [PATCH] Fix: do.call with function lookup puts the lookup into
 RCaller

---
 .../truffle/r/nodes/builtin/base/DoCall.java  | 28 +++++++++++--------
 .../truffle/r/test/ExpectedTestOutput.test    |  4 +++
 .../r/test/builtins/TestBuiltin_docall.java   |  1 +
 3 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index 626d44088d..b84f42df00 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -116,14 +116,15 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
         }
         // Note: if the function is in fact a promise, we are evaluating it here slightly earlier
         // than GNU R. It should not a be a problem.
-        RFunction func = (RFunction) getNode.execute(frame, what.getDataAt(0), env, RType.Function.getName(), true);
-        return doCall(frame, func, argsAsList, quote, env, internal);
+        String funcName = what.getDataAt(0);
+        RFunction func = (RFunction) getNode.execute(frame, funcName, env, RType.Function.getName(), true);
+        return internal.execute(frame, funcName, func, argsAsList, quote, env);
     }
 
     @Specialization
-    protected Object doCall(VirtualFrame virtualFrame, RFunction func, RList argsAsList, boolean quote, REnvironment env,
+    protected Object doCall(VirtualFrame frame, RFunction func, RList argsAsList, boolean quote, REnvironment env,
                     @Cached("create()") DoCallInternal internal) {
-        return internal.execute(virtualFrame, func, argsAsList, quote, env);
+        return internal.execute(frame, null, func, argsAsList, quote, env);
     }
 
     protected abstract static class DoCallInternal extends Node {
@@ -137,7 +138,7 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
             return DoCallInternalNodeGen.create();
         }
 
-        public abstract Object execute(VirtualFrame virtualFrame, RFunction func, RList argsAsList, boolean quote, REnvironment env);
+        public abstract Object execute(VirtualFrame virtualFrame, String funcName, RFunction func, RList argsAsList, boolean quote, REnvironment env);
 
         protected FrameDescriptor getFrameDescriptor(REnvironment env) {
             return env.getFrame(frameAccessProfile).getFrameDescriptor();
@@ -149,7 +150,7 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
          * {@link GetVisibilityNode} for each {@link FrameDescriptor} we encounter.
          */
         @Specialization(guards = {"getFrameDescriptor(env) == fd"}, limit = "20")
-        public Object doFastPath(VirtualFrame virtualFrame, RFunction func, RList argsAsList, boolean quote, REnvironment env,
+        public Object doFastPath(VirtualFrame virtualFrame, String funcName, RFunction func, RList argsAsList, boolean quote, REnvironment env,
                         @Cached("getFrameDescriptor(env)") @SuppressWarnings("unused") FrameDescriptor fd,
                         @Cached("create()") RExplicitCallNode explicitCallNode,
                         @Cached("create()") GetVisibilityNode getVisibilityNode,
@@ -157,7 +158,7 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
                         @Cached("create()") BranchProfile containsRSymbolProfile) {
             MaterializedFrame promiseFrame = env.getFrame(frameAccessProfile).materialize();
             RArgsValuesAndNames args = getArguments(promiseFrame, quote, quoteProfile, containsRSymbolProfile, argsAsList);
-            RCaller caller = getExplicitCaller(virtualFrame, promiseFrame, func, args);
+            RCaller caller = getExplicitCaller(virtualFrame, promiseFrame, funcName, func, args);
             MaterializedFrame evalFrame = getEvalFrame(virtualFrame, promiseFrame);
 
             Object resultValue = explicitCallNode.execute(evalFrame, func, args, caller);
@@ -170,13 +171,13 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
          * again and again and putting it behind truffle boundary to avoid deoptimization.
          */
         @Specialization(replaces = "doFastPath")
-        public Object doSlowPath(VirtualFrame virtualFrame, RFunction func, RList argsAsList, boolean quote, REnvironment env,
+        public Object doSlowPath(VirtualFrame virtualFrame, String funcName, RFunction func, RList argsAsList, boolean quote, REnvironment env,
                         @Cached("create()") SlowPathExplicitCall slowPathExplicitCall,
                         @Cached("createBinaryProfile()") ConditionProfile quoteProfile,
                         @Cached("create()") BranchProfile containsRSymbolProfile) {
             MaterializedFrame promiseFrame = env.getFrame(frameAccessProfile).materialize();
             RArgsValuesAndNames args = getArguments(promiseFrame, quote, quoteProfile, containsRSymbolProfile, argsAsList);
-            RCaller caller = getExplicitCaller(virtualFrame, promiseFrame, func, args);
+            RCaller caller = getExplicitCaller(virtualFrame, promiseFrame, funcName, func, args);
             MaterializedFrame evalFrame = getEvalFrame(virtualFrame, promiseFrame);
 
             Object resultValue = slowPathExplicitCall.execute(evalFrame, caller, func, args);
@@ -205,8 +206,13 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
          * @see RCaller
          * @see RArguments
          */
-        private RCaller getExplicitCaller(VirtualFrame virtualFrame, MaterializedFrame envFrame, RFunction func, RArgsValuesAndNames args) {
-            Supplier<RSyntaxElement> callerSyntax = RCallerHelper.createFromArguments(func, args);
+        private RCaller getExplicitCaller(VirtualFrame virtualFrame, MaterializedFrame envFrame, String funcName, RFunction func, RArgsValuesAndNames args) {
+            Supplier<RSyntaxElement> callerSyntax;
+            if (funcName != null) {
+                callerSyntax = RCallerHelper.createFromArguments(funcName, args);
+            } else {
+                callerSyntax = RCallerHelper.createFromArguments(func, args);
+            }
             return RCaller.create(RArguments.getDepth(virtualFrame) + 1, RArguments.getCall(envFrame), callerSyntax);
         }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 313560d7ad..560ee522da 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -23894,6 +23894,10 @@ a
 #{ e <- new.env(); assign('foo', function() 42, e); foo <- function(x) 1; do.call('foo', list(), envir=e); }
 [1] 42
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_docall.testDoCall#
+#{ f <- function() typeof(sys.call(0)[[1]]); do.call('f', list()); }
+[1] "symbol"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_docall.testDoCall#Output.IgnoreErrorContext#
 #{ f <- function(x) x; do.call(f, list(quote(y + 1)))}
 Error in (function (x)  : object 'y' not found
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_docall.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_docall.java
index 85d9ed9b4d..7c61648365 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_docall.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_docall.java
@@ -50,5 +50,6 @@ public class TestBuiltin_docall extends TestBase {
         assertEval("{ f1 <- function(a) ls(parent.frame(2)); f2 <- function(b) f1(b); f3 <- function(c) f2(c); f4 <- function(d) do.call('f3', list(d)); f4(42); }");
 
         assertEval("do.call('c', list())");
+        assertEval("{ f <- function() typeof(sys.call(0)[[1]]); do.call('f', list()); }");
     }
 }
-- 
GitLab