Skip to content

Commit

Permalink
Showing 1 changed file with 27 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jcodings.Ptr;
import org.jcodings.transcode.EConv;
import org.jcodings.transcode.EConvResult;
@@ -51,6 +52,8 @@ public Object encodingConverterAllocate(RubyBasicObject encodingConverterClass,
@RubiniusPrimitive(name = "encoding_converter_primitive_convert")
public static abstract class PrimitiveConvertNode extends RubiniusPrimitiveNode {

private final ConditionProfile nonNullSourceProfile = ConditionProfile.createBinaryProfile();

public PrimitiveConvertNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}
@@ -61,6 +64,12 @@ public Object encodingConverterPrimitiveConvert(RubyBasicObject encodingConverte
throw new UnsupportedOperationException("not implemented");
}

@Specialization(guards = {"isNil(source)", "isRubyString(target)"})
public Object primitiveConvertNilSource(RubyBasicObject encodingConverter, RubyBasicObject source,
RubyBasicObject target, int offset, int size, int options) {
return primitiveConvertHelper(encodingConverter, new ByteList(), source, target, offset, size, options);
}

@Specialization(guards = {"isRubyString(source)", "isRubyString(target)"})
public Object encodingConverterPrimitiveConvert(RubyBasicObject encodingConverter, RubyBasicObject source,
RubyBasicObject target, int offset, int size, int options) {
@@ -70,10 +79,18 @@ public Object encodingConverterPrimitiveConvert(RubyBasicObject encodingConverte
StringNodes.modify(source);
StringNodes.clearCodeRange(source);

return primitiveConvertHelper(encodingConverter, StringNodes.getByteList(source), source, target, offset, size, options);
}

private Object primitiveConvertHelper(RubyBasicObject encodingConverter, ByteList inBytes, RubyBasicObject source,
RubyBasicObject target, int offset, int size, int options) {
// Taken from org.jruby.RubyConverter#primitive_convert.

final boolean nonNullSource = source != nil();

StringNodes.modify(target);
StringNodes.clearCodeRange(target);

final ByteList inBytes = StringNodes.getByteList(source);
final ByteList outBytes = StringNodes.getByteList(target);

final Ptr inPtr = new Ptr();
@@ -87,8 +104,10 @@ public Object encodingConverterPrimitiveConvert(RubyBasicObject encodingConverte
if (size == -1) {
size = 16; // in MRI, this is RSTRING_EMBED_LEN_MAX

if (size < StringNodes.getByteList(source).getRealSize()) {
size = StringNodes.getByteList(source).getRealSize();
if (nonNullSourceProfile.profile(nonNullSource)) {
if (size < StringNodes.getByteList(source).getRealSize()) {
size = StringNodes.getByteList(source).getRealSize();
}
}
}

@@ -113,7 +132,7 @@ public Object encodingConverterPrimitiveConvert(RubyBasicObject encodingConverte
);
}

outBytes.ensure((int)outputByteEnd);
outBytes.ensure((int) outputByteEnd);

inPtr.p = inBytes.getBegin();
outPtr.p = outBytes.getBegin() + offset;
@@ -122,8 +141,10 @@ public Object encodingConverterPrimitiveConvert(RubyBasicObject encodingConverte

outBytes.setRealSize(outPtr.p - outBytes.begin());

StringNodes.getByteList(source).setRealSize(inBytes.getRealSize() - (inPtr.p - inBytes.getBegin()));
StringNodes.getByteList(source).setBegin(inPtr.p);
if (nonNullSourceProfile.profile(nonNullSource)) {
StringNodes.getByteList(source).setRealSize(inBytes.getRealSize() - (inPtr.p - inBytes.getBegin()));
StringNodes.getByteList(source).setBegin(inPtr.p);
}

if (growOutputBuffer && res == EConvResult.DestinationBufferFull) {
if (Integer.MAX_VALUE / 2 < size) {

0 comments on commit 6b025c9

Please sign in to comment.