Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 46cfd643ae10
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 916378611a81
Choose a head ref
  • 4 commits
  • 2 files changed
  • 1 contributor

Commits on Nov 17, 2016

  1. Copy the full SHA
    d72ccc4 View commit details
  2. Copy the full SHA
    0c1cd73 View commit details
  3. Copy the full SHA
    38ed2ae View commit details
  4. Copy the full SHA
    9163786 View commit details
Showing with 69 additions and 45 deletions.
  1. +0 −3 truffle/src/main/java/org/jruby/truffle/core/rope/RopeNodes.java
  2. +69 −42 truffle/src/main/java/org/jruby/truffle/core/string/StringNodes.java
Original file line number Diff line number Diff line change
@@ -242,7 +242,6 @@ public Rope concatMutableRope(RopeBuffer left, Rope right, Encoding encoding,
try {
Math.addExact(left.byteLength(), right.byteLength());
} catch (ArithmeticException e) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new RaiseException(getContext().getCoreExceptions().argumentError("Result of string concatenation exceeds the system maximum string length", this));
}

@@ -265,7 +264,6 @@ public Rope concat(Rope left, Rope right, Encoding encoding,
try {
Math.addExact(left.byteLength(), right.byteLength());
} catch (ArithmeticException e) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new RaiseException(getContext().getCoreExceptions().argumentError("Result of string concatenation exceeds the system maximum string length", this));
}

@@ -366,7 +364,6 @@ public LeafRope makeValidLeafRope(byte[] bytes, Encoding encoding, CodeRange cod
int delta = StringSupport.encFastMBCLen(bytes, p, e, encoding);

if (delta < 0) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new UnsupportedOperationException("Code range is reported as valid, but is invalid for the given encoding: " + encoding.toString());
}

