diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java index 30b8da14968b3e46595c9622bbcfeb677d395ebc..7baf39bb7d472663a413ba1c8264c101bf0df70c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java @@ -55,6 +55,7 @@ import com.oracle.truffle.r.nodes.function.PromiseNode.VarArgNode; import com.oracle.truffle.r.nodes.function.PromiseNode.VarArgsPromiseNode; import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.CallerFrameClosure; import com.oracle.truffle.r.runtime.HasSignature; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RCaller; @@ -164,7 +165,6 @@ public class FrameFunctions { return current; } } - notifyRCallNodes(actualFrame, RArguments.getCall(frame)); } return Utils.getStackFrame(access, actualFrame); } @@ -172,21 +172,13 @@ public class FrameFunctions { private static Frame getCallerFrame(Frame current) { Object callerFrame = RArguments.getCallerFrame(current); - return callerFrame instanceof Frame ? (Frame) callerFrame : null; - } - - @TruffleBoundary - private static void notifyRCallNodes(int actualFrame, RCaller caller) { - RCaller currentCaller = caller; - for (int i = 0; i < ITERATE_LEVELS; i++) { - if (currentCaller == null || currentCaller.getDepth() <= actualFrame) { - break; - } - if (currentCaller.isValidCaller() && !currentCaller.isPromise() && currentCaller.getSyntaxNode() instanceof RCallNode) { - ((RCallNode) currentCaller.getSyntaxNode()).setNeedsCallerFrame(); - } - currentCaller = currentCaller.getParent(); + if (callerFrame instanceof CallerFrameClosure) { + CallerFrameClosure closure = (CallerFrameClosure) callerFrame; + closure.setNeedsCallerFrame(); + return closure.getMaterializedCallerFrame(); } + assert callerFrame instanceof Frame; + return (Frame) callerFrame; } } 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 fe03a9b9a5f5f2e6606b012a513f4578757b619e..5ec1cab2849f619f1d6e083541e6d07bbf1246f2 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 @@ -16,6 +16,7 @@ import java.util.function.Supplier; 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.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.NodeCost; @@ -32,6 +33,7 @@ import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RArguments.DispatchArgs; +import com.oracle.truffle.r.runtime.RArguments.S3Args; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RVisibility; @@ -263,8 +265,11 @@ public abstract class CallMatcherNode extends RBaseNode { String genFunctionName = functionName == null ? function.getName() : functionName; Supplier<RSyntaxElement> argsSupplier = RCallerHelper.createFromArguments(genFunctionName, preparePermutation, suppliedArguments, suppliedSignature); RCaller caller = genFunctionName == null ? RCaller.createInvalid(frame, parent) : RCaller.create(frame, parent, argsSupplier); + MaterializedFrame callerFrame = dispatchArgs instanceof S3Args ? ((S3Args) dispatchArgs).callEnv : null; try { - return call.execute(frame, cachedFunction, caller, reorderedArgs, matchedArgs.getSignature(), cachedFunction.getEnclosingFrame(), dispatchArgs); + return call.execute(frame, cachedFunction, caller, callerFrame, parent == null || parent.getDepth() == 0, reorderedArgs, matchedArgs.getSignature(), + cachedFunction.getEnclosingFrame(), + dispatchArgs); } finally { visibility.executeAfterCall(frame, caller); } @@ -343,8 +348,9 @@ 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())))); + MaterializedFrame callerFrame = (dispatchArgs instanceof S3Args) ? ((S3Args) dispatchArgs).callEnv : null; try { - return call.execute(frame, function, caller, reorderedArgs.getArguments(), reorderedArgs.getSignature(), function.getEnclosingFrame(), dispatchArgs); + return call.execute(frame, function, caller, callerFrame, reorderedArgs.getArguments(), reorderedArgs.getSignature(), function.getEnclosingFrame(), dispatchArgs); } finally { visibility.executeAfterCall(frame, caller); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java index 1583d0222e7a1d285baad422132c346c1874ebef..b3ca25d93dec0cf40f7046dbaebd39592176445e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.nodes.function; -import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.Frame; @@ -30,9 +29,9 @@ import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.r.runtime.CallerFrameClosure; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.CallerFrameClosure; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -48,7 +47,6 @@ public final class GetCallerFrameNode extends RBaseNode { public MaterializedFrame execute(Frame frame) { Object callerFrameObject = RArguments.getCallerFrame(frame); - MaterializedFrame mCallerFrame; if (callerFrameObject instanceof CallerFrameClosure) { if (!slowPathInitialized) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -62,14 +60,14 @@ public final class GetCallerFrameNode extends RBaseNode { // if interpreted, we will have a materialized frame in the closure MaterializedFrame materializedCallerFrame = closure.getMaterializedCallerFrame(); if (materializedCallerFrame != null) { - CompilerAsserts.neverPartOfCompilation(); + assert CompilerDirectives.inInterpreter() || materializedCallerFrame == null; return materializedCallerFrame; } RError.performanceWarning("slow caller frame access"); // for now, get it on the very slow path Frame callerFrame = Utils.getCallerFrame(frame, FrameAccess.MATERIALIZE); if (callerFrame != null) { - mCallerFrame = callerFrame.materialize(); + callerFrameObject = callerFrame.materialize(); } } if (callerFrameObject == null) { @@ -78,11 +76,9 @@ public final class GetCallerFrameNode extends RBaseNode { // must be the top level case. topLevelProfile.enter(); return frame.materialize(); - } else { - mCallerFrame = (MaterializedFrame) callerFrameObject; } assert callerFrameObject instanceof MaterializedFrame; - return mCallerFrame; + return (MaterializedFrame) callerFrameObject; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java index f1996378bde793255c0bc50eef27cb8fa4343908..61bbb2e68208a2078cc75d36b59bb4bffa4952e7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java @@ -986,7 +986,8 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } } - return call.execute(frame, function, originalCall.createCaller(frame, function), orderedArguments.getArguments(), orderedArguments.getSignature(), function.getEnclosingFrame(), s3Args); + return call.execute(frame, function, originalCall.createCaller(frame, function), orderedArguments.getArguments(), orderedArguments.getSignature(), function.getEnclosingFrame(), + s3Args); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionBaseNode.java index 4f8ca2212e387c8966beee4f1da48f13b0159958..6580ae783689e776968c484aae1c23df6a6d8610 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/CallRFunctionBaseNode.java @@ -1,3 +1,25 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ package com.oracle.truffle.r.nodes.function.call; import com.oracle.truffle.api.Assumption; @@ -12,6 +34,7 @@ public abstract class CallRFunctionBaseNode extends Node { protected final Assumption needsNoCallerFrame = Truffle.getRuntime().createAssumption("no caller frame"); protected final CallerFrameClosure invalidateNoCallerFrame = new InvalidateNoCallerFrame(needsNoCallerFrame); + private static final CallerFrameClosure DUMMY = new DummyCallerFrameClosure(); public boolean setNeedsCallerFrame() { boolean value = !needsNoCallerFrame.isValid(); @@ -19,17 +42,50 @@ public abstract class CallRFunctionBaseNode extends Node { return value; } + private Object getCallerFrameClosure(MaterializedFrame callerFrame) { + if (CompilerDirectives.inInterpreter()) { + return new InvalidateNoCallerFrame(needsNoCallerFrame, callerFrame); + } + return invalidateNoCallerFrame; + } + private Object getCallerFrameClosure(VirtualFrame callerFrame) { if (CompilerDirectives.inInterpreter()) { - return new InvalidateNoCallerFrame(needsNoCallerFrame, callerFrame.materialize()); + return new InvalidateNoCallerFrame(needsNoCallerFrame, callerFrame != null ? callerFrame.materialize() : null); } return invalidateNoCallerFrame; } + protected final Object getCallerFrameObject(VirtualFrame curFrame, MaterializedFrame callerFrame, boolean topLevel) { + if (needsNoCallerFrame.isValid()) { + return getCallerFrameClosure(callerFrame); + } else { + if (callerFrame != null) { + return callerFrame; + } else if (topLevel) { + return DUMMY; + } + return curFrame.materialize(); + } + } + protected final Object getCallerFrameObject(VirtualFrame callerFrame) { return needsNoCallerFrame.isValid() ? getCallerFrameClosure(callerFrame) : callerFrame.materialize(); } + private static final class DummyCallerFrameClosure extends CallerFrameClosure { + + @Override + public void setNeedsCallerFrame() { + } + + @Override + public MaterializedFrame getMaterializedCallerFrame() { + return null; + } + + } + public static final class InvalidateNoCallerFrame extends CallerFrameClosure { private final Assumption needsNoCallerFrame; 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 43fd6ecc99ca99dba05e16744f0ad1da6159c160..b94e7a9a1a6f6a518d7b3bc892e8dd26885cfc04 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 @@ -61,6 +61,12 @@ public abstract class CallRFunctionCachedNode extends CallRFunctionBaseNode { 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, getCallerFrameObject(frame, callerFrame, false), evaluatedArgs, suppliedSignature, enclosingFrame, dispatchArgs); + return execute(frame, function.getTarget(), callArgs, call); + } + protected abstract Object execute(VirtualFrame frame, CallTarget target, Object[] arguments, RCaller caller); protected static DirectCallNode createDirectCallNode(CallTarget target) { 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 432d72b8379bb61837877f537cc3148c5ff297df..89f202ced9792e15e82029bcc0c3ba56263a133c 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 @@ -50,9 +50,19 @@ public final class CallRFunctionNode extends CallRFunctionBaseNode { return new CallRFunctionNode(callTarget); } + public Object execute(VirtualFrame frame, RFunction function, RCaller caller, MaterializedFrame candidate, boolean topLevel, Object[] evaluatedArgs, ArgumentsSignature suppliedSignature, + MaterializedFrame enclosingFrame, DispatchArgs dispatchArgs) { + Object[] callArgs = RArguments.create(function, caller, getCallerFrameObject(frame, candidate, topLevel), evaluatedArgs, suppliedSignature, enclosingFrame, dispatchArgs); + try { + return callNode.call(callArgs); + } finally { + visibility.executeAfterCall(frame, caller); + } + } + public Object execute(VirtualFrame frame, RFunction function, RCaller caller, Object[] evaluatedArgs, ArgumentsSignature suppliedSignature, MaterializedFrame enclosingFrame, DispatchArgs dispatchArgs) { - Object[] callArgs = RArguments.create(function, caller, getCallerFrameObject(frame), evaluatedArgs, suppliedSignature, enclosingFrame, dispatchArgs); + Object[] callArgs = RArguments.create(function, caller, getCallerFrameObject(frame, null, true), evaluatedArgs, suppliedSignature, enclosingFrame, dispatchArgs); try { return callNode.call(callArgs); } finally {