Skip to content

Commit 94e7bf9

Browse files
committed
[Truffle] Use faster version of String#size for single-byte optimizable Strings throughout.
1 parent 3b52341 commit 94e7bf9

File tree

3 files changed

+49
-19
lines changed

3 files changed

+49
-19
lines changed

truffle/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -622,15 +622,18 @@ public Object slice(VirtualFrame frame, RubyString string, RubyString matchStr,
622622
@CoreMethod(names = "[]=", required = 2, lowerFixnumParameters = 0, raiseIfFrozenSelf = true)
623623
public abstract static class ElementSetNode extends CoreMethodNode {
624624

625+
@Child private SizeNode sizeNode;
625626
@Child private ToStrNode toStrNode;
626627

627628
public ElementSetNode(RubyContext context, SourceSection sourceSection) {
628629
super(context, sourceSection);
630+
sizeNode = StringNodesFactory.SizeNodeFactory.create(context, sourceSection, new RubyNode[] { null });
629631
toStrNode = ToStrNodeFactory.create(context, sourceSection, null);
630632
}
631633

632634
public ElementSetNode(ElementSetNode prev) {
633635
super(prev);
636+
sizeNode = prev.sizeNode;
634637
toStrNode = prev.toStrNode;
635638
}
636639

@@ -648,7 +651,7 @@ public RubyString elementSet(VirtualFrame frame, RubyString string, RubyRange.In
648651

649652
int begin = range.getBegin();
650653
int end = range.getEnd();
651-
final int stringLength = string.length();
654+
final int stringLength = sizeNode.executeIntegerFixnum(frame, string);
652655

653656
if (begin < 0) {
654657
begin += stringLength;
@@ -801,19 +804,23 @@ public int byteSize(RubyString string) {
801804
@CoreMethod(names = "chop!", raiseIfFrozenSelf = true)
802805
public abstract static class ChopBangNode extends CoreMethodNode {
803806

807+
@Child private SizeNode sizeNode;
808+
804809
public ChopBangNode(RubyContext context, SourceSection sourceSection) {
805810
super(context, sourceSection);
811+
sizeNode = StringNodesFactory.SizeNodeFactory.create(context, sourceSection, new RubyNode[] { null });
806812
}
807813

808814
public ChopBangNode(ChopBangNode prev) {
809815
super(prev);
816+
sizeNode = prev.sizeNode;
810817
}
811818

812819
@Specialization
813-
public Object chopBang(RubyString string) {
820+
public Object chopBang(VirtualFrame frame, RubyString string) {
814821
notDesignedForCompilation();
815822

816-
if (string.length() == 0) {
823+
if (sizeNode.executeIntegerFixnum(frame, string) == 0) {
817824
return nil();
818825
}
819826

@@ -1483,38 +1490,43 @@ public RubyString replace(RubyString string, RubyString other) {
14831490
@CoreMethod(names = "rindex", required = 1, optional = 1, lowerFixnumParameters = 1)
14841491
public abstract static class RindexNode extends CoreMethodNode {
14851492

1493+
@Child private SizeNode sizeNode;
1494+
14861495
public RindexNode(RubyContext context, SourceSection sourceSection) {
14871496
super(context, sourceSection);
1497+
sizeNode = StringNodesFactory.SizeNodeFactory.create(context, sourceSection, new RubyNode[] { null });
14881498
}
14891499

14901500
public RindexNode(RindexNode prev) {
14911501
super(prev);
1502+
sizeNode = prev.sizeNode;
14921503
}
14931504

14941505
@Specialization
1495-
public Object rindex(RubyString string, RubyString subString, @SuppressWarnings("unused") UndefinedPlaceholder endPosition) {
1506+
public Object rindex(VirtualFrame frame, RubyString string, RubyString subString, @SuppressWarnings("unused") UndefinedPlaceholder endPosition) {
14961507
notDesignedForCompilation();
14971508

1498-
return rindex(string, subString, string.length());
1509+
return rindex(frame, string, subString, sizeNode.executeIntegerFixnum(frame, string));
14991510
}
15001511

15011512
@Specialization
1502-
public Object rindex(RubyString string, RubyString subString, int endPosition) {
1513+
public Object rindex(VirtualFrame frame, RubyString string, RubyString subString, int endPosition) {
15031514
notDesignedForCompilation();
15041515

1516+
final int stringLength = sizeNode.executeIntegerFixnum(frame, string);
15051517
int normalizedEndPosition = endPosition;
15061518

15071519
if (endPosition < 0) {
1508-
normalizedEndPosition = endPosition + string.length();
1520+
normalizedEndPosition = endPosition + stringLength;
15091521

15101522
if (normalizedEndPosition < 0) {
15111523
return nil();
15121524
}
1513-
} else if (endPosition > string.length()) {
1514-
normalizedEndPosition = string.length();
1525+
} else if (endPosition > stringLength) {
1526+
normalizedEndPosition = stringLength;
15151527
}
15161528

1517-
int result = StringSupport.rindex(string.getBytes(), string.length(), subString.length(),
1529+
int result = StringSupport.rindex(string.getBytes(), stringLength, subString.length(),
15181530
normalizedEndPosition, subString, string.getBytes().getEncoding()
15191531
);
15201532

@@ -1770,6 +1782,8 @@ public SizeNode(SizeNode prev) {
17701782
super(prev);
17711783
}
17721784

1785+
public abstract int executeIntegerFixnum(VirtualFrame frame, RubyString string);
1786+
17731787
@Specialization(guards = "isSingleByteOptimizable")
17741788
public int sizeSingleByte(RubyString string) {
17751789
return string.getByteList().getRealSize();
@@ -1819,7 +1833,7 @@ public SuccBangNode(SuccBangNode prev) {
18191833
public RubyString succBang(RubyString string) {
18201834
notDesignedForCompilation();
18211835

1822-
if (string.length() > 0) {
1836+
if (string.getByteList().getRealSize() > 0) {
18231837
string.set(StringSupport.succCommon(getContext().getRuntime(), string.getBytes()));
18241838
}
18251839

truffle/src/main/java/org/jruby/truffle/nodes/rubinius/StringPrimitiveNodes.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -363,23 +363,30 @@ public static abstract class StringCompareSubstringPrimitiveNode extends Rubiniu
363363
private final ConditionProfile startTooLargeProfile = ConditionProfile.createBinaryProfile();
364364
private final ConditionProfile startTooSmallProfile = ConditionProfile.createBinaryProfile();
365365

366+
@Child private StringNodes.SizeNode sizeNode;
367+
366368
public StringCompareSubstringPrimitiveNode(RubyContext context, SourceSection sourceSection) {
367369
super(context, sourceSection);
370+
sizeNode = StringNodesFactory.SizeNodeFactory.create(context, sourceSection, new RubyNode[] { null });
368371
}
369372

370373
public StringCompareSubstringPrimitiveNode(StringCompareSubstringPrimitiveNode prev) {
371374
super(prev);
375+
sizeNode = prev.sizeNode;
372376
}
373377

374378
@Specialization
375-
public int stringCompareSubstring(RubyString string, RubyString other, int start, int size) {
379+
public int stringCompareSubstring(VirtualFrame frame, RubyString string, RubyString other, int start, int size) {
376380
// Transliterated from Rubinius C++.
377381

382+
final int stringLength = sizeNode.executeIntegerFixnum(frame, string);
383+
final int otherLength = sizeNode.executeIntegerFixnum(frame, other);
384+
378385
if (start < 0) {
379-
start += other.length();
386+
start += otherLength;
380387
}
381388

382-
if (startTooLargeProfile.profile(start > other.length())) {
389+
if (startTooLargeProfile.profile(start > otherLength)) {
383390
CompilerDirectives.transferToInterpreter();
384391

385392
throw new RaiseException(
@@ -399,12 +406,12 @@ public int stringCompareSubstring(RubyString string, RubyString other, int start
399406
));
400407
}
401408

402-
if (start + size > other.length()) {
403-
size = other.length() - start;
409+
if (start + size > otherLength) {
410+
size = otherLength - start;
404411
}
405412

406-
if (size > string.length()) {
407-
size = string.length();
413+
if (size > stringLength) {
414+
size = stringLength;
408415
}
409416

410417
final ByteList bytes = string.getByteList();

truffle/src/main/java/org/jruby/truffle/runtime/core/RubyString.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
package org.jruby.truffle.runtime.core;
1111

12+
import com.oracle.truffle.api.CompilerDirectives;
1213
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
1314
import com.oracle.truffle.api.nodes.Node;
1415
import org.jcodings.Encoding;
@@ -134,7 +135,15 @@ public String toString() {
134135
}
135136

136137
public int length() {
137-
return StringSupport.strLengthFromRubyString(this);
138+
if (CompilerDirectives.injectBranchProbability(
139+
CompilerDirectives.FASTPATH_PROBABILITY,
140+
StringSupport.isSingleByteOptimizable(this, getByteList().getEncoding()))) {
141+
142+
return getByteList().getRealSize();
143+
144+
} else {
145+
return StringSupport.strLengthFromRubyString(this);
146+
}
138147
}
139148

140149
public int normalizeIndex(int index) {

0 commit comments

Comments
 (0)