From b07c88fd621cd134466e27830020b9c3892ddac0 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Tue, 28 Jan 2025 19:37:32 +0100 Subject: [PATCH] Fix shared caches should be allowed when used for a single specialization with multiple instances. --- .../api/dsl/test/SharedCachedTest.java | 39 +++++++++++++++++++ .../dsl/processor/parser/NodeParser.java | 15 ++++--- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SharedCachedTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SharedCachedTest.java index da56b08c6999..b66727398de8 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SharedCachedTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SharedCachedTest.java @@ -45,6 +45,7 @@ import org.junit.Test; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Cached.Exclusive; import com.oracle.truffle.api.dsl.Cached.Shared; @@ -54,11 +55,14 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.UnsupportedSpecializationException; import com.oracle.truffle.api.dsl.test.GenerateInlineTest.SimpleNode; +import com.oracle.truffle.api.dsl.test.SharedCachedTestFactory.SharedCachedInMultiInstanceNodeGen; import com.oracle.truffle.api.dsl.test.SharedCachedTestFactory.SharedStringInGuardNodeGen; import com.oracle.truffle.api.dsl.test.SharedCachedTestFactory.UnboundExclusiveObjectNodeGen; import com.oracle.truffle.api.dsl.test.SharedCachedTestFactory.UnboundSharedObjectNodeGen; import com.oracle.truffle.api.dsl.test.SharedCachedTestFactory.UseGenerateInlineSharedNodeGen; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.strings.TruffleString; +import com.oracle.truffle.api.strings.TruffleString.Encoding; import com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest; @SuppressWarnings({"truffle-inlining", "truffle-neverdefault", "unused"}) @@ -448,4 +452,39 @@ public void testObjectReference() { }); } + @Test + public void testSharedCachedInMultiInstanceNode() { + SharedCachedInMultiInstanceNode node = SharedCachedInMultiInstanceNodeGen.create(); + TruffleString a = TruffleString.fromJavaStringUncached("a", Encoding.UTF_16); + TruffleString b = TruffleString.fromJavaStringUncached("b", Encoding.UTF_16); + TruffleString c = TruffleString.fromJavaStringUncached("c", Encoding.UTF_16); + + assertEquals(a, node.execute(a)); + assertEquals(b, node.execute(b)); + assertEquals(c, node.execute(c)); + } + + public abstract static class SharedCachedInMultiInstanceNode extends Node { + + abstract Object execute(TruffleString name); + + @Specialization(guards = {"stringEquals(equalsNode, cachedName, name)"}, limit = "2") + protected TruffleString doCached(TruffleString name, + @Cached("name") TruffleString cachedName, + @Cached @Shared TruffleString.EqualNode equalsNode, + @Cached("doGeneric(name)") TruffleString cachedResult) { + return cachedResult; + } + + static boolean stringEquals(TruffleString.EqualNode equalNode, TruffleString s1, TruffleString s2) { + return equalNode.execute(s1, s2, Encoding.UTF_16); + } + + @TruffleBoundary + @Specialization(replaces = "doCached") + protected TruffleString doGeneric(TruffleString name) { + return name; + } + } + } diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java index 2be7d62384c2..da9549302999 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java @@ -1263,11 +1263,16 @@ public static Map computeSharing(Element templateType, } if (declaredSharing.size() <= 1 && (expressions == null || expressions.size() <= 1)) { - cache.addError(cache.getSharedGroupMirror(), cache.getSharedGroupValue(), - "Could not find any other cached parameter that this parameter could be shared. " + - "Cached parameters are only sharable if they declare the same type and initializer expressions and if the specialization only has a single instance. " + - "Remove the @%s annotation or make the parameter sharable to resolve this.", - types.Cached_Shared.asElement().getSimpleName().toString()); + if (declaredSharing.size() == 1 && expressions != null && expressions.size() == 1 && declaredSharing.get(0).specialization.hasMultipleInstances()) { + // allow single shared in multiple instance specialization + sharedExpressions.put(sharable.expression, group); + } else { + cache.addError(cache.getSharedGroupMirror(), cache.getSharedGroupValue(), + "Could not find any other cached parameter that this parameter could be shared. " + + "Cached parameters are only sharable if they declare the same type and initializer expressions and if the specialization only has a single instance. " + + "Remove the @%s annotation or make the parameter sharable to resolve this.", + types.Cached_Shared.asElement().getSimpleName().toString()); + } } else { if (declaredSharing.size() <= 1) {