@@ -169,56 +169,17 @@ protected Rope substringNativeRope(NativeRope base, int byteOffset, int byteLeng
169
169
170
170
@ Specialization (guards = { "byteLength > 1" , "!sameAsBase(base, byteLength)" })
171
171
protected Rope substringConcatRope (ConcatRope base , int byteOffset , int byteLength ,
172
+ @ Cached BytesNode bytesNode ,
172
173
@ Cached WithEncodingNode withEncodingNode ,
173
174
@ Cached MakeSubstringRopeNode makeSubstringRopeNode ,
174
175
@ Cached ConditionProfile matchesChildProfile ) {
175
- Rope root = base ;
176
-
177
- while (root instanceof ConcatRope ) {
178
- ConcatRope concatRoot = (ConcatRope ) root ;
179
- Rope left = concatRoot .getLeft ();
180
- Rope right = concatRoot .getRight ();
181
-
182
- // CASE 1: Fits in left.
183
- if (byteOffset + byteLength <= left .byteLength ()) {
184
- root = left ;
185
- continue ;
186
- }
187
-
188
- // CASE 2: Fits in right.
189
- if (byteOffset >= left .byteLength ()) {
190
- byteOffset -= left .byteLength ();
191
- root = right ;
192
- continue ;
193
- }
194
-
195
- // CASE 3: Spans left and right.
196
- if (byteLength == root .byteLength ()) {
197
- return withEncodingNode .executeWithEncoding (root , base .getEncoding ());
198
- } else {
199
- return makeSubstringRopeNode .executeMake (base .getEncoding (), root , byteOffset , byteLength );
200
- }
201
- }
202
-
203
- if (root instanceof SubstringRope ) {
204
- return substringSubstringRopeWithEncoding (
205
- base .getEncoding (),
206
- (SubstringRope ) root ,
207
- byteOffset ,
208
- byteLength ,
209
- makeSubstringRopeNode );
210
- } else if (root instanceof RepeatingRope ) {
211
- return substringRepeatingRopeWithEncoding (
212
- base .getEncoding (),
213
- (RepeatingRope ) root ,
214
- byteOffset ,
215
- byteLength ,
216
- matchesChildProfile ,
217
- makeSubstringRopeNode ,
218
- withEncodingNode );
219
- }
220
-
221
- return makeSubstringRopeNode .executeMake (base .getEncoding (), root , byteOffset , byteLength );
176
+ // NOTE(norswap, 19 Nov 2020):
177
+ // We flatten the rope here. This avoids issue in the (fairly common) case where the rope tree is basically
178
+ // a linked list. In that case, reading successive substrings causes increasingly bigger concat ropes
179
+ // to be flattened. So better to preventively flatten at the top. This is also generally beneficial if
180
+ // we shift from a write-heavy load (rope tree creation) to a read-heavy load.
181
+ bytesNode .execute (base ); // flatten rope
182
+ return makeSubstringRopeNode .executeMake (base .getEncoding (), base , byteOffset , byteLength );
222
183
}
223
184
224
185
protected static boolean sameAsBase (Rope base , int byteLength ) {
0 commit comments