111 changes: 69 additions & 42 deletions truffle/src/main/java/org/jruby/truffle/core/string/StringNodes.java
Original file line number Diff line number Diff line change
@@ -1354,6 +1354,7 @@ public abstract static class InsertNode extends CoreMethodNode {

@Child private CallDispatchHeadNode appendNode;
@Child private CharacterByteIndexNode characterByteIndexNode;
@Child private CheckCharacterIndexNode checkCharacterIndexNode;
@Child private EncodingNodes.CheckEncodingNode checkEncodingNode;
@Child private RopeNodes.MakeConcatNode prependMakeConcatNode;
@Child private RopeNodes.MakeConcatNode leftMakeConcatNode;
@@ -1366,6 +1367,7 @@ public InsertNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
characterByteIndexNode = StringNodesFactory.CharacterByteIndexNodeFactory.create(new RubyNode[] {});
checkEncodingNode = EncodingNodesFactory.CheckEncodingNodeGen.create(context, sourceSection, null, null);
checkCharacterIndexNode = StringNodesFactory.CheckCharacterIndexNodeGen.create(null, null);
leftMakeConcatNode = RopeNodesFactory.MakeConcatNodeGen.create(null, null, null);
rightMakeConcatNode = RopeNodesFactory.MakeConcatNodeGen.create(null, null, null);
leftMakeSubstringNode = RopeNodesFactory.MakeSubstringNodeGen.create(null, null, null);
@@ -1423,8 +1425,7 @@ public Object insert(VirtualFrame frame, DynamicObject string, int index, Dynami
final Rope insert = rope(other);
final Encoding compatibleEncoding = checkEncodingNode.executeCheckEncoding(string, other);

final int stringLength = source.characterLength();
final int normalizedIndex = StringNodesHelper.checkIndex(stringLength, index, this);
final int normalizedIndex = checkCharacterIndexNode.executeCheck(source, index);
final int byteIndex = characterByteIndexNode.executeInt(frame, string, normalizedIndex, 0);

final Rope splitLeft = leftMakeSubstringNode.executeMake(source, 0, byteIndex);
@@ -1451,6 +1452,37 @@ protected boolean indexAtEitherBounds(int index) {
}
}

@ImportStatic(StringGuards.class)
@NodeChildren({ @NodeChild("string"), @NodeChild("index") })
public static abstract class CheckCharacterIndexNode extends RubyNode {

public abstract int executeCheck(Rope string, int index);

@Specialization
protected int check(Rope rope, int characterIndex,
@Cached("createBinaryProfile()") ConditionProfile negativeIndexProfile,
@Cached("create()") BranchProfile errorProfile) {
final int characterLength = rope.characterLength();

if (characterIndex > characterLength) {
errorProfile.enter();
throw new RaiseException(getContext().getCoreExceptions().indexErrorOutOfString(characterIndex, this));
}

if (negativeIndexProfile.profile(characterIndex < 0)) {
if (-characterIndex > characterLength) {
errorProfile.enter();
throw new RaiseException(getContext().getCoreExceptions().indexErrorOutOfString(characterIndex, this));
}

characterIndex += characterLength;
}

return characterIndex;
}

}

@CoreMethod(names = "lstrip!", raiseIfFrozenSelf = true)
@ImportStatic(StringGuards.class)
public abstract static class LstripBangNode extends CoreMethodArrayArgumentsNode {
@@ -1911,6 +1943,7 @@ private int codePointX(Encoding enc, byte[] bytes, int p, int end) {
@ImportStatic(StringGuards.class)
public abstract static class SetByteNode extends CoreMethodNode {

@Child private CheckByteIndexNode checkByteIndexNode;
@Child private RopeNodes.MakeConcatNode composedMakeConcatNode;
@Child private RopeNodes.MakeConcatNode middleMakeConcatNode;
@Child private RopeNodes.MakeLeafRopeNode makeLeafRopeNode;
@@ -1919,6 +1952,7 @@ public abstract static class SetByteNode extends CoreMethodNode {

public SetByteNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
checkByteIndexNode = StringNodesFactory.CheckByteIndexNodeGen.create(null, null);
composedMakeConcatNode = RopeNodesFactory.MakeConcatNodeGen.create(null, null, null);
middleMakeConcatNode = RopeNodesFactory.MakeConcatNodeGen.create(null, null, null);
makeLeafRopeNode = RopeNodesFactory.MakeLeafRopeNodeGen.create(null, null, null, null);
@@ -1938,9 +1972,8 @@ public SetByteNode(RubyContext context, SourceSection sourceSection) {

@Specialization(guards = "!isRopeBuffer(string)")
public int setByte(DynamicObject string, int index, int value) {
final int normalizedIndex = StringNodesHelper.checkIndexForRef(string, index, this);

final Rope rope = rope(string);
final int normalizedIndex = checkByteIndexNode.executeCheck(rope, index);

final Rope left = leftMakeSubstringNode.executeMake(rope, 0, normalizedIndex);
final Rope right = rightMakeSubstringNode.executeMake(rope, normalizedIndex + 1, rope.byteLength() - normalizedIndex - 1);
@@ -1954,9 +1987,8 @@ public int setByte(DynamicObject string, int index, int value) {

@Specialization(guards = "isRopeBuffer(string)")
public int setByteRopeBuffer(DynamicObject string, int index, int value) {
final int normalizedIndex = StringNodesHelper.checkIndexForRef(string, index, this);

final RopeBuffer rope = (RopeBuffer) rope(string);
final int normalizedIndex = checkByteIndexNode.executeCheck(rope, index);

rope.getByteList().set(normalizedIndex, value);

@@ -1965,6 +1997,37 @@ public int setByteRopeBuffer(DynamicObject string, int index, int value) {

}

@ImportStatic(StringGuards.class)
@NodeChildren({ @NodeChild("string"), @NodeChild("index") })
public static abstract class CheckByteIndexNode extends RubyNode {

public abstract int executeCheck(Rope string, int index);

@Specialization
protected int checkIndex(Rope rope, int byteIndex,
@Cached("createBinaryProfile()") ConditionProfile negativeIndexProfile,
@Cached("create()") BranchProfile errorProfile) {
final int byteLength = rope.byteLength();

if (byteIndex >= byteLength) {
errorProfile.enter();
throw new RaiseException(getContext().getCoreExceptions().indexErrorOutOfString(byteIndex, this));
}

if (negativeIndexProfile.profile(byteIndex < 0)) {
if (-byteIndex > byteLength) {
errorProfile.enter();
throw new RaiseException(getContext().getCoreExceptions().indexErrorOutOfString(byteIndex, this));
}

byteIndex += byteLength;
}

return byteIndex;
}

}

@CoreMethod(names = {"size", "length"})
@ImportStatic(StringGuards.class)
public abstract static class SizeNode extends CoreMethodArrayArgumentsNode {
@@ -2656,42 +2719,6 @@ public DynamicObject clear(DynamicObject string) {

public static class StringNodesHelper {

public static int checkIndex(int length, int index, RubyNode node) {
if (index > length) {
throw new RaiseException(node.getContext().getCoreExceptions().indexErrorOutOfString(index, node));
}

if (index < 0) {
if (-index > length) {
throw new RaiseException(node.getContext().getCoreExceptions().indexErrorOutOfString(index, node));
}

index += length;
}

return index;
}

public static int checkIndexForRef(DynamicObject string, int index, RubyNode node) {
assert RubyGuards.isRubyString(string);

final int length = rope(string).byteLength();

if (index >= length) {
throw new RaiseException(node.getContext().getCoreExceptions().indexErrorOutOfString(index, node));
}

if (index < 0) {
if (-index > length) {
throw new RaiseException(node.getContext().getCoreExceptions().indexErrorOutOfString(index, node));
}

index += length;
}

return index;
}

@TruffleBoundary
private static Object trTransHelper(RubyContext context, EncodingNodes.CheckEncodingNode checkEncodingNode,
DynamicObject self, DynamicObject fromStr,