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 2ef8f6aa55e0873c046b2af1b52257695489ec9b..e58454418aaec752705161e80ef211b976375550 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 @@ -17,16 +17,19 @@ 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.CompilerAsserts; 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.nodes.Node; import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.nodes.RASTUtils; 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.RCallNode.BuiltinCallNode; import com.oracle.truffle.r.nodes.function.opt.UpdateShareableChildValueNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -34,11 +37,13 @@ import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.Closure; import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @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); @@ -61,14 +66,29 @@ public abstract class Slot extends RBuiltinNode.Arg2 { throw error(RError.Message.GENERIC, "invalid type or length for slot name"); } - protected boolean isLhsOfForeignCall(Object o) { - return isLhsOfCall && RRuntime.isForeignObject(o); + private static boolean isLhsOfSyntaxCall(RSyntaxNode n) { + Node unwrapParent = RASTUtils.unwrapParent(n.asNode()); + return unwrapParent instanceof RSyntaxCall && ((RSyntaxCall) unwrapParent).getSyntaxLHS() == n; } - @Specialization(guards = {"isLhsOfForeignCall(object)"}) + protected boolean isForeignObject(Object obj) { + return RRuntime.isForeignObject(obj); + } + + protected boolean isLhsOfCall() { + CompilerAsserts.neverPartOfCompilation(); + Node unwrapParent = RASTUtils.unwrapParent(this); + assert ((BuiltinCallNode) unwrapParent).getBuiltin() == this; + return unwrapParent instanceof BuiltinCallNode && isLhsOfSyntaxCall(((RBaseNode) unwrapParent).asRSyntaxNode()); + } + + @Specialization(guards = {"isForeignObject(object)", "lhsOfCall"}) protected Object getSlot(TruffleObject object, Object nameObj, + @Cached("isLhsOfCall()") boolean lhsOfCall, @Cached("createClassProfile()") ValueProfile nameObjProfile) { + assert lhsOfCall; + String name = getName(nameObjProfile.profile(nameObj)); assert Utils.isInterned(name); @@ -76,7 +96,7 @@ public abstract class Slot extends RBuiltinNode.Arg2 { return RCallNode.createDeferredMemberAccess(object, name); } - @Specialization(guards = "!isLhsOfForeignCall(object)") + @Specialization protected Object getSlot(Object object, Object nameObj, @Cached("createClassProfile()") ValueProfile nameObjProfile) { String name = getName(nameObjProfile.profile(nameObj)); @@ -88,9 +108,4 @@ public abstract class Slot extends RBuiltinNode.Arg2 { 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/access/AccessSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java index 182e05aa0f9cb3c097906931ead5ea775bb93bfc..c8d8a6c3f14dd2757d50fe7c23c020ae2a20632b 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java @@ -13,6 +13,7 @@ package com.oracle.truffle.r.nodes.access; import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.attributes.GetAttributeNode; @@ -21,6 +22,7 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClass import com.oracle.truffle.r.nodes.function.ImplicitClassHierarchyNode; 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.Utils; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributable; @@ -80,4 +82,10 @@ public abstract class AccessSlotNode extends BaseAccessSlotNode { throw error(RError.Message.SLOT_NON_S4, name, classAttr.getDataAt(0)); } } + + @Fallback + protected Object getSlot(Object object, String name) { + throw error(RError.Message.SLOT_CANNOT_GET, name, RRuntime.getRTypeName(object)); + } + } 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 26cb8527385876b373cbcc1997021386e442a154..11315ae9979fbad45ae0f72a77a21b590fadbe42 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,10 +148,6 @@ 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 d8746d02f3e4c8196ff0b910dbc920a0a86ce819..c4fe686b5f0d843d63e92b042f71186906940c42 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 @@ -886,9 +886,6 @@ 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