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 6726f5afe90dc344d0428b525794623e08c9ce2f..019d0c5541331f5cb48de4bfd9dfcefc63bb3e5a 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,6 +13,7 @@ package com.oracle.truffle.r.nodes.builtin.base; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; @@ -70,9 +71,12 @@ public abstract class Slot extends RBuiltinNode { // in general, treatment of the name parameter has to be finessed to be // fully compatible with GNU R on direct calls to `@` function if (classHierarchy == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); classHierarchy = insert(ClassHierarchyNodeGen.create(true)); } return classHierarchy.execute(object); + } else if (name == RRuntime.DOT_DATA) { + return getDataPart(object); } else if (name == RRuntime.NAMES_ATTR_KEY && object instanceof RAbstractVector) { assert false; // RS4Object can never be a vector? return RNull.instance; @@ -81,6 +85,7 @@ public abstract class Slot extends RBuiltinNode { RStringVector classAttr = object.getClassAttr(attrProfiles); if (classAttr == null) { if (typeofNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); typeofNode = insert(TypeofNodeGen.create()); } throw RError.error(this, RError.Message.SLOT_CANNOT_GET, name, typeofNode.execute(object).getName()); @@ -109,7 +114,7 @@ public abstract class Slot extends RBuiltinNode { return getSlotS4Internal(object, name, value); } - protected RFunction getDataPart(REnvironment methodsNamespace) { + protected RFunction getDataPartFunction(REnvironment methodsNamespace) { Object f = methodsNamespace.findFunction("getDataPart"); return (RFunction) RContext.getRRuntimeASTAccess().forcePromise(f); } @@ -118,18 +123,22 @@ public abstract class Slot extends RBuiltinNode { return REnvironment.getRegisteredNamespace("methods"); } - @SuppressWarnings("unused") - @Specialization(guards = {"!isS4(object)", "isDotData(getName(nameObj))"}) - protected Object getSlotNonS4(RAbstractContainer object, Object nameObj) { - // TODO: any way to cache it? + private Object getDataPart(Object object) { + // TODO: any way to cache it or use a mechanism similar to overrides? REnvironment methodsNamespace = REnvironment.getRegisteredNamespace("methods"); - RFunction dataPart = getDataPart(methodsNamespace); + RFunction dataPart = getDataPartFunction(methodsNamespace); return RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), object); } + @SuppressWarnings("unused") + @Specialization(guards = "isDotData(getName(nameObj))") + protected Object getSlotNonS4(RAbstractContainer object, Object nameObj) { + return getDataPart(object); + } + // this is really a fallback specialization but @Fallback does not work here (because of the // type of "object"?) - @Specialization + @Specialization(guards = "!isDotData(getName(nameObj))") protected Object getSlot(RAbstractContainer object, Object nameObj) { // first argument is wrong String name = getName(nameObj);