diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java index 30fe74af0a997c9fdd179f41e46abe25824f42ef..ad1b25a74de3cda9cbc664347f7ca255b1fa4200 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java @@ -229,8 +229,7 @@ public abstract class Identical extends RBuiltinNode.Arg8 { @SuppressWarnings("unused") @Specialization protected byte doInternalIdentical(RSymbol x, RSymbol y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment, boolean ignoreSrcref) { - assert Utils.isInterned(x.getName()) && Utils.isInterned(y.getName()); - return RRuntime.asLogical(x.getName() == y.getName()); + return RRuntime.asLogical(x == y); } @Specialization @@ -343,10 +342,7 @@ public abstract class Identical extends RBuiltinNode.Arg8 { return RRuntime.LOGICAL_FALSE; } else { if (xSubList.getTag() instanceof RSymbol && ySubList.getTag() instanceof RSymbol) { - String xTagName = ((RSymbol) xSubList.getTag()).getName(); - String yTagName = ((RSymbol) ySubList.getTag()).getName(); - assert Utils.isInterned(xTagName) && Utils.isInterned(yTagName); - if (xTagName != yTagName) { + if (xSubList.getTag() != ySubList.getTag()) { return RRuntime.LOGICAL_FALSE; } } else { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java index c368686daf1bcc444c4c2148d12a59b7549d893f..8a74878b896b8e360b137a09d6a95ba0e66ae5c0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java @@ -112,10 +112,6 @@ public abstract class MatchFun extends RBuiltinNode.Arg2 { return vec.getDataAt(0); } - protected static String firstString(RSymbol symbol) { - return symbol.getName(); - } - private RFunction checkResult(Object result) { if (result instanceof RFunction) { return (RFunction) result; @@ -140,11 +136,11 @@ public abstract class MatchFun extends RBuiltinNode.Arg2 { } @SuppressWarnings("unused") - @Specialization(limit = "LIMIT", guards = {"funValue.getName() == cachedName", "getCallerFrameDescriptor(frame) == cachedCallerFrameDescriptor"}) + @Specialization(limit = "LIMIT", guards = {"funValue == cachedFunValue", "getCallerFrameDescriptor(frame) == cachedCallerFrameDescriptor"}) protected RFunction matchfunCached(VirtualFrame frame, RPromise funPromise, RSymbol funValue, boolean descend, - @Cached("firstString(funValue)") String cachedName, + @Cached("funValue") RSymbol cachedFunValue, @Cached("getCallerFrameDescriptor(frame)") FrameDescriptor cachedCallerFrameDescriptor, - @Cached("createLookup(cachedName, descend)") ReadVariableNode lookup) { + @Cached("createLookup(cachedFunValue.getName(), descend)") ReadVariableNode lookup) { return checkResult(lookup.execute(frame, getCallerFrame.execute(frame))); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseAccessSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseAccessSlotNode.java index e53a1687a3a21f55dd2c8995eff4f036b9b26211..ffd83c138f3835cb97e8c28458e194e4651d752f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseAccessSlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseAccessSlotNode.java @@ -96,7 +96,7 @@ public abstract class BaseAccessSlotNode extends RBaseNode { } if (value instanceof RSymbol) { symbolValue.enter(); - if (((RSymbol) value).getName() == RRuntime.PSEUDO_NULL.getName()) { + if (value == RRuntime.PSEUDO_NULL) { return RNull.instance; } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java index 1d292d32d89b0bf3178cd714c612b6402c906928..d4d8e4ac01187840d116c45b6467f89c058c0e08 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java @@ -46,12 +46,12 @@ import java.util.WeakHashMap; */ public final class CharSXPWrapper extends RObject implements RTruffleObject { private static final CharSXPWrapper NA = new CharSXPWrapper(RRuntime.STRING_NA); - private final String contents; + private String contents; private byte[] bytes; private static final Map<CharSXPWrapper, WeakReference<CharSXPWrapper>> instances = new WeakHashMap<>(2048); private CharSXPWrapper(String contents) { - this.contents = Utils.intern(contents); + this.contents = contents; } @TruffleBoundary @@ -96,6 +96,16 @@ public final class CharSXPWrapper extends RObject implements RTruffleObject { } public static CharSXPWrapper create(String contents) { + return create(contents, false); + } + + public static CharSXPWrapper createInterned(String contents) { + assert Utils.isInterned(contents); + return create(contents, true); + } + + private static CharSXPWrapper create(String contents, boolean intern) { + assert !intern || Utils.isInterned(contents); if (contents == RRuntime.STRING_NA) { return NA; } else { @@ -106,6 +116,9 @@ public final class CharSXPWrapper extends RObject implements RTruffleObject { if (wr != null) { cachedWrapper = wr.get(); if (cachedWrapper != null) { + if (intern) { + cachedWrapper.contents = contents; + } return cachedWrapper; } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java index 84a6d232a4c6393a497df9a1746165184f130546..715b8cd6d3292fd9d5ccb40a14c0573674862874 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java @@ -22,11 +22,13 @@ */ package com.oracle.truffle.r.runtime.data; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.Utils; /** * Denotes an R "symbol" or "name". Its rep is a {@code String} but it's a different type in the @@ -39,14 +41,15 @@ public final class RSymbol extends RAttributeStorage { * Note: GnuR caches all symbols and some packages rely on their identity. Moreover, the cached * symbols are never garbage collected. This table corresponds to {@code R_SymbolTable} in GNUR. */ - private static final ConcurrentHashMap<String, RSymbol> symbolTable = new ConcurrentHashMap<>(1024); + private static final ConcurrentHashMap<String, RSymbol> symbolTable = new ConcurrentHashMap<>(2551); public static final RSymbol MISSING = RDataFactory.createSymbol(""); - private final CharSXPWrapper name; + private final String name; + private CharSXPWrapper nameWrapper; private RSymbol(String name) { - this.name = CharSXPWrapper.create(name); + this.name = Utils.intern(name); } @TruffleBoundary @@ -60,11 +63,14 @@ public final class RSymbol extends RAttributeStorage { } public String getName() { - return name.getContents(); + return name; } public CharSXPWrapper getWrappedName() { - return name; + if (nameWrapper == null) { + nameWrapper = CharSXPWrapper.createInterned(name); + } + return nameWrapper; } @Override @@ -78,7 +84,7 @@ public final class RSymbol extends RAttributeStorage { @Override public int hashCode() { - return this.getName().hashCode(); + return System.identityHashCode(this.getName()); } @Override @@ -86,7 +92,7 @@ public final class RSymbol extends RAttributeStorage { if (obj == this) { return true; } else if (obj instanceof RSymbol) { - return ((RSymbol) obj).getName().equals(this.getName()); + return ((RSymbol) obj).getName() == this.name; } return false; }