From c11f714a3eac0563bf6760dc9598d4b4781798a4 Mon Sep 17 00:00:00 2001 From: Adam Welc <adam.welc@oracle.com> Date: Wed, 4 Nov 2015 14:15:29 -0800 Subject: [PATCH] Interning of ReadVariableNode ids and RSymbol names to make sure that string comparisons work correctly. --- .../fficall/jni/src/rffiutils.c | 2 +- .../truffle/r/nodes/builtin/base/AsVector.java | 4 +++- .../r/nodes/builtin/base/FrameFunctions.java | 11 ++++++++--- .../truffle/r/nodes/builtin/base/Slot.java | 4 +++- .../builtin/base/foreign/ForeignFunctions.java | 2 +- .../com/oracle/truffle/r/nodes/RASTUtils.java | 15 ++++++++++----- .../truffle/r/nodes/access/AccessSlotNode.java | 8 ++------ .../truffle/r/nodes/access/UpdateSlotNode.java | 7 ++++--- .../access/WriteVariableNodeSyntaxHelper.java | 5 ++++- .../access/variables/ReadVariableNode.java | 6 ++++-- .../truffle/r/nodes/unary/CastSymbolNode.java | 7 +++++-- .../oracle/truffle/r/parser/ast/Constant.java | 18 +++++++++++++++++- .../truffle/r/parser/ast/FieldAccess.java | 5 +---- .../oracle/truffle/r/runtime/RSerialize.java | 6 ++++-- .../truffle/r/runtime/data/RDataFactory.java | 8 ++++++++ .../com/oracle/truffle/r/runtime/ffi/DLL.java | 4 +++- .../com/oracle/truffle/r/test/S4/TestS4.java | 2 ++ 17 files changed, 80 insertions(+), 34 deletions(-) diff --git a/com.oracle.truffle.r.native/fficall/jni/src/rffiutils.c b/com.oracle.truffle.r.native/fficall/jni/src/rffiutils.c index 346ba55cf2..a3e08bb2f2 100644 --- a/com.oracle.truffle.r.native/fficall/jni/src/rffiutils.c +++ b/com.oracle.truffle.r.native/fficall/jni/src/rffiutils.c @@ -73,7 +73,7 @@ void init_utils(JNIEnv *env) { RRuntimeClass = checkFindClass(env, "com/oracle/truffle/r/runtime/RRuntime"); RInternalErrorClass = checkFindClass(env, "com/oracle/truffle/r/runtime/RInternalError"); unimplementedMethodID = checkGetMethodID(env, RInternalErrorClass, "unimplemented", "(Ljava/lang/String;)Ljava/lang/RuntimeException;", 1); - createSymbolMethodID = checkGetMethodID(env, RDataFactoryClass, "createSymbol", "(Ljava/lang/String;)Lcom/oracle/truffle/r/runtime/data/RSymbol;", 1); + createSymbolMethodID = checkGetMethodID(env, RDataFactoryClass, "createSymbolInterned", "(Ljava/lang/String;)Lcom/oracle/truffle/r/runtime/data/RSymbol;", 1); validateMethodID = checkGetMethodID(env, CallRFFIHelperClass, "validate", "(Ljava/lang/Object;)Ljava/lang/Object;", 1); for (int i = 0; i < CACHED_GLOBALREFS_TABLE_SIZE; i++) { cachedGlobalRefs[i] = NULL; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java index fc335525ef..1b79ed7583 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java @@ -123,7 +123,9 @@ public abstract class AsVector extends RBuiltinNode { @Specialization(guards = "isSymbol(x, mode)") protected RSymbol asVectorSymbol(RSymbol x, @SuppressWarnings("unused") String mode) { controlVisibility(); - return RDataFactory.createSymbol(x.getName()); + String sName = x.getName(); + assert sName == sName.intern(); + return RDataFactory.createSymbol(sName); } protected boolean isSymbol(@SuppressWarnings("unused") RSymbol x, String mode) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java index ed3f626254..a563a19e6f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java @@ -26,6 +26,7 @@ import static com.oracle.truffle.r.runtime.RBuiltinKind.*; import java.util.*; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; @@ -243,7 +244,9 @@ public class FrameFunctions { if (n instanceof ConstantNode) { listValue = ((ConstantNode) n).getValue(); } else if (n instanceof ReadVariableNode) { - listValue = RDataFactory.createSymbol(((ReadVariableNode) n).getIdentifier()); + String id = ((ReadVariableNode) n).getIdentifier(); + assert id == id.intern(); + listValue = RDataFactory.createSymbol(id); } else if (n instanceof VarArgNode) { listValue = createVarArgSymbol((VarArgNode) n); } else { @@ -251,7 +254,7 @@ public class FrameFunctions { } pl.setCar(listValue); if (varArgSignature.getName(i2) != null) { - pl.setTag(RDataFactory.createSymbol(varArgSignature.getName(i2))); + pl.setTag(RDataFactory.createSymbol(varArgSignature.getName(i2).intern())); } if (prev != null) { prev.setCdr(pl); @@ -308,7 +311,9 @@ public class FrameFunctions { private static RSymbol createVarArgSymbol(VarArgNode varArgNode) { int vn = varArgNode.getIndex() + 1; - return RDataFactory.createSymbol((vn < 10 ? ".." : ".") + vn); + CompilerAsserts.neverPartOfCompilation(); // for string concatenation and interning + String varArgSymbol = (vn < 10 ? ".." : ".") + vn; + return RDataFactory.createSymbol(varArgSymbol.intern()); } @Specialization 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 09c47e6c6c..aafa26a098 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 @@ -58,7 +58,9 @@ public abstract class Slot extends RBuiltinNode { @Specialization protected Object getSlot(RAttributable object, Object nameObj) { - return accessSlotNode.executeAccess(object, getName(nameObj)); + String name = getName(nameObj); + assert name == name.intern(); + return accessSlotNode.executeAccess(object, name); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java index 208e4cb7ff..021eb25bbf 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java @@ -84,7 +84,7 @@ public class ForeignFunctions { Object list = RNull.instance; for (int i = args.getLength() - 1; i >= 0; i--) { String name = args.getSignature().getName(i); - list = RDataFactory.createPairList(args.getArgument(i), list, name == null ? RNull.instance : RDataFactory.createSymbol(name)); + list = RDataFactory.createPairList(args.getArgument(i), list, name == null ? RNull.instance : RDataFactory.createSymbol(name.intern())); } list = RDataFactory.createPairList(symbolName, list); return list; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java index 5cf1c1e345..43a00cc2b8 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.WrapperNode; @@ -114,9 +115,11 @@ public class RASTUtils { public static RSymbol createRSymbol(Node readVariableNode) { if (readVariableNode instanceof ReadVariadicComponentNode) { ReadVariadicComponentNode rvcn = (ReadVariadicComponentNode) readVariableNode; - return RDataFactory.createSymbol(rvcn.getPrintForm()); + return RDataFactory.createSymbol(rvcn.getPrintForm().intern()); } else { - return RDataFactory.createSymbol(((ReadVariableNode) readVariableNode).getIdentifier()); + String id = ((ReadVariableNode) readVariableNode).getIdentifier(); + assert id == id.intern(); + return RDataFactory.createSymbol(id); } } @@ -229,25 +232,27 @@ public class RASTUtils { * or {@link GroupDispatchNode}. */ public static Object findFunctionName(Node node) { + CompilerAsserts.neverPartOfCompilation(); // for string interning RNode child = (RNode) unwrap(getFunctionNode(node)); if (child instanceof ConstantNode && ConstantNode.isFunction(child)) { return ((ConstantNode) child).getValue(); } else if (child instanceof ReadVariableNode) { String name = ((ReadVariableNode) child).getIdentifier(); + assert name == name.intern(); return RDataFactory.createSymbol(name); } else if (child instanceof GroupDispatchNode) { GroupDispatchNode groupDispatchNode = (GroupDispatchNode) child; String gname = groupDispatchNode.getGenericName(); - return RDataFactory.createSymbol(gname); + return RDataFactory.createSymbol(gname.intern()); } else if (child instanceof RBuiltinNode) { RBuiltinNode builtinNode = (RBuiltinNode) child; - return RDataFactory.createSymbol((builtinNode.getBuiltin().getName())); + return RDataFactory.createSymbol((builtinNode.getBuiltin().getName().intern())); } else { // TODO This should really fail in some way as (clearly) this is not a "name" // some more complicated expression, just deparse it RDeparse.State state = RDeparse.State.createPrintableState(); child.deparse(state); - return RDataFactory.createSymbol(state.toString()); + return RDataFactory.createSymbol(state.toString().intern()); } } 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 f709f8d3b7..2b23220db5 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 @@ -41,7 +41,6 @@ public abstract class AccessSlotNode extends RNode { @Child private ClassHierarchyNode classHierarchy; @Child private TypeofNode typeofNode; private final BranchProfile noSlot = BranchProfile.create(); - private final ConditionProfile nullSlot = ConditionProfile.createBinaryProfile(); protected AttributeAccess createAttrAccess(String name) { return AttributeAccessNodeGen.create(name); @@ -50,11 +49,8 @@ public abstract class AccessSlotNode extends RNode { private Object getSlotS4Internal(RAttributable object, String name, Object value) { if (value == null) { noSlot.enter(); + assert name == name.intern(); if (name == RRuntime.DOT_S3_CLASS) { - // TODO: this will not work if `@` function is called directly, as in: - // `@`(x, ".S3Class") - // 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)); @@ -128,7 +124,7 @@ public abstract class AccessSlotNode extends RNode { } protected boolean isDotData(String name) { - // see comment on usinq object equality in getSlotS4() + assert name == name.intern(); return name == RRuntime.DOT_DATA; } } 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 50d8164135..bdda2e770a 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 @@ -17,7 +17,6 @@ import com.oracle.truffle.api.dsl.*; 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.*; import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.nodes.*; @@ -44,7 +43,8 @@ public abstract class UpdateSlotNode extends RNode { @Specialization(contains = "updateSlotS4Cached") protected Object updateSlotS4(RS4Object object, String name, Object value) { - object.setAttr(name.intern(), value); + assert name == name.intern(); + object.setAttr(name, value); return object; } @@ -57,7 +57,8 @@ public abstract class UpdateSlotNode extends RNode { @Specialization(contains = "updateSlotCached") protected Object updateSlot(RAbstractContainer object, String name, Object value) { - object.setAttr(name.intern(), value); + assert name == name.intern(); + object.setAttr(name, value); return object; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNodeSyntaxHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNodeSyntaxHelper.java index 96ed55de7d..2809aeba1c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNodeSyntaxHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNodeSyntaxHelper.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.access; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -56,9 +57,11 @@ abstract class WriteVariableNodeSyntaxHelper extends WriteVariableNode { protected Object getRelementHelper(String op, int index) { switch (index) { case 0: + assert op == op.intern(); return RDataFactory.createSymbol(op); case 1: - return RDataFactory.createSymbol(getName().toString()); + CompilerAsserts.neverPartOfCompilation(); + return RDataFactory.createSymbol(getName().toString().intern()); case 2: return RASTUtils.createLanguageElement(getRhs()); default: diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java index 673ac2dd79..329e4ca35f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java @@ -137,7 +137,7 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi private ReadVariableNode(Object identifier, RType mode, ReadKind kind, boolean visibilityChange) { this.identifier = identifier; - this.identifierAsString = identifier.toString(); + this.identifierAsString = identifier.toString().intern(); this.mode = mode; this.kind = kind; this.visibilityChange = visibilityChange; @@ -180,7 +180,9 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi @Override public Object getRelementImpl(int index) { - return RDataFactory.createSymbol(identifier.toString()); + String id = identifier.toString(); + assert id == id.intern(); + return RDataFactory.createSymbol(id); } @Override diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java index 4b00e38b6a..e90f8a8de9 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java @@ -57,9 +57,11 @@ public abstract class CastSymbolNode extends CastBaseNode { return backQuote(toString(value)); } + @TruffleBoundary @Specialization protected RSymbol doString(String value) { - return RDataFactory.createSymbol(value); + // TODO: see if this is going to hit us performance-wise + return RDataFactory.createSymbol(value.intern()); } @Specialization @@ -85,7 +87,8 @@ public abstract class CastSymbolNode extends CastBaseNode { @TruffleBoundary private static RSymbol backQuote(String s) { - return RDataFactory.createSymbol("`" + s + "`"); + String quotedString = "`" + s + "`"; + return RDataFactory.createSymbol(quotedString.intern()); } public static CastSymbolNode createNonPreserving() { diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Constant.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Constant.java index 40f40c1a88..6177da34e1 100644 --- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Constant.java +++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Constant.java @@ -30,8 +30,23 @@ public final class Constant extends ASTNode { private final String[] values; private final ConstantType type; + /* + * Used in case parameter is a single String value that should not be interned (e.g., NA) + */ + private Constant(String value, SourceSection source) { + super(source); + this.values = new String[]{value}; + this.type = ConstantType.STRING; + } + private Constant(String[] values, ConstantType type, SourceSection source) { super(source); + if (type == ConstantType.STRING) { + assert values != null; + for (int i = 0; i < values.length; i++) { + values[i] = values[i].intern(); + } + } this.values = values; this.type = type; } @@ -95,7 +110,8 @@ public final class Constant extends ASTNode { } public static Constant createStringNA(SourceSection src) { - return new Constant(new String[]{RRuntime.STRING_NA}, ConstantType.STRING, src); + // don't intern NA value, otherwise each "NA" literal becomes an NA value + return new Constant(RRuntime.STRING_NA, src); } public void addNegativeSign() { diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FieldAccess.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FieldAccess.java index 18b51191d2..6dd48e261a 100644 --- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FieldAccess.java +++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FieldAccess.java @@ -45,10 +45,7 @@ public final class FieldAccess extends ASTNode { public static ASTNode create(SourceSection src, FieldOperator op, ASTNode value, String fieldName) { switch (op) { case AT: - // these two names have special meaning for slot retrieval - - String newName = fieldName.equals(RRuntime.DOT_DATA) ? RRuntime.DOT_DATA : (fieldName.equals(RRuntime.DOT_S3_CLASS) ? RRuntime.DOT_S3_CLASS : fieldName); - return new FieldAccess(src, value, newName, true); + return new FieldAccess(src, value, fieldName.intern(), true); case FIELD: return new FieldAccess(src, value, fieldName, false); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java index 0bba416246..ce0aaeb9c4 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java @@ -15,6 +15,7 @@ import java.io.*; import java.nio.charset.*; import java.util.*; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.source.*; @@ -670,7 +671,7 @@ public class RSerialize { case SYMSXP: { String name = (String) readItem(); - result = RDataFactory.createSymbol(name); + result = RDataFactory.createSymbol(name.intern()); addReadRef(result); break; } @@ -1823,7 +1824,8 @@ public class RSerialize { RSymbol findSymbol(String name) { RSymbol symbol = symbolMap.get(name); if (symbol == null) { - symbol = RDataFactory.createSymbol(name); + CompilerAsserts.neverPartOfCompilation(); // for interning + symbol = RDataFactory.createSymbol(name.intern()); symbolMap.put(name, symbol); } return symbol; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java index 6acc3e48d4..56016b5b14 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java @@ -366,9 +366,17 @@ public final class RDataFactory { } public static RSymbol createSymbol(String name) { + assert name == name.intern(); return traceDataCreated(new RSymbol(name)); } + /* + * A version of {@link createSymbol} method used from native code. + */ + public static RSymbol createSymbolInterned(String name) { + return createSymbol(name.intern()); + } + public static RLanguage createLanguage(RNode rep) { return traceDataCreated(new RLanguage(rep)); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java index 469e9f1c81..3fc09939fc 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java @@ -16,6 +16,7 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.RError.RErrorException; import com.oracle.truffle.r.runtime.context.*; @@ -205,7 +206,8 @@ public class DLL { } public static RExternalPtr createExternalPtr(long value, RStringVector rClass) { - RExternalPtr result = RDataFactory.createExternalPtr(value, RDataFactory.createSymbol(rClass.getDataAt(0))); + CompilerAsserts.neverPartOfCompilation(); // for interning + RExternalPtr result = RDataFactory.createExternalPtr(value, RDataFactory.createSymbol(rClass.getDataAt(0).intern())); result.setClassAttr(rClass, false); return result; } 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 46e7b99886..72532269a0 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 @@ -38,6 +38,8 @@ public class TestS4 extends TestBase { assertEval("{ getClass(\"ClassUnionRepresentation\")@virtual }"); assertEval("{ getClass(\"ClassUnionRepresentation\")@.S3Class }"); assertEval("{ c(42)@.Data }"); + assertEval("{ x<-42; `@`(x, \".Data\") }"); + assertEval("{ x<-42; `@`(x, .Data) }"); assertEval(Output.ContainsError, "{ getClass(\"ClassUnionRepresentation\")@foo }"); assertEval(Output.ContainsError, "{ c(42)@foo }"); assertEval(Output.ContainsError, "{ x<-c(42); class(x)<-\"bar\"; x@foo }"); -- GitLab