From 39cb41f173993e17f47e0f1e5d653286fe837963 Mon Sep 17 00:00:00 2001 From: Lukas Stadler <lukas.stadler@oracle.com> Date: Tue, 9 Feb 2016 13:20:44 +0100 Subject: [PATCH] refactor S4 dispatching to use S3Args-like mechanism instead of creating additional frames --- .../builtin/base/S3DispatchFunctions.java | 12 +- .../r/nodes/builtin/base/StandardGeneric.java | 18 +- .../r/nodes/function/CallMatcherNode.java | 60 ++++-- .../function/FunctionDefinitionNode.java | 166 ++++++++++----- .../function/signature/RArgumentsNode.java | 16 +- .../r/nodes/objects/DispatchGeneric.java | 4 +- .../r/nodes/objects/ExecuteMethod.java | 51 ++--- .../truffle/r/nodes/objects/LoadMethod.java | 7 +- .../oracle/truffle/r/runtime/RArguments.java | 48 +++-- .../oracle/truffle/r/runtime/RRuntime.java | 12 +- .../truffle/r/test/ExpectedTestOutput.test | 201 ++++++++++++++++++ .../com/oracle/truffle/r/test/S4/TestS4.java | 3 +- 12 files changed, 445 insertions(+), 153 deletions(-) diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java index 591ef9b773..c312f099b5 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2014, Purdue University - * Copyright (c) 2014, 2015, Oracle and/or its affiliates + * Copyright (c) 2014, 2016, Oracle and/or its affiliates * * All rights reserved. */ @@ -156,11 +156,11 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { @RBuiltin(name = "NextMethod", kind = SUBSTITUTE, parameterNames = {"generic", "object", "..."}) public abstract static class NextMethod extends S3DispatchFunctions { - @Child private LocalReadVariableNode rvnGroup = LocalReadVariableNode.create(RRuntime.RDotGroup, false); - @Child private LocalReadVariableNode rvnClass = LocalReadVariableNode.create(RRuntime.RDotClass, false); - @Child private LocalReadVariableNode rvnGeneric = LocalReadVariableNode.create(RRuntime.RDotGeneric, false); - @Child private LocalReadVariableNode rvnCall = LocalReadVariableNode.create(RRuntime.RDotGenericCallEnv, false); - @Child private LocalReadVariableNode rvnDef = LocalReadVariableNode.create(RRuntime.RDotGenericDefEnv, false); + @Child private LocalReadVariableNode rvnGroup = LocalReadVariableNode.create(RRuntime.R_DOT_GROUP, false); + @Child private LocalReadVariableNode rvnClass = LocalReadVariableNode.create(RRuntime.R_DOT_CLASS, false); + @Child private LocalReadVariableNode rvnGeneric = LocalReadVariableNode.create(RRuntime.R_DOT_GENERIC, false); + @Child private LocalReadVariableNode rvnCall = LocalReadVariableNode.create(RRuntime.R_DOT_GENERIC_CALL_ENV, false); + @Child private LocalReadVariableNode rvnDef = LocalReadVariableNode.create(RRuntime.R_DOT_GENERIC_DEF_ENV, false); @Child private CombineSignaturesNode combineSignatures; @Child private CollectArgumentsNode collectArguments = CollectArgumentsNodeGen.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java index 097062b22e..c8bd90527c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java @@ -6,7 +6,7 @@ * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka * Copyright (c) 1995-2014, The R Core Team * Copyright (c) 2002-2008, The R Foundation - * Copyright (c) 2015, Oracle and/or its affiliates + * Copyright (c) 2015, 2016, Oracle and/or its affiliates * * All rights reserved. */ @@ -118,7 +118,6 @@ public abstract class StandardGeneric extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); collectArgumentsNode = insert(CollectGenericArgumentsNodeGen.create(sigArgs.getDataWithoutCopying(), sigLength)); } - String[] classes = collectArgumentsNode.execute(frame, sigArgs, sigLength); Object ret = dispatchGeneric.executeObject(frame, methodsEnv, mtable, RDataFactory.createStringVector(classes, RDataFactory.COMPLETE_VECTOR), fdef, fname); return ret; @@ -132,6 +131,10 @@ public abstract class StandardGeneric extends RBuiltinNode { if (attributes == null) { return null; } + if (genericAttrAccess == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + genericAttrAccess = insert(AttributeAccessNodeGen.create(RRuntime.GENERIC_ATTR_KEY)); + } genObj = genericAttrAccess.execute(attributes); if (genObj == null) { return null; @@ -148,17 +151,16 @@ public abstract class StandardGeneric extends RBuiltinNode { protected Object stdGeneric(VirtualFrame frame, RAbstractStringVector fVec, @SuppressWarnings("unused") RMissing fdef) { String fname = fVec.getDataAt(0); int n = RArguments.getDepth(frame); - if (genericAttrAccess == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - assert sysFunction == null; - genericAttrAccess = insert(AttributeAccessNodeGen.create(RRuntime.GENERIC_ATTR_KEY)); - sysFunction = insert(FrameFunctionsFactory.SysFunctionNodeGen.create(new RNode[1], null, null)); - } Object fnObj = RArguments.getFunction(frame); fnObj = getFunction(frame, fVec, fname, fnObj); if (fnObj != null) { return fnObj; } + if (sysFunction == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + sysFunction = insert(FrameFunctionsFactory.SysFunctionNodeGen.create(new RNode[1], null, null)); + RError.performanceWarning("sys.frame usage in standardGeneric"); + } // TODO: GNU R counts to (i < n) - does their equivalent of getDepth return a different // value // TODO; shouldn't we count from n to 0? 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 3b8ebc385a..469da5f98f 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 @@ -11,21 +11,35 @@ package com.oracle.truffle.r.nodes.function; -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.api.nodes.*; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.*; -import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.DirectCallNode; +import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.nodes.IndirectCallNode; +import com.oracle.truffle.api.nodes.NodeCost; +import com.oracle.truffle.api.nodes.NodeInfo; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.RRootNode; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.RBuiltinRootNode; import com.oracle.truffle.r.nodes.function.ArgumentMatcher.MatchPermutation; -import com.oracle.truffle.r.nodes.function.signature.*; -import com.oracle.truffle.r.nodes.unary.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.RArguments.S3Args; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; +import com.oracle.truffle.r.nodes.unary.CastNode; +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.RCaller; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.REmpty; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class CallMatcherNode extends RBaseNode { @@ -50,7 +64,7 @@ public abstract class CallMatcherNode extends RBaseNode { return new CallMatcherUninitializedNode(forNextMethod, argsAreEvaluated); } - public abstract Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, S3Args s3Args); + public abstract Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, DispatchArgs dispatchArgs); protected CallMatcherCachedNode specialize(ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, CallMatcherNode next) { @@ -90,8 +104,8 @@ public abstract class CallMatcherNode extends RBaseNode { return new CallMatcherCachedNode(suppliedSignature, varArgSignatures, function, preparePermutation, permutation, forNextMethod, argsAreEvaluated, next); } - protected Object[] prepareArguments(VirtualFrame frame, Object[] reorderedArgs, ArgumentsSignature reorderedSignature, RFunction function, S3Args s3Args) { - return argsNode.execute(function, caller, null, RArguments.getDepth(frame) + 1, reorderedArgs, reorderedSignature, s3Args); + protected Object[] prepareArguments(VirtualFrame frame, Object[] reorderedArgs, ArgumentsSignature reorderedSignature, RFunction function, DispatchArgs dispatchArgs) { + return argsNode.execute(function, caller, null, RArguments.getDepth(frame) + 1, reorderedArgs, reorderedSignature, dispatchArgs); } protected final void evaluatePromises(VirtualFrame frame, RFunction function, Object[] args, int varArgIndex) { @@ -139,17 +153,17 @@ public abstract class CallMatcherNode extends RBaseNode { private int depth; @Override - public Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, S3Args s3Args) { + public Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, DispatchArgs dispatchArgs) { CompilerDirectives.transferToInterpreterAndInvalidate(); if (++depth > MAX_CACHE_DEPTH) { - return replace(new CallMatcherGenericNode(forNextMethod, argsAreEvaluated)).execute(frame, suppliedSignature, suppliedArguments, function, s3Args); + return replace(new CallMatcherGenericNode(forNextMethod, argsAreEvaluated)).execute(frame, suppliedSignature, suppliedArguments, function, dispatchArgs); } else { CallMatcherCachedNode cachedNode = replace(specialize(suppliedSignature, suppliedArguments, function, this)); // for splitting if necessary if (cachedNode.call != null && RCallNode.needsSplitting(function)) { cachedNode.call.cloneCallTarget(); } - return cachedNode.execute(frame, suppliedSignature, suppliedArguments, function, s3Args); + return cachedNode.execute(frame, suppliedSignature, suppliedArguments, function, dispatchArgs); } } @@ -196,7 +210,7 @@ public abstract class CallMatcherNode extends RBaseNode { } @Override - public Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, S3Args s3Args) { + public Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, DispatchArgs dispatchArgs) { if (suppliedSignature == cachedSuppliedSignature && function == cachedFunction && checkLastArgSignature(cachedSuppliedSignature, suppliedArguments)) { Object[] preparedArguments = prepareSuppliedArgument(preparePermutation, suppliedArguments); @@ -204,14 +218,14 @@ public abstract class CallMatcherNode extends RBaseNode { Object[] reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(permutation, preparedArguments, formals); evaluatePromises(frame, cachedFunction, reorderedArgs, formals.getSignature().getVarArgIndex()); if (call != null) { - Object[] arguments = prepareArguments(frame, reorderedArgs, formals.getSignature(), cachedFunction, s3Args); + Object[] arguments = prepareArguments(frame, reorderedArgs, formals.getSignature(), cachedFunction, dispatchArgs); return call.call(frame, arguments); } else { applyCasts(reorderedArgs); return builtin.execute(frame, reorderedArgs); } } else { - return next.execute(frame, suppliedSignature, suppliedArguments, function, s3Args); + return next.execute(frame, suppliedSignature, suppliedArguments, function, dispatchArgs); } } @@ -281,10 +295,10 @@ public abstract class CallMatcherNode extends RBaseNode { private final ConditionProfile hasVarArgsProfile = ConditionProfile.createBinaryProfile(); @Override - public Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, S3Args s3Args) { + public Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, DispatchArgs dispatchArgs) { EvaluatedArguments reorderedArgs = reorderArguments(suppliedArguments, function, suppliedSignature); evaluatePromises(frame, function, reorderedArgs.getArguments(), reorderedArgs.getSignature().getVarArgIndex()); - Object[] arguments = prepareArguments(frame, reorderedArgs.getArguments(), reorderedArgs.getSignature(), function, s3Args); + Object[] arguments = prepareArguments(frame, reorderedArgs.getArguments(), reorderedArgs.getSignature(), function, dispatchArgs); return call.call(frame, function.getTarget(), arguments); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java index 6b0189cb79..b156a78e61 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java @@ -22,31 +22,57 @@ */ package com.oracle.truffle.r.nodes.function; -import java.util.*; +import java.util.ArrayList; -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.api.instrument.*; -import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotTypeException; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.instrument.QuitException; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.NodeUtil; import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; -import com.oracle.truffle.api.source.*; -import com.oracle.truffle.api.profiles.*; -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.control.*; -import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.InlineCacheNode; +import com.oracle.truffle.r.nodes.RASTUtils; +import com.oracle.truffle.r.nodes.RRootNode; +import com.oracle.truffle.r.nodes.access.FrameSlotNode; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.control.BreakException; +import com.oracle.truffle.r.nodes.control.NextException; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.BrowserQuitException; +import com.oracle.truffle.r.runtime.FunctionUID; import com.oracle.truffle.r.runtime.RAllNames.State; +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.RArguments.S4Args; +import com.oracle.truffle.r.runtime.RDeparse; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RErrorHandling; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RSerialize; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.ReturnException; import com.oracle.truffle.r.runtime.Utils.DebugExitException; -import com.oracle.truffle.r.runtime.context.*; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.env.*; -import com.oracle.truffle.r.runtime.env.frame.*; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RBuiltinDescriptor; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; +import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; import com.oracle.truffle.r.runtime.instrument.FunctionUIDFactory; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNode { @@ -77,12 +103,18 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo private final BranchProfile nextProfile = BranchProfile.create(); @CompilationFinal private BranchProfile invalidateFrameSlotProfile; + // S3/S4 slots @Child private FrameSlotNode dotGenericSlot; @Child private FrameSlotNode dotMethodSlot; + // S3 slots @Child private FrameSlotNode dotClassSlot; @Child private FrameSlotNode dotGenericCallEnvSlot; @Child private FrameSlotNode dotGenericCallDefSlot; @Child private FrameSlotNode dotGroupSlot; + // S4 slots + @Child private FrameSlotNode dotDefinedSlot; + @Child private FrameSlotNode dotTargetSlot; + @Child private FrameSlotNode dotMethodsSlot; @Child private PostProcessArgumentsNode argPostProcess; @@ -139,8 +171,11 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo private static boolean containsAnyDispatch(BodyNode body) { NodeCountFilter dispatchingMethodsFilter = node -> { if (node instanceof ReadVariableNode) { - String identifier = ((ReadVariableNode) node).getIdentifier(); - return "UseMethod".equals(identifier) /* || "NextMethod".equals(identifier) */; + ReadVariableNode rvn = (ReadVariableNode) node; + String identifier = rvn.getIdentifier(); + // TODO: can we also do this for S4 new? + return rvn.getMode() == RType.Function && ("UseMethod".equals(identifier) || "standardGeneric".equals(identifier)); + /* || "NextMethod".equals(identifier) */ } return false; }; @@ -170,28 +205,28 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo * to do this. If a function uses lapply anywhere as name then it gets split. * This could get exploited. */ - RBuiltinDescriptor directBuiltin = RContext.lookupBuiltinDescriptor(readInternal.getIdentifier()); - if (directBuiltin != null && directBuiltin.isSplitCaller()) { - return true; - } + RBuiltinDescriptor directBuiltin = RContext.lookupBuiltinDescriptor(readInternal.getIdentifier()); + if (directBuiltin != null && directBuiltin.isSplitCaller()) { + return true; + } - if (readInternal.getIdentifier().equals(".Internal")) { - Node internalFunctionArgument = RASTUtils.unwrap(internalCall.getArguments().getArguments()[0]); - if (internalFunctionArgument instanceof RCallNode) { - RCallNode innerCall = (RCallNode) internalFunctionArgument; - if (innerCall.getFunctionNode() instanceof ReadVariableNode) { - ReadVariableNode readInnerCall = (ReadVariableNode) innerCall.getFunctionNode(); - RBuiltinDescriptor builtin = RContext.lookupBuiltinDescriptor(readInnerCall.getIdentifier()); - if (builtin != null && builtin.isSplitCaller()) { - return true; + if (readInternal.getIdentifier().equals(".Internal")) { + Node internalFunctionArgument = RASTUtils.unwrap(internalCall.getArguments().getArguments()[0]); + if (internalFunctionArgument instanceof RCallNode) { + RCallNode innerCall = (RCallNode) internalFunctionArgument; + if (innerCall.getFunctionNode() instanceof ReadVariableNode) { + ReadVariableNode readInnerCall = (ReadVariableNode) innerCall.getFunctionNode(); + RBuiltinDescriptor builtin = RContext.lookupBuiltinDescriptor(readInnerCall.getIdentifier()); + if (builtin != null && builtin.isSplitCaller()) { + return true; + } } } } } } - } - return false; - }; + return false; + }; return NodeUtil.countNodes(this, findAlwaysSplitInternal) > 0; } @@ -232,7 +267,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo boolean runOnExitHandlers = true; try { verifyEnclosingAssumptions(vf); - setupS3Slots(vf); + setupDispatchSlots(vf); Object result = body.execute(vf); normalExit.enter(); return result; @@ -302,29 +337,56 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo } } - private void setupS3Slots(VirtualFrame frame) { - S3Args args = RArguments.getS3Args(frame); - if (args == null) { + private void setupDispatchSlots(VirtualFrame frame) { + DispatchArgs dispatchArgs = RArguments.getDispatchArgs(frame); + if (dispatchArgs == null) { return; } if (dotGenericSlot == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - assert invalidateFrameSlotProfile == null && dotMethodSlot == null && dotClassSlot == null && dotGenericCallEnvSlot == null && dotGenericCallDefSlot == null && dotGroupSlot == null; + assert invalidateFrameSlotProfile == null && dotMethodSlot == null; invalidateFrameSlotProfile = BranchProfile.create(); FrameDescriptor frameDescriptor = frame.getFrameDescriptor(); - dotGenericSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.RDotGeneric, true)); - dotMethodSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.RDotMethod, true)); - dotClassSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.RDotClass, true)); - dotGenericCallEnvSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.RDotGenericCallEnv, true)); - dotGenericCallDefSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.RDotGenericDefEnv, true)); - dotGroupSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.RDotGroup, true)); + + dotGenericSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_GENERIC, true)); + dotMethodSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_METHOD, true)); + } + FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericSlot.executeFrameSlot(frame), dispatchArgs.generic, false, invalidateFrameSlotProfile); + FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotMethodSlot.executeFrameSlot(frame), dispatchArgs.method, false, invalidateFrameSlotProfile); + + if (dispatchArgs instanceof S3Args) { + S3Args s3Args = (S3Args) dispatchArgs; + if (dotClassSlot == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + assert dotGenericCallEnvSlot == null && dotGenericCallDefSlot == null && dotGroupSlot == null; + invalidateFrameSlotProfile = BranchProfile.create(); + FrameDescriptor frameDescriptor = frame.getFrameDescriptor(); + + dotClassSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_CLASS, true)); + dotGenericCallEnvSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_GENERIC_CALL_ENV, true)); + dotGenericCallDefSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_GENERIC_DEF_ENV, true)); + dotGroupSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_GROUP, true)); + } + FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotClassSlot.executeFrameSlot(frame), s3Args.clazz, false, invalidateFrameSlotProfile); + FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericCallEnvSlot.executeFrameSlot(frame), s3Args.callEnv, false, invalidateFrameSlotProfile); + FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericCallDefSlot.executeFrameSlot(frame), s3Args.defEnv, false, invalidateFrameSlotProfile); + FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGroupSlot.executeFrameSlot(frame), s3Args.group, false, invalidateFrameSlotProfile); + } else { + S4Args s4Args = (S4Args) dispatchArgs; + if (dotDefinedSlot == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + assert dotTargetSlot == null && dotMethodsSlot == null; + invalidateFrameSlotProfile = BranchProfile.create(); + FrameDescriptor frameDescriptor = frame.getFrameDescriptor(); + + dotDefinedSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_DEFINED, true)); + dotTargetSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_TARGET, true)); + dotMethodsSlot = insert(FrameSlotNode.createInitialized(frameDescriptor, RRuntime.R_DOT_METHODS, true)); + } + FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotDefinedSlot.executeFrameSlot(frame), s4Args.defined, false, invalidateFrameSlotProfile); + FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotTargetSlot.executeFrameSlot(frame), s4Args.target, false, invalidateFrameSlotProfile); + FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotMethodsSlot.executeFrameSlot(frame), s4Args.methods, false, invalidateFrameSlotProfile); } - FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericSlot.executeFrameSlot(frame), args.generic, false, invalidateFrameSlotProfile); - FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotMethodSlot.executeFrameSlot(frame), args.method, false, invalidateFrameSlotProfile); - FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotClassSlot.executeFrameSlot(frame), args.clazz, false, invalidateFrameSlotProfile); - FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericCallEnvSlot.executeFrameSlot(frame), args.callEnv, false, invalidateFrameSlotProfile); - FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGenericCallDefSlot.executeFrameSlot(frame), args.defEnv, false, invalidateFrameSlotProfile); - FrameSlotChangeMonitor.setObjectAndInvalidate(frame, dotGroupSlot.executeFrameSlot(frame), args.group, false, invalidateFrameSlotProfile); } @SuppressWarnings("unchecked") diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/RArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/RArgumentsNode.java index d3f7ae2e09..e79bd6006b 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/RArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/RArgumentsNode.java @@ -37,7 +37,7 @@ public abstract class RArgumentsNode extends RBaseNode { * certain parameters, on which Truffle DSL cannot specialize. */ - public abstract Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs, ArgumentsSignature signature, S3Args s3Args); + public abstract Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs, ArgumentsSignature signature, DispatchArgs dispatchArgs); public static RArgumentsNode create() { return new RArgumentsUninitializedNode(); @@ -50,9 +50,9 @@ public abstract class RArgumentsNode extends RBaseNode { private static final class RArgumentsUninitializedNode extends RArgumentsNode { @Override - public Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs, ArgumentsSignature signature, S3Args s3Args) { + public Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs, ArgumentsSignature signature, DispatchArgs dispatchArgs) { CompilerDirectives.transferToInterpreterAndInvalidate(); - return replace(new RArgumentsCachedNode(function)).execute(function, caller, callerFrame, depth, evaluatedArgs, signature, s3Args); + return replace(new RArgumentsCachedNode(function)).execute(function, caller, callerFrame, depth, evaluatedArgs, signature, dispatchArgs); } } @@ -64,20 +64,20 @@ public abstract class RArgumentsNode extends RBaseNode { } @Override - public Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs, ArgumentsSignature signature, S3Args s3Args) { + public Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs, ArgumentsSignature signature, DispatchArgs dispatchArgs) { if (function == cachedFunction) { - return RArguments.create(cachedFunction, caller, callerFrame, depth, evaluatedArgs, signature, cachedFunction.getEnclosingFrame(), s3Args); + return RArguments.create(cachedFunction, caller, callerFrame, depth, evaluatedArgs, signature, cachedFunction.getEnclosingFrame(), dispatchArgs); } else { CompilerDirectives.transferToInterpreterAndInvalidate(); - return replace(new RArgumentsGenericNode()).execute(function, caller, callerFrame, depth, evaluatedArgs, signature, s3Args); + return replace(new RArgumentsGenericNode()).execute(function, caller, callerFrame, depth, evaluatedArgs, signature, dispatchArgs); } } } private static final class RArgumentsGenericNode extends RArgumentsNode { @Override - public Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs, ArgumentsSignature signature, S3Args s3Args) { - return RArguments.create(function, caller, callerFrame, depth, evaluatedArgs, signature, function.getEnclosingFrame(), s3Args); + public Object[] execute(RFunction function, RCaller caller, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs, ArgumentsSignature signature, DispatchArgs dispatchArgs) { + return RArguments.create(function, caller, callerFrame, depth, evaluatedArgs, signature, function.getEnclosingFrame(), dispatchArgs); } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java index 3320fd394a..68e0873ef7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java @@ -6,7 +6,7 @@ * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka * Copyright (c) 1995-2014, The R Core Team * Copyright (c) 2002-2008, The R Foundation - * Copyright (c) 2015, Oracle and/or its affiliates + * Copyright (c) 2015, 2016, Oracle and/or its affiliates * * All rights reserved. */ @@ -93,7 +93,7 @@ public abstract class DispatchGeneric extends RBaseNode { } } method = loadMethod.executeRFunction(frame, methodsEnv, method, fname); - Object ret = executeMethod.executeMethod(frame, method); + Object ret = executeMethod.executeObject(frame, method); return ret; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java index ebb7430460..6dd3b86e41 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java @@ -13,6 +13,7 @@ package com.oracle.truffle.r.nodes.objects; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameDescriptor; @@ -22,11 +23,16 @@ import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.function.CallMatcherNode; import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.RMissingHelper; +import com.oracle.truffle.r.nodes.function.signature.CollectArgumentsNode; +import com.oracle.truffle.r.nodes.function.signature.CollectArgumentsNodeGen; import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RArguments.S4Args; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; @@ -41,45 +47,30 @@ public abstract class ExecuteMethod extends RBaseNode { public abstract Object executeObject(VirtualFrame frame, RFunction fdef); @Child private LocalReadVariableNode readDefined = LocalReadVariableNode.create(RRuntime.R_DOT_DEFINED, true); - @Child private LocalReadVariableNode readMethod = LocalReadVariableNode.create(RRuntime.RDotMethod, true); + @Child private LocalReadVariableNode readMethod = LocalReadVariableNode.create(RRuntime.R_DOT_METHOD, true); @Child private LocalReadVariableNode readTarget = LocalReadVariableNode.create(RRuntime.R_DOT_TARGET, true); - @Child private LocalReadVariableNode readGeneric = LocalReadVariableNode.create(RRuntime.RDotGeneric, true); - @Child private LocalReadVariableNode readMethods = LocalReadVariableNode.create(RRuntime.R_DOT_METHODS, true); + @Child private ReadVariableNode readGeneric = ReadVariableNode.create(RRuntime.R_DOT_GENERIC); + @Child private ReadVariableNode readMethods = ReadVariableNode.create(RRuntime.R_DOT_METHODS); @Child private RArgumentsNode argsNode = RArgumentsNode.create(); + @Child private CollectArgumentsNode collectArgs; + @Child private CallMatcherNode callMatcher; + @Specialization protected Object executeMethod(VirtualFrame frame, RFunction fdef) { + if (collectArgs == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + collectArgs = insert(CollectArgumentsNodeGen.create()); + callMatcher = insert(CallMatcherNode.create(false, false)); + } - Object[] args = argsNode.execute(RArguments.getFunction(frame), RArguments.getCall(frame), null, RArguments.getDepth(frame) + 1, RArguments.getArguments(frame), - RArguments.getSignature(frame), null); - MaterializedFrame newFrame = Truffle.getRuntime().createMaterializedFrame(args); - FrameDescriptor desc = newFrame.getFrameDescriptor(); - FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<executeMethod>", desc); - FrameSlotChangeMonitor.initializeEnclosingFrame(newFrame, RArguments.getFunction(frame).getEnclosingFrame()); FormalArguments formals = ((RRootNode) fdef.getRootNode()).getFormalArguments(); - if (formals != null) { - ArgumentsSignature signature = formals.getSignature(); - MaterializedFrame currentFrame = frame.materialize(); - FrameDescriptor currentFrameDesc = currentFrame.getFrameDescriptor(); - for (int i = 0; i < signature.getLength(); i++) { - String argName = signature.getName(i); - boolean missing = RMissingHelper.isMissingArgument(frame, argName); - Object val = slotRead(currentFrame, currentFrameDesc, argName); - slotInit(newFrame, desc, argName, val); - if (missing && !(val instanceof RArgsValuesAndNames || val == RMissing.instance)) { - throw RInternalError.unimplemented(); - } - } - } + ArgumentsSignature signature = formals.getSignature(); + Object[] oldArgs = collectArgs.execute(frame, signature); - slotInit(newFrame, desc, RRuntime.R_DOT_DEFINED, readDefined.execute(frame)); - slotInit(newFrame, desc, RRuntime.RDotMethod, readMethod.execute(frame)); - slotInit(newFrame, desc, RRuntime.R_DOT_TARGET, readTarget.execute(frame)); - slotInit(newFrame, desc, RRuntime.RDotGeneric, readGeneric.execute(frame)); - slotInit(newFrame, desc, RRuntime.R_DOT_METHODS, readMethods.execute(frame)); + S4Args s4Args = new S4Args(readDefined.execute(frame), readMethod.execute(frame), readTarget.execute(frame), readGeneric.execute(frame), readMethods.execute(frame)); - Object ret = callMethod(fdef, newFrame); - return ret; + return callMatcher.execute(frame, signature, oldArgs, fdef, s4Args); } @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java index 6bc7bc3189..803961b517 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java @@ -6,7 +6,7 @@ * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka * Copyright (c) 1995-2014, The R Core Team * Copyright (c) 2002-2008, The R Foundation - * Copyright (c) 2015, Oracle and/or its affiliates + * Copyright (c) 2015, 2016, Oracle and/or its affiliates * * All rights reserved. */ @@ -26,6 +26,7 @@ import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributable; @@ -42,7 +43,7 @@ public abstract class LoadMethod extends RBaseNode { @Child private WriteLocalFrameVariableNode writeRTarget = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_TARGET, null, WriteVariableNode.Mode.REGULAR); @Child private WriteLocalFrameVariableNode writeRDefined = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_DEFINED, null, WriteVariableNode.Mode.REGULAR); @Child private WriteLocalFrameVariableNode writeRNextMethod = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_NEXT_METHOD, null, WriteVariableNode.Mode.REGULAR); - @Child private WriteLocalFrameVariableNode writeRMethod = WriteLocalFrameVariableNode.create(RRuntime.RDotMethod, null, WriteVariableNode.Mode.REGULAR); + @Child private WriteLocalFrameVariableNode writeRMethod = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_METHOD, null, WriteVariableNode.Mode.REGULAR); @Child private ReadVariableNode loadMethodFind; @Child private DirectCallNode loadMethodCall; @CompilationFinal private RFunction loadMethodFunction; @@ -86,7 +87,7 @@ public abstract class LoadMethod extends RBaseNode { loadMethodFind = insert(ReadVariableNode.createFunctionLookup(null, "loadMethod")); loadMethodFunction = (RFunction) loadMethodFind.execute(null, methodsEnv.getFrame()); loadMethodCall = insert(Truffle.getRuntime().createDirectCallNode(loadMethodFunction.getTarget())); - + RError.performanceWarning("loadMethod executing slow path"); } RFunction currentFunction = (RFunction) loadMethodFind.execute(null, methodsEnv.getFrame()); if (cached.profile(currentFunction == loadMethodFunction)) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java index 0e215243f0..6ef072b227 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -84,32 +84,54 @@ public final class RArguments { @CompilationFinal public static final String[] EMPTY_STRING_ARRAY = new String[0]; @ValueType - public static final class S3Args { - public final String generic; - public final Object clazz; + public abstract static class DispatchArgs { + public final Object generic; public final Object method; + + public DispatchArgs(Object generic, Object method) { + this.generic = generic; + this.method = method; + } + } + + @ValueType + public static final class S3Args extends DispatchArgs { + public final Object clazz; public final MaterializedFrame callEnv; public final MaterializedFrame defEnv; public final String group; public S3Args(String generic, Object clazz, Object method, MaterializedFrame callEnv, MaterializedFrame defEnv, String group) { + super(generic, method); assert generic != null && callEnv != null : generic + " " + callEnv; assert generic.intern() == generic; - this.generic = generic; this.clazz = clazz; - this.method = method; this.callEnv = callEnv; this.defEnv = defEnv; this.group = group; } } + @ValueType + public static final class S4Args extends DispatchArgs { + public final Object defined; + public final Object target; + public final Object methods; + + public S4Args(Object defined, Object method, Object target, Object generic, Object methods) { + super(generic, method); + this.defined = defined; + this.target = target; + this.methods = methods; + } + } + static final int INDEX_ENVIRONMENT = 0; static final int INDEX_FUNCTION = 1; static final int INDEX_CALL = 2; static final int INDEX_CALLER_FRAME = 3; static final int INDEX_ENCLOSING_FRAME = 4; - static final int INDEX_S3_ARGS = 5; + static final int INDEX_DISPATCH_ARGS = 5; static final int INDEX_DEPTH = 6; static final int INDEX_IS_IRREGULAR = 7; static final int INDEX_SIGNATURE = 8; @@ -132,13 +154,13 @@ public final class RArguments { return ((HasSignature) function.getRootNode()).getSignature(); } - public static Object[] create(RFunction functionObj, RCaller call, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs, ArgumentsSignature signature, S3Args s3Args) { + public static Object[] create(RFunction functionObj, RCaller call, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs, ArgumentsSignature signature, DispatchArgs dispatchArgs) { CompilerAsserts.neverPartOfCompilation(); - return create(functionObj, call, callerFrame, depth, evaluatedArgs, signature, functionObj.getEnclosingFrame(), s3Args); + return create(functionObj, call, callerFrame, depth, evaluatedArgs, signature, functionObj.getEnclosingFrame(), dispatchArgs); } public static Object[] create(RFunction functionObj, RCaller call, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs, ArgumentsSignature signature, - MaterializedFrame enclosingFrame, S3Args s3Args) { + MaterializedFrame enclosingFrame, DispatchArgs dispatchArgs) { assert evaluatedArgs != null && signature != null : evaluatedArgs + " " + signature; assert evaluatedArgs.length == signature.getLength() : Arrays.toString(evaluatedArgs) + " " + signature; assert signature == getSignature(functionObj) : signature + " vs. " + getSignature(functionObj); @@ -151,7 +173,7 @@ public final class RArguments { a[INDEX_CALL] = call; a[INDEX_CALLER_FRAME] = callerFrame; a[INDEX_ENCLOSING_FRAME] = enclosingFrame; - a[INDEX_S3_ARGS] = s3Args; + a[INDEX_DISPATCH_ARGS] = dispatchArgs; a[INDEX_DEPTH] = depth; a[INDEX_IS_IRREGULAR] = false; a[INDEX_SIGNATURE] = signature; @@ -183,8 +205,8 @@ public final class RArguments { return (MaterializedFrame) args[INDEX_CALLER_FRAME]; } - public static S3Args getS3Args(Frame frame) { - return (S3Args) frame.getArguments()[INDEX_S3_ARGS]; + public static DispatchArgs getDispatchArgs(Frame frame) { + return (DispatchArgs) frame.getArguments()[INDEX_DISPATCH_ARGS]; } public static REnvironment getEnvironment(Frame frame) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java index ca7ae5588d..f7f6f51aa4 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java @@ -117,17 +117,17 @@ public class RRuntime { public static final String RS3MethodsTable = ".__S3MethodsTable__."; - public static final String RDotGeneric = ".Generic"; + public static final String R_DOT_GENERIC = ".Generic"; - public static final String RDotMethod = ".Method"; + public static final String R_DOT_METHOD = ".Method"; - public static final String RDotClass = ".Class"; + public static final String R_DOT_CLASS = ".Class"; - public static final String RDotGenericCallEnv = ".GenericCallEnv"; + public static final String R_DOT_GENERIC_CALL_ENV = ".GenericCallEnv"; - public static final String RDotGenericDefEnv = ".GenericDefEnv"; + public static final String R_DOT_GENERIC_DEF_ENV = ".GenericDefEnv"; - public static final String RDotGroup = ".Group"; + public static final String R_DOT_GROUP = ".Group"; public static final String RDOT = "."; 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 f8a032a818..4a68fb8594 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 @@ -1,3 +1,113 @@ +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation1.R") } +An object of class "Person" +Slot "name": +[1] "Hadley" + +Slot "age": +[1] 31 + + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation10.R") } +Error in validObject(hadley) : + invalid class “Person” object: Age is length 10. Should be 1 + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation2.R") } +Error in validObject(.Object) : + invalid class “Person” object: invalid object for slot "age" in class "Person": got class "character", should be or extend class "numeric" + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation3.R") } +Error in initialize(value, ...) : + invalid name for slot of class “Person”: sex + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation4.R") } +numeric(0) + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation5.R") } +numeric(0) + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation6.R") } +[1] NA + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation7.R") } +Error in validObject(.Object) : + invalid class “Person” object: Age is length 0. Should be 1 + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation8.R") } +Error in validObject(.Object) : + invalid class “Person” object: Age is length 10. Should be 1 + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation9.R") } +An object of class "Person" +Slot "name": +[1] "Hadley" + +Slot "age": +[1] 31 + + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods1.R") } +Function: sides (package .GlobalEnv) +object="Polygon" +object="Square" +object="Triangle" + +description class mode text opened can read + "stdout" "terminal" "w" "text" "opened" "no" + can write + "yes" +description class mode text opened can read + "stdout" "terminal" "w" "text" "opened" "no" + can write + "yes" + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods2.R") } +Function: sides (package .GlobalEnv) +object="Polygon" + +description class mode text opened can read + "stdout" "terminal" "w" "text" "opened" "no" + can write + "yes" +description class mode text opened can read + "stdout" "terminal" "w" "text" "opened" "no" + can write + "yes" + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods3.R") } +Error in .valueClassTest({ : + invalid value from generic function ‘sides’, class “character”, expected “numeric” + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods4.R") } +Note: method with signature ‘A2#A1’ chosen for function ‘foo’, + target signature ‘A2#A2’. + "A1#A2" would also be valid +[1] "2-1" +[1] "2-1" + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods5.R") } +[1] "Looking for rust" +[1] "Checking seat belts" + +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests +#{ source("com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/slot_access1.R") } + name age +"character" "numeric" + ##com.oracle.truffle.r.test.S4.TestS4.testAllocation #{ new("numeric") } numeric(0) @@ -43,6 +153,97 @@ Error: unexpected '}' in "{ asS4(NULL); isS4(NULL }" #{ x<-42; y<-asS4(x); isS4(y) } [1] TRUE +##com.oracle.truffle.r.test.S4.TestS4.testMethods +#{ gen<-function(object) 0; setGeneric("gen"); res<-print(gen); removeGeneric("gen"); res } +function (object) +standardGeneric("gen") +<environment: 0x7fa971ee8c78> +attr(,"generic") +[1] "gen" +attr(,"generic")attr(,"package") +[1] ".GlobalEnv" +attr(,"package") +[1] ".GlobalEnv" +attr(,"group") +list() +attr(,"valueClass") +character(0) +attr(,"signature") +[1] "object" +attr(,"default") +Method Definition (Class "derivedDefaultMethod"): + +function (object) +0 + +Signatures: + object +target "ANY" +defined "ANY" +attr(,"skeleton") +(function (object) +0)(object) +attr(,"class") +[1] "standardGeneric" +attr(,"class")attr(,"package") +[1] "methods" +standardGeneric for "gen" defined from package ".GlobalEnv" + +function (object) +standardGeneric("gen") +<environment: 0x7fa971ee8c78> +Methods may be defined for arguments: object +Use showMethods("gen") for currently available ones. + +##com.oracle.truffle.r.test.S4.TestS4.testMethods +#{ gen<-function(object) 0; setGeneric("gen"); setClass("foo", representation(d="numeric")); setMethod("gen", signature(object="foo"), function(object) object@d); res<-print(gen(new("foo", d=42))); removeGeneric("gen"); res } +[1] 42 +[1] 42 + +##com.oracle.truffle.r.test.S4.TestS4.testMethods +#{ setClass("foo", representation(d="numeric")); setClass("bar", contains="foo"); setGeneric("gen", function(o) standardGeneric("gen")); setMethod("gen", signature(o="foo"), function(o) "FOO"); setMethod("gen", signature(o="bar"), function(o) "BAR"); res<-print(c(gen(new("foo", d=7)), gen(new("bar", d=42)))); removeGeneric("gen"); res } +[1] "FOO" "BAR" +[1] "FOO" "BAR" + +##com.oracle.truffle.r.test.S4.TestS4.testMethods +#{ setGeneric("gen", function(o) standardGeneric("gen")); res<-print(setGeneric("gen", function(o) standardGeneric("gen"))); removeGeneric("gen"); res } +[1] "gen" +[1] "gen" + +##com.oracle.truffle.r.test.S4.TestS4.testMethods +#{ setGeneric("gen", function(object) standardGeneric("gen")); res<-print(gen); removeGeneric("gen"); res } +function(object) standardGeneric("gen") +<environment: 0x7feb710c8bc8> +attr(,"generic") +[1] "gen" +attr(,"generic")attr(,"package") +[1] ".GlobalEnv" +attr(,"package") +[1] ".GlobalEnv" +attr(,"group") +list() +attr(,"valueClass") +character(0) +attr(,"signature") +[1] "object" +attr(,"default") +`\001NULL\001` +attr(,"skeleton") +(function (object) +stop("invalid call in method dispatch to 'gen' (no default method)", + domain = NA))(object) +attr(,"class") +[1] "standardGeneric" +attr(,"class")attr(,"package") +[1] "methods" +standardGeneric for "gen" defined from package ".GlobalEnv" + +function (object) +standardGeneric("gen") +<environment: 0x7feb710c8bc8> +Methods may be defined for arguments: object +Use showMethods("gen") for currently available ones. + ##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess #{ `@`(getClass("ClassUnionRepresentation"), "virtual") } [1] FALSE diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java index 1e275e9daf..3d4512bf1c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java @@ -90,7 +90,6 @@ public class TestS4 extends TestRBase { } @Test - @Ignore public void testMethods() { // output slightly different from GNU R even though we use R's "show" method to print it assertEval(Ignored.OutputFormatting, "{ setGeneric(\"gen\", function(object) standardGeneric(\"gen\")); res<-print(gen); removeGeneric(\"gen\"); res }"); @@ -106,7 +105,7 @@ public class TestS4 extends TestRBase { @Override public String getTestDir() { - return null;// "S4"; + return "S4"; } } -- GitLab