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