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: eedb0e82441e
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 018eeacc4ae7
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Jan 28, 2016

  1. Unverified

    This user has not yet uploaded their public signing key.
    Copy the full SHA
    f7cb856 View commit details
  2. [Truffle] Improved reuse of existing descendent byte[] calculations w…

    …hen flattening a rope.
    nirvdrum committed Jan 28, 2016
    Copy the full SHA
    018eeac View commit details
Original file line number Diff line number Diff line change
@@ -2465,7 +2465,12 @@ private RuntimeException handleException(PackException exception) {
}

private DynamicObject finishPack(int formatLength, PackResult result) {
final Rope rope = makeLeafRopeNode.executeMake(Arrays.copyOfRange((byte[]) result.getOutput(), 0, result.getOutputLength()), ASCIIEncoding.INSTANCE, StringSupport.CR_UNKNOWN);
byte[] bytes = (byte[]) result.getOutput();
if (bytes.length != result.getOutputLength()) {
bytes = Arrays.copyOf(bytes, result.getOutputLength());
}

final Rope rope = makeLeafRopeNode.executeMake(bytes, ASCIIEncoding.INSTANCE, StringSupport.CR_UNKNOWN);
final DynamicObject string = createString(rope);

if (formatLength == 0) {
Original file line number Diff line number Diff line change
@@ -154,7 +154,6 @@ public static LeafRope flatten(Rope rope) {
return create(flattenBytes(rope), rope.getEncoding(), rope.getCodeRange());
}

@TruffleBoundary
/**
* Performs an iterative depth first search of the Rope tree to calculate its byte[] without needing to populate
* the byte[] for each level beneath. Every LeafRope has its byte[] populated by definition. The goal is to determine
@@ -165,6 +164,7 @@ public static LeafRope flatten(Rope rope) {
* of stack frame management. Additionally, a recursive algorithm will eventually overflow the stack if the Rope
* tree is too deep.
*/
@TruffleBoundary
public static byte[] flattenBytes(Rope rope) {
if (rope instanceof LeafRope) {
return rope.getRawBytes();
@@ -194,6 +194,47 @@ public static byte[] flattenBytes(Rope rope) {
continue;
}

if (current.getRawBytes() != null) {
// In the absence of any SubstringRopes, we always take the full contents of the current rope.
if (substringLengths.isEmpty()) {
System.arraycopy(current.getRawBytes(), offset, buffer, bufferPosition, current.byteLength());
bufferPosition += current.byteLength();
} else {
int bytesToCopy = substringLengths.pop();
final int currentBytesToCopy;

// If we reach here, this rope is a descendant of a SubstringRope at some level. Based on
// the currently calculated byte[] offset and the number of bytes to extract, determine how many
// bytes we can copy to the buffer.
if (bytesToCopy > (current.byteLength() - offset)) {
currentBytesToCopy = current.byteLength() - offset;
} else {
currentBytesToCopy = bytesToCopy;
}

System.arraycopy(current.getRawBytes(), offset, buffer, bufferPosition, currentBytesToCopy);
bufferPosition += currentBytesToCopy;
bytesToCopy -= currentBytesToCopy;

// If this rope wasn't able to satisfy the remaining byte count from the ancestor SubstringRope,
// update the byte count for the next item in the work queue.
if (bytesToCopy > 0) {
substringLengths.push(bytesToCopy);
}
}

// By definition, offsets only affect the start of the rope. Once we've copied bytes out of a rope,
// we need to reset the offset or subsequent items in the work queue will copy from the wrong location.
//
// NB: In contrast to the number of bytes to extract, the offset can be shared and updated by multiple
// levels of SubstringRopes. Thus, we do not need to maintain offsets in a stack and it is appropriate
// to clear the offset after the first time we use it, since it will have been updated accordingly at
// each SubstringRope encountered for this SubstringRope ancestry chain.
offset = 0;

continue;
}

if (current instanceof ConcatRope) {
final ConcatRope concatRope = (ConcatRope) current;

@@ -225,7 +266,8 @@ public static byte[] flattenBytes(Rope rope) {
final SubstringRope substringRope = (SubstringRope) current;

// If this SubstringRope is a descendant of another SubstringRope, we need to increment the offset
// so that when we finally reach a LeafRope, we're extracting bytes from the correct location.
// so that when we finally reach a rope with its byte[] filled, we're extracting bytes from the correct
// location.
offset += substringRope.getOffset();

workStack.push(substringRope.getChild());
@@ -263,43 +305,6 @@ public static byte[] flattenBytes(Rope rope) {
substringLengths.push(adjustedByteLength);
}
}
} else if (current instanceof LeafRope) {
// In the absence of any SubstringRopes, we always take the full contents of the LeafRope.
if (substringLengths.isEmpty()) {
System.arraycopy(current.getRawBytes(), offset, buffer, bufferPosition, current.byteLength());
bufferPosition += current.byteLength();
} else {
int bytesToCopy = substringLengths.pop();
final int currentBytesToCopy;

// If we reach here, this LeafRope is a descendant of a SubstringRope at some level. Based on
// the currently calculated byte[] offset and the number of bytes to extract, determine how many
// bytes we can copy to the buffer.
if (bytesToCopy > (current.byteLength() - offset)) {
currentBytesToCopy = current.byteLength() - offset;
} else {
currentBytesToCopy = bytesToCopy;
}

System.arraycopy(current.getRawBytes(), offset, buffer, bufferPosition, currentBytesToCopy);
bufferPosition += currentBytesToCopy;
bytesToCopy -= currentBytesToCopy;

// If this LeafRope wasn't able to satisfy the remaining byte count from the ancestor SubstringRope,
// update the byte count for the next item in the work queue.
if (bytesToCopy > 0) {
substringLengths.push(bytesToCopy);
}
}

// By definition, offsets only affect the start of the rope. Once we've copied bytes out of a LeafRope,
// we need to reset the offset or subsequent items in the work queue will copy from the wrong location.
//
// NB: In contrast to the number of bytes to extract, the offset can be shared and updated by multiple
// levels of SubstringRopes. Thus, we do not need to maintain offsets in a stack and it is appropriate
// to clear the offset after the first time we use it, since it will have been updated accordingly at
// each SubstringRope encountered for this SubstringRope ancestry chain.
offset = 0;
} else {
CompilerDirectives.transferToInterpreter();
throw new UnsupportedOperationException("Don't know how to flatten rope of type: " + rope.getClass().getName());