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 6c6f4809338e16b3f13c8af5884de5833585f33f..8267a9660a77bfc94ed7c908335b6b45f8746704 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 @@ -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. */ @@ -32,6 +32,7 @@ import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -64,7 +65,10 @@ public abstract class AccessSlotNode extends RNode { } return classHierarchy.execute(object); } else if (name == RRuntime.DOT_DATA) { - return getDataPart(object); + // TODO: any way to cache it or use a mechanism similar to overrides? + REnvironment methodsNamespace = REnvironment.getRegisteredNamespace("methods"); + RFunction dataPart = getDataPartFunction(methodsNamespace); + return RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), 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,9 @@ public abstract class AccessSlotNode extends RNode { throw RError.error(this, RError.Message.SLOT_NONE, name, classAttr.getLength() == 0 ? RRuntime.STRING_NA : classAttr.getDataAt(0)); } } + if (value instanceof RSymbol && ((RSymbol) value).getName() == RRuntime.PSEUDO_NULL.getName()) { + return RNull.instance; + } return value; } @@ -108,19 +115,15 @@ public abstract class AccessSlotNode extends RNode { return (RFunction) RContext.getRRuntimeASTAccess().forcePromise(f); } - private Object getDataPart(RAttributable object) { + @SuppressWarnings("unused") + @Specialization(guards = {"!object.isS4()", "isDotData(name)"}) + protected Object getSlotNonS4(RAttributable object, String name) { // TODO: any way to cache it or use a mechanism similar to overrides? REnvironment methodsNamespace = REnvironment.getRegisteredNamespace("methods"); RFunction dataPart = getDataPartFunction(methodsNamespace); return RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), object); } - @SuppressWarnings("unused") - @Specialization(guards = {"!object.isS4()", "isDotData(name)"}) - protected Object getSlotNonS4(RAttributable object, String name) { - return getDataPart(object); - } - // this is really a fallback specialization but @Fallback does not work here (because of the // type of "object"?) @Specialization(guards = {"!object.isS4()", "!isDotData(name)"}) diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java index 938971c931d5d81dea6f63876f148ff9d15f02ba..f886c666886f5940f42a333f44e7342d790799bb 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java @@ -6,70 +6,66 @@ * 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. */ package com.oracle.truffle.r.nodes.access; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.NodeChild; +import com.oracle.truffle.api.dsl.NodeChildren; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.attributes.PutAttributeNode; import com.oracle.truffle.r.nodes.attributes.PutAttributeNodeGen; -import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.env.REnvironment; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.r.runtime.nodes.RNode; @NodeChildren({@NodeChild(value = "object", type = RNode.class), @NodeChild(value = "name", type = RNode.class), @NodeChild(value = "value", type = RNode.class)}) public abstract class UpdateSlotNode extends RNode { public abstract Object executeUpdate(Object object, String name, Object value); - @CompilationFinal RFunction checkSlotAssign; - @Child private ClassHierarchyNode objClassHierarchy; - @Child private ClassHierarchyNode valClassHierarchy; - protected PutAttributeNode createAttrUpdate(String name) { return PutAttributeNodeGen.create(name); } + private static Object prepareValue(Object value) { + return value == RNull.instance ? RRuntime.PSEUDO_NULL : value; + } + @SuppressWarnings("unused") @Specialization(guards = {"!isData(name)", "name == cachedName"}) - protected Object updateSlotS4Cached(RAttributable object, String name, Object value, @Cached("name") String cachedName, @Cached("createAttrUpdate(cachedName)") PutAttributeNode attributeUpdate) { - attributeUpdate.execute(object.initAttributes(), value); + protected Object updateSlotS4Cached(RAttributable object, String name, Object value, // + @Cached("name") String cachedName, // + @Cached("createAttrUpdate(cachedName)") PutAttributeNode attributeUpdate) { + attributeUpdate.execute(object.initAttributes(), prepareValue(value)); return object; } @Specialization(contains = "updateSlotS4Cached", guards = "!isData(name)") protected Object updateSlotS4(RAttributable object, String name, Object value) { assert name == name.intern(); - object.setAttr(name, value); + object.setAttr(name, prepareValue(value)); return object; } - protected RFunction setDataPartFunction(REnvironment methodsNamespace) { - Object f = methodsNamespace.findFunction("setDataPart"); - return (RFunction) RContext.getRRuntimeASTAccess().forcePromise(f); - } - - private Object setDataPart(RAttributable object, Object value) { - // TODO: any way to cache it or use a mechanism similar to overrides? - REnvironment methodsNamespace = REnvironment.getRegisteredNamespace("methods"); - RFunction dataPart = setDataPartFunction(methodsNamespace); - return RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), object, value, RRuntime.LOGICAL_TRUE); - } - @Specialization(guards = "isData(name)") protected Object updateSlotS4Data(RAttributable object, @SuppressWarnings("unused") String name, Object value) { - return setDataPart(object, value); + // TODO: any way to cache it or use a mechanism similar to overrides? + REnvironment methodsNamespace = REnvironment.getRegisteredNamespace("methods"); + Object f = methodsNamespace.findFunction("setDataPart"); + RFunction dataPart = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(f); + return RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), object, prepareValue(value), RRuntime.LOGICAL_TRUE); } protected boolean isData(String name) { assert name == name.intern(); return name == RRuntime.DOT_DATA; } - } 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 4640f6702d04fffd1414d10bc35df82435d34f0c..4da8e0ecda0f2945c291215719a0a231ddf2eb13 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 @@ -35,7 +35,6 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributes; -import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.env.REnvironment; 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 949e23ab57aab51317900c4adffdf7c4fa255859..744aeec69f2c6e89a4f9ff86355353014ca253c6 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 @@ -156,6 +156,7 @@ public class RRuntime { public static final String R_SOURCE = "source"; public static final String NULL = "NULL"; + public static final RSymbol PSEUDO_NULL = new RSymbol("\u0001NULL\u0001"); public static final String UNBOUND = "UNBOUND"; @CompilationFinal private static final String[] numberStringCache = new String[4096];