Skip to content

Commit b7796b9

Browse files
author
Nicolas Laurent
committed
[GR-27582] Flatten ConcatRope when taking its substring.
PullRequest: truffleruby/2185
2 parents 6d65f3d + af850f0 commit b7796b9

File tree

1 file changed

+8
-47
lines changed

1 file changed

+8
-47
lines changed

src/main/java/org/truffleruby/core/rope/RopeNodes.java

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -169,56 +169,17 @@ protected Rope substringNativeRope(NativeRope base, int byteOffset, int byteLeng
169169

170170
@Specialization(guards = { "byteLength > 1", "!sameAsBase(base, byteLength)" })
171171
protected Rope substringConcatRope(ConcatRope base, int byteOffset, int byteLength,
172+
@Cached BytesNode bytesNode,
172173
@Cached WithEncodingNode withEncodingNode,
173174
@Cached MakeSubstringRopeNode makeSubstringRopeNode,
174175
@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);
222183
}
223184

224185
protected static boolean sameAsBase(Rope base, int byteLength) {

0 commit comments

Comments
 (0)