Skip to content

Commit

Permalink
[Truffle] Use faster version of String#size for single-byte optimizab…
Browse files Browse the repository at this point in the history
…le Strings throughout.
  • Loading branch information
nirvdrum committed Mar 30, 2015
1 parent 3b52341 commit 94e7bf9
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 19 deletions.
36 changes: 25 additions & 11 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
Expand Up @@ -622,15 +622,18 @@ public Object slice(VirtualFrame frame, RubyString string, RubyString matchStr,
@CoreMethod(names = "[]=", required = 2, lowerFixnumParameters = 0, raiseIfFrozenSelf = true)
public abstract static class ElementSetNode extends CoreMethodNode {

@Child private SizeNode sizeNode;
@Child private ToStrNode toStrNode;

public ElementSetNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
sizeNode = StringNodesFactory.SizeNodeFactory.create(context, sourceSection, new RubyNode[] { null });
toStrNode = ToStrNodeFactory.create(context, sourceSection, null);
}

public ElementSetNode(ElementSetNode prev) {
super(prev);
sizeNode = prev.sizeNode;
toStrNode = prev.toStrNode;
}

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

int begin = range.getBegin();
int end = range.getEnd();
final int stringLength = string.length();
final int stringLength = sizeNode.executeIntegerFixnum(frame, string);

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

@Child private SizeNode sizeNode;

public ChopBangNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
sizeNode = StringNodesFactory.SizeNodeFactory.create(context, sourceSection, new RubyNode[] { null });
}

public ChopBangNode(ChopBangNode prev) {
super(prev);
sizeNode = prev.sizeNode;
}

@Specialization
public Object chopBang(RubyString string) {
public Object chopBang(VirtualFrame frame, RubyString string) {
notDesignedForCompilation();

if (string.length() == 0) {
if (sizeNode.executeIntegerFixnum(frame, string) == 0) {
return nil();
}

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

@Child private SizeNode sizeNode;

public RindexNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
sizeNode = StringNodesFactory.SizeNodeFactory.create(context, sourceSection, new RubyNode[] { null });
}

public RindexNode(RindexNode prev) {
super(prev);
sizeNode = prev.sizeNode;
}

@Specialization
public Object rindex(RubyString string, RubyString subString, @SuppressWarnings("unused") UndefinedPlaceholder endPosition) {
public Object rindex(VirtualFrame frame, RubyString string, RubyString subString, @SuppressWarnings("unused") UndefinedPlaceholder endPosition) {
notDesignedForCompilation();

return rindex(string, subString, string.length());
return rindex(frame, string, subString, sizeNode.executeIntegerFixnum(frame, string));
}

@Specialization
public Object rindex(RubyString string, RubyString subString, int endPosition) {
public Object rindex(VirtualFrame frame, RubyString string, RubyString subString, int endPosition) {
notDesignedForCompilation();

final int stringLength = sizeNode.executeIntegerFixnum(frame, string);
int normalizedEndPosition = endPosition;

if (endPosition < 0) {
normalizedEndPosition = endPosition + string.length();
normalizedEndPosition = endPosition + stringLength;

if (normalizedEndPosition < 0) {
return nil();
}
} else if (endPosition > string.length()) {
normalizedEndPosition = string.length();
} else if (endPosition > stringLength) {
normalizedEndPosition = stringLength;
}

int result = StringSupport.rindex(string.getBytes(), string.length(), subString.length(),
int result = StringSupport.rindex(string.getBytes(), stringLength, subString.length(),
normalizedEndPosition, subString, string.getBytes().getEncoding()
);

Expand Down Expand Up @@ -1770,6 +1782,8 @@ public SizeNode(SizeNode prev) {
super(prev);
}

public abstract int executeIntegerFixnum(VirtualFrame frame, RubyString string);

@Specialization(guards = "isSingleByteOptimizable")
public int sizeSingleByte(RubyString string) {
return string.getByteList().getRealSize();
Expand Down Expand Up @@ -1819,7 +1833,7 @@ public SuccBangNode(SuccBangNode prev) {
public RubyString succBang(RubyString string) {
notDesignedForCompilation();

if (string.length() > 0) {
if (string.getByteList().getRealSize() > 0) {
string.set(StringSupport.succCommon(getContext().getRuntime(), string.getBytes()));
}

Expand Down
Expand Up @@ -363,23 +363,30 @@ public static abstract class StringCompareSubstringPrimitiveNode extends Rubiniu
private final ConditionProfile startTooLargeProfile = ConditionProfile.createBinaryProfile();
private final ConditionProfile startTooSmallProfile = ConditionProfile.createBinaryProfile();

@Child private StringNodes.SizeNode sizeNode;

public StringCompareSubstringPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
sizeNode = StringNodesFactory.SizeNodeFactory.create(context, sourceSection, new RubyNode[] { null });
}

public StringCompareSubstringPrimitiveNode(StringCompareSubstringPrimitiveNode prev) {
super(prev);
sizeNode = prev.sizeNode;
}

@Specialization
public int stringCompareSubstring(RubyString string, RubyString other, int start, int size) {
public int stringCompareSubstring(VirtualFrame frame, RubyString string, RubyString other, int start, int size) {
// Transliterated from Rubinius C++.

final int stringLength = sizeNode.executeIntegerFixnum(frame, string);
final int otherLength = sizeNode.executeIntegerFixnum(frame, other);

if (start < 0) {
start += other.length();
start += otherLength;
}

if (startTooLargeProfile.profile(start > other.length())) {
if (startTooLargeProfile.profile(start > otherLength)) {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(
Expand All @@ -399,12 +406,12 @@ public int stringCompareSubstring(RubyString string, RubyString other, int start
));
}

if (start + size > other.length()) {
size = other.length() - start;
if (start + size > otherLength) {
size = otherLength - start;
}

if (size > string.length()) {
size = string.length();
if (size > stringLength) {
size = stringLength;
}

final ByteList bytes = string.getByteList();
Expand Down
Expand Up @@ -9,6 +9,7 @@
*/
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.nodes.Node;
import org.jcodings.Encoding;
Expand Down Expand Up @@ -134,7 +135,15 @@ public String toString() {
}

public int length() {
return StringSupport.strLengthFromRubyString(this);
if (CompilerDirectives.injectBranchProbability(
CompilerDirectives.FASTPATH_PROBABILITY,
StringSupport.isSingleByteOptimizable(this, getByteList().getEncoding()))) {

return getByteList().getRealSize();

} else {
return StringSupport.strLengthFromRubyString(this);
}
}

public int normalizeIndex(int index) {
Expand Down

0 comments on commit 94e7bf9

Please sign in to comment.