@@ -43,6 +43,11 @@ public TBytesKey(byte[] bytes, RubyEncoding encoding) {
43
43
this (bytes , 0 , bytes .length , Arrays .hashCode (bytes ), encoding );
44
44
}
45
45
46
+ /** Supports the creation of a cache key using a subset of bytes. This key *must* be used for lookups only. If you
47
+ * want to insert into the cache, you *must* use the result of {@link #makeCacheable(boolean)}.
48
+ *
49
+ * @param byteArray A byte array retrieved from a {@link TruffleString}
50
+ * @param encoding The Ruby encoding object needed to properly decode the associated byte array */
46
51
public TBytesKey (InternalByteArray byteArray , RubyEncoding encoding ) {
47
52
this (
48
53
byteArray .getArray (),
@@ -113,13 +118,27 @@ private boolean isPerfectFit() {
113
118
return offset == 0 && length == bytes .length ;
114
119
}
115
120
121
+ /** Returns a cache key suitable for insertion into the string cache. It's quite common that we want to cache a
122
+ * substring. Since we don't want to retain the entire original string, we resolve the substring by making a copy of
123
+ * the byte range that we need. However, that is a costly operation and that work is discarded in the event of a
124
+ * cache hit. To avoid incurring that cost unnecessarily, we allow cache keys to refer to a subset of a byte array.
125
+ * While that saves computation during a cache lookup, it means such keys are unsuitable for insertion into the
126
+ * cache. This method makes a key we can use safely for insertion.
127
+ *
128
+ * If we know that the key refers to an immutable byte array and the key does not refer to a substring, we can
129
+ * safely refer to the original byte array without needing to make an additional copy.
130
+ *
131
+ * @param isImmutable whether the key's byte array is immutable
132
+ * @return a cache key suitable for insertion */
116
133
public TBytesKey makeCacheable (boolean isImmutable ) {
117
134
if (isImmutable && isPerfectFit ()) {
118
- return new TBytesKey ( bytes , encoding ) ;
135
+ return this ;
119
136
}
120
137
121
- var simplified = ArrayUtils .extractRange (this .bytes , this .offset , this .offset + this .length );
122
- return new TBytesKey (simplified , encoding );
138
+ // Make a copy of the substring's bytes so we can cache them without retaining the original byte array.
139
+ var resolvedSubstring = ArrayUtils .extractRange (this .bytes , this .offset , this .offset + this .length );
140
+
141
+ return new TBytesKey (resolvedSubstring , encoding );
123
142
}
124
143
125
144
public TBytesKey withNewEncoding (RubyEncoding encoding ) {
0 commit comments