Skip to content

Commit 081387d

Browse files
committed
Inline cache one RubyEncoding for RubyStringLibrary#getEncoding()
* TruffleString nodes benefit a lot from a constant encoding. Notably checks with the expectedEncoding fold much better.
1 parent 6b3582d commit 081387d

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

src/main/java/org/truffleruby/language/library/RubyStringLibrary.java

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ public final TruffleString.Encoding getTEncoding(Object object) {
5252
static final class Cached extends RubyStringLibrary {
5353

5454
@CompilationFinal private boolean seenMutable, seenImmutable, seenOther;
55+
@CompilationFinal private Object cachedEncoding;
56+
57+
private static final Object GENERIC = new Object();
5558

5659
@Override
5760
public boolean seen(Object object) {
@@ -122,26 +125,46 @@ private AbstractTruffleString specializeGetTString(Object object) {
122125

123126
@Override
124127
public RubyEncoding getEncoding(Object object) {
128+
final RubyEncoding encoding;
125129
if (seenMutable && object instanceof RubyString) {
126-
return ((RubyString) object).getEncodingUnprofiled();
130+
encoding = ((RubyString) object).getEncodingUnprofiled();
127131
} else if (seenImmutable && object instanceof ImmutableRubyString) {
128-
return ((ImmutableRubyString) object).getEncodingUnprofiled();
132+
encoding = ((ImmutableRubyString) object).getEncodingUnprofiled();
133+
} else {
134+
CompilerDirectives.transferToInterpreterAndInvalidate();
135+
return specializeGetEncoding(object);
129136
}
130137

131-
CompilerDirectives.transferToInterpreterAndInvalidate();
132-
return specializeGetEncoding(object);
138+
var localCachedEncoding = this.cachedEncoding;
139+
if (encoding == localCachedEncoding) {
140+
return (RubyEncoding) localCachedEncoding;
141+
} else if (localCachedEncoding == GENERIC) {
142+
return encoding;
143+
} else {
144+
CompilerDirectives.transferToInterpreterAndInvalidate();
145+
return specializeGetEncoding(object);
146+
}
133147
}
134148

135149
private RubyEncoding specializeGetEncoding(Object object) {
150+
final RubyEncoding encoding;
136151
if (object instanceof RubyString) {
137152
seenMutable = true;
138-
return ((RubyString) object).getEncodingUnprofiled();
153+
encoding = ((RubyString) object).getEncodingUnprofiled();
139154
} else if (object instanceof ImmutableRubyString) {
140155
seenImmutable = true;
141-
return ((ImmutableRubyString) object).getEncodingUnprofiled();
156+
encoding = ((ImmutableRubyString) object).getEncodingUnprofiled();
142157
} else {
143158
throw CompilerDirectives.shouldNotReachHere();
144159
}
160+
161+
var localCachedEncoding = this.cachedEncoding;
162+
if (localCachedEncoding == null) {
163+
this.cachedEncoding = encoding;
164+
} else if (encoding != localCachedEncoding) {
165+
this.cachedEncoding = GENERIC;
166+
}
167+
return encoding;
145168
}
146169

147170
@Override

test/truffle/compiler/pe/core/string_pe.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
ABC_ROPE_USASCII = 'abc'.force_encoding('us-ascii')
1111
ABC_ROPE_UTF8 = 'abc'.force_encoding('utf-8')
1212

13+
example "'abc'.encoding", Encoding::UTF_8
14+
1315
example "'abc'.length", 3
1416
example "'こにちわ'.length", 4
1517

0 commit comments

Comments
 (0)