From 7c0b9b6170a97cf59718a3a15c541700b33d3fb5 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 20 Sep 2016 15:47:52 +0200
Subject: [PATCH] pass visibility through RCaller object

---
 .../r/nodes/builtin/base/EvalFunctions.java   |  4 +--
 .../r/nodes/builtin/RBuiltinRootNode.java     | 17 ++++------
 .../r/nodes/function/CallMatcherNode.java     | 13 ++++++--
 .../call/CallRFunctionCachedNode.java         | 14 ++++----
 .../function/call/CallRFunctionNode.java      |  2 +-
 .../visibility/SetVisibilityNode.java         | 32 +++++++++----------
 .../com/oracle/truffle/r/runtime/RCaller.java |  9 ++++++
 .../truffle/r/runtime/RInternalCode.java      |  2 +-
 8 files changed, 53 insertions(+), 40 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java
index 34a92b2682..2c3f263917 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java
@@ -134,13 +134,13 @@ public class EvalFunctions {
                 try {
                     return RContext.getEngine().eval((RExpression) expr1, envir1, rCaller);
                 } finally {
-                    visibility.executeAfterCall(frame);
+                    visibility.executeAfterCall(frame, rCaller);
                 }
             } else if (expr1 instanceof RLanguage) {
                 try {
                     return RContext.getEngine().eval((RLanguage) expr1, envir1, rCaller);
                 } finally {
-                    visibility.executeAfterCall(frame);
+                    visibility.executeAfterCall(frame, rCaller);
                 }
             } else {
                 // just return value
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
index a4f5ca5269..f402cf9e9b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
@@ -29,18 +29,18 @@ import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
+import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.runtime.RDispatch;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RVisibility;
 import com.oracle.truffle.r.runtime.builtins.FastPathFactory;
-import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
 public final class RBuiltinRootNode extends RRootNode {
 
     @Child private RBuiltinNode builtin;
+    @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
     private final RBuiltinFactory factory;
 
@@ -65,24 +65,19 @@ public final class RBuiltinRootNode extends RRootNode {
     @Override
     public Object execute(VirtualFrame frame) {
         verifyEnclosingAssumptions(frame);
-        Object result = null;
         try {
             if (builtin == null) {
                 assert factory.getDispatch() == RDispatch.SPECIAL : "null builtin node only allowed for SPECIAL dispatch";
                 throw RError.error(RError.SHOW_CALLER, Message.INVALID_USE, factory.getName());
             }
-            result = builtin.execute(frame);
+            return builtin.execute(frame);
         } catch (NullPointerException | ArrayIndexOutOfBoundsException | AssertionError e) {
             CompilerDirectives.transferToInterpreter();
             throw new RInternalError(e, "internal error");
+        } finally {
+            visibility.execute(frame, factory.getVisibility());
+            visibility.executeEndOfFunction(frame);
         }
-        if (factory.getVisibility() == RVisibility.OFF) {
-            RContext.getInstance().setVisible(false);
-        } else if (factory.getVisibility() == RVisibility.ON) {
-            RContext.getInstance().setVisible(true);
-        }
-
-        return result;
     }
 
     public RBuiltinNode getBuiltinNode() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java
index 58f248caeb..6cb1c9e2fa 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java
@@ -252,7 +252,11 @@ public abstract class CallMatcherNode extends RBaseNode {
                     String genFunctionName = functionName == null ? function.getName() : functionName;
                     Supplier<RSyntaxNode> argsSupplier = RCallerHelper.createFromArguments(genFunctionName, preparePermutation, suppliedArguments, suppliedSignature);
                     RCaller caller = genFunctionName == null ? RCaller.createInvalid(frame, parent) : RCaller.create(frame, parent, argsSupplier);
-                    return call.execute(frame, cachedFunction, caller, null, reorderedArgs, matchedArgs.getSignature(), cachedFunction.getEnclosingFrame(), dispatchArgs);
+                    try {
+                        return call.execute(frame, cachedFunction, caller, null, reorderedArgs, matchedArgs.getSignature(), cachedFunction.getEnclosingFrame(), dispatchArgs);
+                    } finally {
+                        visibility.executeAfterCall(frame, caller);
+                    }
                 } else {
                     applyCasts(reorderedArgs);
                     Object result = builtin.execute(frame, reorderedArgs);
@@ -327,6 +331,7 @@ public abstract class CallMatcherNode extends RBaseNode {
         }
 
         @Child private CallRFunctionCachedNode call = CallRFunctionCachedNodeGen.create(0);
+        @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
         @Override
         public Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, String functionName, DispatchArgs dispatchArgs) {
@@ -338,7 +343,11 @@ public abstract class CallMatcherNode extends RBaseNode {
             RCaller caller = genFunctionName == null ? RCaller.createInvalid(frame, parent)
                             : RCaller.create(frame, RCallerHelper.createFromArguments(genFunctionName,
                                             new RArgsValuesAndNames(reorderedArgs.getArguments(), ArgumentsSignature.empty(reorderedArgs.getLength()))));
-            return call.execute(frame, function, caller, null, reorderedArgs.getArguments(), reorderedArgs.getSignature(), function.getEnclosingFrame(), dispatchArgs);
+            try {
+                return call.execute(frame, function, caller, null, reorderedArgs.getArguments(), reorderedArgs.getSignature(), function.getEnclosingFrame(), dispatchArgs);
+            } finally {
+                visibility.executeAfterCall(frame, caller);
+            }
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionCachedNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionCachedNode.java
index 1c8b0fce0b..bb8e9eb11a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionCachedNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionCachedNode.java
@@ -53,28 +53,28 @@ public abstract class CallRFunctionCachedNode extends Node {
 
     public final Object execute(VirtualFrame frame, RFunction function, RCaller call, MaterializedFrame callerFrame, Object[] evaluatedArgs, DispatchArgs dispatchArgs) {
         Object[] callArgs = RArguments.create(function, call, callerFrame, evaluatedArgs, dispatchArgs);
-        return execute(frame, function.getTarget(), callArgs);
+        return execute(frame, function.getTarget(), callArgs, call);
     }
 
     public final Object execute(VirtualFrame frame, RFunction function, RCaller call, MaterializedFrame callerFrame, Object[] evaluatedArgs,
                     ArgumentsSignature suppliedSignature, MaterializedFrame enclosingFrame, DispatchArgs dispatchArgs) {
         Object[] callArgs = RArguments.create(function, call, callerFrame, evaluatedArgs, suppliedSignature, enclosingFrame, dispatchArgs);
-        return execute(frame, function.getTarget(), callArgs);
+        return execute(frame, function.getTarget(), callArgs, call);
     }
 
-    protected abstract Object execute(VirtualFrame frame, CallTarget target, Object[] arguments);
+    protected abstract Object execute(VirtualFrame frame, CallTarget target, Object[] arguments, RCaller caller);
 
     protected static DirectCallNode createDirectCallNode(CallTarget target) {
         return Truffle.getRuntime().createDirectCallNode(target);
     }
 
     @Specialization(guards = "target == callNode.getCallTarget()", limit = "cacheLimit")
-    protected Object call(VirtualFrame frame, @SuppressWarnings("unused") CallTarget target, Object[] arguments,
+    protected Object call(VirtualFrame frame, @SuppressWarnings("unused") CallTarget target, Object[] arguments, RCaller caller,
                     @Cached("createDirectCallNode(target)") DirectCallNode callNode) {
         try {
             return callNode.call(frame, arguments);
         } finally {
-            visibility.executeAfterCall(frame);
+            visibility.executeAfterCall(frame, caller);
         }
     }
 
@@ -83,12 +83,12 @@ public abstract class CallRFunctionCachedNode extends Node {
     }
 
     @Specialization
-    protected Object call(VirtualFrame frame, CallTarget target, Object[] arguments,
+    protected Object call(VirtualFrame frame, CallTarget target, Object[] arguments, RCaller caller,
                     @Cached("createIndirectCallNode()") IndirectCallNode callNode) {
         try {
             return callNode.call(frame, target, arguments);
         } finally {
-            visibility.executeAfterCall(frame);
+            visibility.executeAfterCall(frame, caller);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionNode.java
index 6cdf8d2596..5a59ddbbf6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionNode.java
@@ -57,7 +57,7 @@ public final class CallRFunctionNode extends Node {
         try {
             return callNode.call(frame, callArgs);
         } finally {
-            visibility.executeAfterCall(frame);
+            visibility.executeAfterCall(frame, call);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java
index e6347e24ff..33ec70e1b2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java
@@ -33,6 +33,8 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.r.runtime.FastROptions;
+import com.oracle.truffle.r.runtime.RArguments;
+import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RVisibility;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -45,7 +47,7 @@ public abstract class SetVisibilityNode extends Node {
 
     public abstract void execute(VirtualFrame frame, RVisibility visibility);
 
-    public abstract void executeAfterCall(VirtualFrame frame);
+    public abstract void executeAfterCall(VirtualFrame frame, RCaller caller);
 
     public abstract void executeEndOfFunction(VirtualFrame frame);
 
@@ -75,7 +77,7 @@ public abstract class SetVisibilityNode extends Node {
         }
 
         @Override
-        public void executeAfterCall(VirtualFrame frame) {
+        public void executeAfterCall(VirtualFrame frame, RCaller caller) {
             // nothing to do
         }
 
@@ -102,7 +104,7 @@ public abstract class SetVisibilityNode extends Node {
         }
 
         @Override
-        public void executeAfterCall(VirtualFrame frame) {
+        public void executeAfterCall(VirtualFrame frame, RCaller caller) {
             // nothing to do
         }
 
@@ -119,12 +121,16 @@ public abstract class SetVisibilityNode extends Node {
 
         @CompilationFinal private FrameSlot frameSlot;
 
-        @Override
-        public void execute(Frame frame, boolean value) {
+        private void ensureFrameSlot(Frame frame) {
             if (frameSlot == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Object);
             }
+        }
+
+        @Override
+        public void execute(Frame frame, boolean value) {
+            ensureFrameSlot(frame);
             frame.setObject(frameSlot, value);
         }
 
@@ -138,24 +144,18 @@ public abstract class SetVisibilityNode extends Node {
         }
 
         @Override
-        public void executeAfterCall(VirtualFrame frame) {
-            if (frameSlot == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Object);
-            }
-            frame.setObject(frameSlot, null);
+        public void executeAfterCall(VirtualFrame frame, RCaller caller) {
+            ensureFrameSlot(frame);
+            frame.setObject(frameSlot, caller.getVisibility());
         }
 
         @Override
         public void executeEndOfFunction(VirtualFrame frame) {
-            if (frameSlot == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Object);
-            }
+            ensureFrameSlot(frame);
             try {
                 Object visibility = frame.getObject(frameSlot);
                 if (visibility != null) {
-                    RContext.getInstance().setVisible(visibility == Boolean.TRUE);
+                    RArguments.getCall(frame).setVisibility(visibility == Boolean.TRUE);
                 }
             } catch (FrameSlotTypeException e) {
                 throw RInternalError.shouldNotReachHere(e);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java
index 6de384ca59..d248667612 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java
@@ -38,6 +38,7 @@ public final class RCaller {
     private static final Object PROMISE_MARKER = new Object();
 
     private final int depth;
+    private boolean visibility;
     private final RCaller parent;
     /**
      * payload can be an RSyntaxNode, a {@link Supplier}, or an PROMISE_MARKER.
@@ -116,4 +117,12 @@ public final class RCaller {
     public static RCaller createForPromise(RCaller original, int newDepth) {
         return new RCaller(newDepth, original, PROMISE_MARKER);
     }
+
+    public boolean getVisibility() {
+        return visibility;
+    }
+
+    public void setVisibility(boolean visibility) {
+        this.visibility = visibility;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java
index 05c5cfbc2c..dc57b2b69c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java
@@ -66,7 +66,7 @@ public final class RInternalCode {
             evaluatedEnvironment.setParent(statsPackage);
             // caller is put into arguments by eval, internal code is assumed to be well-behaved and
             // not accessing it
-            context.getThisEngine().eval(parsedCode, evaluatedEnvironment, /* caller: */null);
+            context.getThisEngine().eval(parsedCode, evaluatedEnvironment, RCaller.createInvalid(null));
             return evaluatedEnvironment;
         } catch (ParseException e) {
             throw e.throwAsRError();
-- 
GitLab