Skip to content

Commit

Permalink
Showing 2 changed files with 80 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -23,12 +23,18 @@

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import org.jcodings.Encoding;
import org.jcodings.specific.ASCIIEncoding;
import org.jcodings.specific.USASCIIEncoding;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.Ruby;
import org.jruby.RubyEncoding;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.util.ByteList;
import org.jruby.util.Memo;
import org.jruby.util.StringSupport;
@@ -41,6 +47,7 @@
import java.util.concurrent.ConcurrentHashMap;

import static org.jruby.truffle.core.rope.CodeRange.CR_7BIT;
import static org.jruby.truffle.core.rope.CodeRange.CR_BROKEN;
import static org.jruby.truffle.core.rope.CodeRange.CR_UNKNOWN;
import static org.jruby.truffle.core.rope.CodeRange.CR_VALID;

@@ -639,4 +646,69 @@ public static ByteList toByteListCopy(Rope rope) {
return new ByteList(rope.getBytes(), rope.getEncoding(), true);
}

@TruffleBoundary
public static Rope format(RubyContext context, Object... values) {
Rope rope = null;

for (Object value : values) {
final Rope valueRope;

if (value instanceof DynamicObject && RubyGuards.isRubyString(value)) {
final Rope stringRope = Layouts.STRING.getRope((DynamicObject) value);
final Encoding encoding = stringRope.getEncoding();

if (encoding == UTF8Encoding.INSTANCE
|| encoding == USASCIIEncoding.INSTANCE
|| encoding == ASCIIEncoding.INSTANCE) {
valueRope = stringRope;
} else {
valueRope = StringOperations.encodeRope(decodeRope(context.getJRubyRuntime(), stringRope), UTF8Encoding.INSTANCE);
}
} else if (value instanceof Integer) {
valueRope = RopeConstants.getIntegerRope((int) value);
} else if (value instanceof String) {
valueRope = context.getRopeTable().getRope((String) value);
} else {
throw new IllegalArgumentException();
}

if (rope == null) {
rope = valueRope;
} else {
if (valueRope == null) {
throw new UnsupportedOperationException(value.getClass().toString());
}

rope = new ConcatRope(
rope,
valueRope,
UTF8Encoding.INSTANCE,
commonCodeRange(rope.getCodeRange(), valueRope.getCodeRange()),
rope.isSingleByteOptimizable() && valueRope.isSingleByteOptimizable(),
Math.max(rope.depth(), valueRope.depth()) + 1);

}
}

if (rope == null) {
rope = RopeConstants.EMPTY_UTF8_ROPE;
}

return rope;
}

private static CodeRange commonCodeRange(CodeRange first, CodeRange second) {
if (first == second) {
return first;
}

if ((first == CR_BROKEN) || (second == CR_BROKEN)) {
return CR_BROKEN;
}

// If we get this far, one must be CR_7BIT and the other must be CR_VALID, so promote to the more general code range.

return CR_VALID;
}

}
Original file line number Diff line number Diff line change
@@ -18,6 +18,9 @@
import org.jruby.truffle.core.CoreClass;
import org.jruby.truffle.core.CoreMethod;
import org.jruby.truffle.core.UnaryCoreMethodNode;
import org.jruby.truffle.core.rope.RopeOperations;
import org.jruby.truffle.core.string.StringNodes;
import org.jruby.truffle.core.string.StringNodesFactory;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.backtrace.Activation;
import org.jruby.truffle.language.backtrace.BacktraceFormatter;
@@ -87,7 +90,6 @@ public ToSNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@TruffleBoundary
@Specialization
public DynamicObject toS(DynamicObject threadBacktraceLocation) {
final Activation activation= ThreadBacktraceLocationLayoutImpl.INSTANCE
@@ -103,10 +105,13 @@ public DynamicObject toS(DynamicObject threadBacktraceLocation) {
return createString(StringOperations.encodeRope(sourceSection.getShortDescription(), UTF8Encoding.INSTANCE));
}

return createString(StringOperations.encodeRope(String.format("%s:%d:in `%s'",
return createString(RopeOperations.format(getContext(),
sourceSection.getSource().getName(),
":",
sourceSection.getStartLine(),
sourceSection.getIdentifier()), UTF8Encoding.INSTANCE));
":in `",
sourceSection.getIdentifier(),
"'"));
}

}

1 comment on commit 38e32b0

@chrisseaton
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nirvdrum in lots of places we do String.format and then convert to a rope. This helper lets you create a concat rope from what you already have. Hopefully will save memory with things like long backtraces. Not sure though, as the rope object itself is fairly heavy. Maybe we need n-way concats...

Sorry, something went wrong.

Please sign in to comment.