Skip to content

Commit

Permalink
Showing 1 changed file with 35 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -89,6 +89,7 @@
import org.jruby.truffle.core.rope.CodeRange;
import org.jruby.truffle.core.rope.RepeatingRope;
import org.jruby.truffle.core.rope.Rope;
import org.jruby.truffle.core.rope.RopeBuffer;
import org.jruby.truffle.core.rope.RopeConstants;
import org.jruby.truffle.core.rope.RopeNodes;
import org.jruby.truffle.core.rope.RopeNodesFactory;
@@ -1655,7 +1656,8 @@ public Object stringSubstring(DynamicObject string, int beg, int len,
@Cached("createBinaryProfile()") ConditionProfile negativeBeginProfile,
@Cached("createBinaryProfile()") ConditionProfile stillNegativeBeginProfile,
@Cached("createBinaryProfile()") ConditionProfile tooLargeTotalProfile,
@Cached("createBinaryProfile()") ConditionProfile negativeLengthProfile) {
@Cached("createBinaryProfile()") ConditionProfile negativeLengthProfile,
@Cached("createBinaryProfile()") ConditionProfile mutableRopeProfile) {
// Taken from org.jruby.RubyString#substr19.
final Rope rope = rope(string);
if (emptyStringProfile.profile(rope.isEmpty())) {
@@ -1684,6 +1686,10 @@ public Object stringSubstring(DynamicObject string, int beg, int len,
beg = 0;
}

if (mutableRopeProfile.profile(rope instanceof RopeBuffer)) {
return makeBuffer(string, beg, len);
}

return makeRope(string, beg, len);
}

@@ -1790,6 +1796,34 @@ private DynamicObject makeRope(DynamicObject string, int beg, int len) {
return ret;
}

private DynamicObject makeBuffer(DynamicObject string, int beg, int len) {
assert RubyGuards.isRubyString(string);

final RopeBuffer buffer = (RopeBuffer) rope(string);

if (allocateNode == null) {
CompilerDirectives.transferToInterpreter();
allocateNode = insert(AllocateObjectNodeGen.create(getContext(), getSourceSection(), null, null));
}

if (taintResultNode == null) {
CompilerDirectives.transferToInterpreter();
taintResultNode = insert(new TaintResultNode(getContext(), getSourceSection()));
}

// NB: This is only valid for the single-byte case. If multi-byte, the code range must be recalculated.
// This is not intended to be a 100% correct implementation, since you should normally be using the
// immutable rope variant.

This comment has been minimized.

Copy link
@eregon

eregon Apr 13, 2016

Member

Maybe an assert then? Or computing it if len != 1?

This comment has been minimized.

Copy link
@nirvdrum

nirvdrum Apr 13, 2016

Author Contributor

Sure. But we generally don't have assertions enabled at runtime. I guess I could guard and throw exceptions. There's no way to create a RopeBuffer without using our primitive to convert an existing rope so I was okay being a bit loose with it.

This comment has been minimized.

Copy link
@eregon

eregon Apr 13, 2016

Member

I was thinking a long comment can sometimes be expressed more concisely in code, and get the bonus to be checked.

This comment has been minimized.

Copy link
@nirvdrum

nirvdrum Apr 13, 2016

Author Contributor

You win. I guess I was just being lazy. Fixed in a52432e.

final DynamicObject ret = allocateNode.allocate(
Layouts.BASIC_OBJECT.getLogicalClass(string),
new RopeBuffer(new ByteList(buffer.getByteList(), beg, len), buffer.getCodeRange(), buffer.isSingleByteOptimizable(), len),
null);

taintResultNode.maybeTaint(string, ret);

return ret;
}

}

@RubiniusPrimitive(name = "string_from_bytearray", needsSelf = false, lowerFixnumParameters = { 1, 2 })

0 comments on commit cbc3631

Please sign in to comment.