Skip to content

Commit 1f5048f

Browse files
bjfisheregon
authored andcommitted
Cache Symbol#to_proc by DeclarationContext
1 parent 5cfbbd0 commit 1f5048f

File tree

3 files changed

+28
-6
lines changed

3 files changed

+28
-6
lines changed

src/main/java/org/truffleruby/core/inlined/CoreMethods.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public class CoreMethods {
8585
public final InternalMethod STRING_BYTESIZE;
8686
public final InternalMethod MODULE_CASE_EQUAL;
8787
public final InternalMethod STRING_EQUAL;
88+
public final InternalMethod SYMBOL_TO_PROC;
8889

8990
public CoreMethods(RubyContext context) {
9091
this.context = context;
@@ -96,6 +97,7 @@ public CoreMethods(RubyContext context) {
9697
final RubyClass moduleClass = context.getCoreLibrary().moduleClass;
9798
final RubyClass nilClass = context.getCoreLibrary().nilClass;
9899
final RubyClass stringClass = context.getCoreLibrary().stringClass;
100+
final RubyClass symbolClass = context.getCoreLibrary().symbolClass;
99101

100102
integerNegAssumption = registerAssumption(integerClass, "-@");
101103
floatNegAssumption = registerAssumption(floatClass, "-@");
@@ -143,6 +145,7 @@ public CoreMethods(RubyContext context) {
143145
KERNEL_KIND_OF = getMethod(kernelModule, "kind_of?");
144146
MODULE_CASE_EQUAL = getMethod(moduleClass, "===");
145147
STRING_EQUAL = getMethod(stringClass, "==");
148+
SYMBOL_TO_PROC = getMethod(symbolClass, "to_proc");
146149
}
147150

148151
private Assumption registerAssumption(RubyClass klass, String methodName) {

src/main/java/org/truffleruby/core/symbol/RubySymbol.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.truffleruby.RubyLanguage;
1414
import org.truffleruby.core.Hashing;
1515
import org.truffleruby.core.klass.RubyClass;
16+
import org.truffleruby.core.proc.RubyProc;
1617
import org.truffleruby.core.rope.Rope;
1718
import org.truffleruby.language.ImmutableRubyObject;
1819

@@ -23,6 +24,10 @@
2324
import com.oracle.truffle.api.interop.TruffleObject;
2425
import com.oracle.truffle.api.library.ExportLibrary;
2526
import com.oracle.truffle.api.library.ExportMessage;
27+
import org.truffleruby.language.methods.DeclarationContext;
28+
29+
import java.util.concurrent.ConcurrentHashMap;
30+
import java.util.concurrent.ConcurrentMap;
2631

2732
@ExportLibrary(InteropLibrary.class)
2833
public final class RubySymbol extends ImmutableRubyObject implements TruffleObject {
@@ -35,6 +40,7 @@ public final class RubySymbol extends ImmutableRubyObject implements TruffleObje
3540
private final Rope rope;
3641
private final int javaStringHashCode;
3742
private final long id;
43+
private final ConcurrentMap<DeclarationContext, RubyProc> cachedProcs = new ConcurrentHashMap<>();
3844

3945
public RubySymbol(String string, Rope rope, long id) {
4046
this.string = string;
@@ -59,6 +65,10 @@ public Rope getRope() {
5965
return rope;
6066
}
6167

68+
public ConcurrentMap<DeclarationContext, RubyProc> getCachedProcs() {
69+
return cachedProcs;
70+
}
71+
6272
public long computeHashCode(Hashing hashing) {
6373
return hashing.hash(CLASS_SALT, javaStringHashCode);
6474
}

src/main/java/org/truffleruby/core/symbol/SymbolNodes.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.truffleruby.builtins.CoreMethodArrayArgumentsNode;
1414
import org.truffleruby.builtins.CoreModule;
1515
import org.truffleruby.builtins.UnaryCoreMethodNode;
16+
import org.truffleruby.collections.ConcurrentOperations;
1617
import org.truffleruby.core.CoreLibrary;
1718
import org.truffleruby.core.array.RubyArray;
1819
import org.truffleruby.core.klass.RubyClass;
@@ -105,20 +106,28 @@ public abstract static class ToProcNode extends CoreMethodArrayArgumentsNode {
105106
protected RubyProc toProcCached(VirtualFrame frame, RubySymbol symbol,
106107
@Cached("symbol") RubySymbol cachedSymbol,
107108
@Cached("getDeclarationContext(frame)") DeclarationContext cachedDeclarationContext,
108-
@Cached("createProc(cachedDeclarationContext, getMethod(frame), symbol)") RubyProc cachedProc) {
109+
@Cached("getOrCreateProc(cachedDeclarationContext, symbol)") RubyProc cachedProc) {
109110
return cachedProc;
110111
}
111112

112113
@Specialization
113114
protected RubyProc toProcUncached(VirtualFrame frame, RubySymbol symbol) {
114-
final InternalMethod method = getMethod(frame);
115115
DeclarationContext declarationContext = getDeclarationContext(frame);
116-
return createProc(declarationContext, method, symbol);
116+
return getOrCreateProc(declarationContext, symbol);
117117
}
118118

119119
@TruffleBoundary
120-
protected RubyProc createProc(DeclarationContext declarationContext, InternalMethod method,
121-
RubySymbol symbol) {
120+
protected RubyProc getOrCreateProc(DeclarationContext declarationContext, RubySymbol symbol) {
121+
declarationContext = declarationContext == null ? DeclarationContext.NONE : declarationContext;
122+
return ConcurrentOperations.getOrCompute(
123+
symbol.getCachedProcs(),
124+
declarationContext,
125+
key -> createProc(key, symbol));
126+
}
127+
128+
@TruffleBoundary
129+
protected RubyProc createProc(DeclarationContext declarationContext, RubySymbol symbol) {
130+
final InternalMethod method = getContext().getCoreMethods().SYMBOL_TO_PROC;
122131
final SourceSection sourceSection = CoreLibrary.UNAVAILABLE_SOURCE_SECTION;
123132
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(
124133
sourceSection,
@@ -157,7 +166,7 @@ protected RubyProc createProc(DeclarationContext declarationContext, InternalMet
157166
method,
158167
null,
159168
null,
160-
declarationContext == null ? DeclarationContext.NONE : declarationContext);
169+
declarationContext);
161170
}
162171

163172
protected InternalMethod getMethod(VirtualFrame frame) {

0 commit comments

Comments
 (0)