From 65eeba37c659ce8d74d15a639b60e9782dc8087d Mon Sep 17 00:00:00 2001 From: Florian Angerer <florian.angerer@oracle.com> Date: Wed, 15 Nov 2017 13:55:53 +0100 Subject: [PATCH] Using operator '@' to send INVOKE to foreign objects. --- .../truffle/r/nodes/builtin/base/Slot.java | 31 +++++++++++++++++-- .../truffle/r/nodes/builtin/CastBuilder.java | 5 +++ .../truffle/r/nodes/builtin/RBuiltinNode.java | 4 +++ .../truffle/r/nodes/function/RCallNode.java | 14 ++++++++- 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java index b1ee00c719..2ef8f6aa55 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java @@ -13,18 +13,23 @@ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.foreign; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.access.AccessSlotNode; import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.nodes.function.opt.UpdateShareableChildValueNode; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.Closure; @@ -33,12 +38,13 @@ import com.oracle.truffle.r.runtime.data.RPromise; @RBuiltin(name = "@", kind = PRIMITIVE, parameterNames = {"", ""}, nonEvalArgs = 1, behavior = COMPLEX) public abstract class Slot extends RBuiltinNode.Arg2 { + @CompilationFinal private boolean isLhsOfCall; @Child private UpdateShareableChildValueNode sharedAttrUpdate = UpdateShareableChildValueNode.create(); @Child private AccessSlotNode accessSlotNode = AccessSlotNodeGen.create(true); static { Casts casts = new Casts(Slot.class); - casts.arg(0).asAttributable(true, true, true); + casts.arg(0).returnIf(foreign()).asAttributable(true, true, true); } private String getName(Object nameObj) { @@ -55,7 +61,22 @@ public abstract class Slot extends RBuiltinNode.Arg2 { throw error(RError.Message.GENERIC, "invalid type or length for slot name"); } - @Specialization + protected boolean isLhsOfForeignCall(Object o) { + return isLhsOfCall && RRuntime.isForeignObject(o); + } + + @Specialization(guards = {"isLhsOfForeignCall(object)"}) + protected Object getSlot(TruffleObject object, Object nameObj, + @Cached("createClassProfile()") ValueProfile nameObjProfile) { + + String name = getName(nameObjProfile.profile(nameObj)); + assert Utils.isInterned(name); + + // just return evaluated receiver object and name + return RCallNode.createDeferredMemberAccess(object, name); + } + + @Specialization(guards = "!isLhsOfForeignCall(object)") protected Object getSlot(Object object, Object nameObj, @Cached("createClassProfile()") ValueProfile nameObjProfile) { String name = getName(nameObjProfile.profile(nameObj)); @@ -66,4 +87,10 @@ public abstract class Slot extends RBuiltinNode.Arg2 { sharedAttrUpdate.execute(object, result); return result; } + + @Override + public void setLhsOfCall(boolean value) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + this.isLhsOfCall = value; + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java index adef023a62..fd5623610a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.function.Function; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.r.nodes.builtin.casts.Filter; import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter; import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter; @@ -662,6 +663,10 @@ public final class CastBuilder { return new TypeFilter<>(RFunction.class, x -> x.isBuiltin()); } + public static TypeFilter<Object, TruffleObject> foreign() { + return new TypeFilter<>(TruffleObject.class, x -> RRuntime.isForeignObject(x)); + } + public static <R extends RAbstractIntVector> Filter<Object, R> integerValue() { return new RTypeFilter<>(RType.Integer); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java index 11315ae997..26cb852738 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java @@ -148,6 +148,10 @@ public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithA } } + public void setLhsOfCall(@SuppressWarnings("unused") boolean value) { + // default: do nothing + } + public abstract static class Arg0 extends RBuiltinNode { public abstract Object execute(VirtualFrame frame); 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 98e02a92ca..72ad55339c 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 @@ -692,7 +692,12 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS * {@code src == RSyntaxNode.EAGER_DEPARSE} we force a deparse. */ public static RCallNode createCall(SourceSection src, RNode function, ArgumentsSignature signature, RSyntaxNode... arguments) { - return RCallNodeGen.create(src, arguments, signature, function); + return RCallNodeGen.create(src, arguments, signature, tagFunctionNode(function)); + } + + private static RNode tagFunctionNode(RNode function) { + // TODO Auto-generated method stub + return function; } /** @@ -895,6 +900,9 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS varArgSeen = new boolean[formals.getLength()]; nonWrapSeen = new boolean[formals.getLength()]; wrapSeen = new boolean[formals.getLength()]; + + // Tell this builtin that it is LHS of a call which might imply different behavior. + builtin.setLhsOfCall(true); } @Override @@ -1189,4 +1197,8 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } } + + public static Object createDeferredMemberAccess(TruffleObject object, String name) { + return new DeferredFunctionValue(object, name); + } } -- GitLab