Skip to content

Commit

Permalink
Showing 19 changed files with 304 additions and 254 deletions.
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.ByteList;
import org.jruby.util.StringSupport;
@@ -112,7 +113,7 @@ public CompatibleQueryNode(RubyContext context, SourceSection sourceSection) {
@TruffleBoundary
@Specialization(guards = {"isRubyString(first)", "isRubyString(second)"})
public Object isCompatibleStringString(DynamicObject first, DynamicObject second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(StringNodes.getCodeRangeable(first), StringNodes.getCodeRangeable(second));
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(StringOperations.getCodeRangeable(first), StringOperations.getCodeRangeable(second));

if (compatibleEncoding != null) {
return getEncoding(compatibleEncoding);
@@ -196,7 +197,7 @@ public Object isCompatibleSymbolRegexp(DynamicObject first, DynamicObject second
@TruffleBoundary
@Specialization(guards = {"isRubyString(first)", "isRubySymbol(second)"})
public Object isCompatibleStringSymbol(DynamicObject first, DynamicObject second) {
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(StringNodes.getCodeRangeable(first), SymbolNodes.getCodeRangeable(second));
final Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(StringOperations.getCodeRangeable(first), SymbolNodes.getCodeRangeable(second));

if (compatibleEncoding != null) {
return getEncoding(compatibleEncoding);
Original file line number Diff line number Diff line change
@@ -63,6 +63,7 @@
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.ArrayOperations;
import org.jruby.truffle.runtime.core.MethodFilter;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.hash.HashOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.methods.InternalMethod;
@@ -1256,7 +1257,7 @@ public DynamicObject methodCached(VirtualFrame frame, Object self, String name)
name, getContext().getCoreLibrary().getLogicalClass(self), this));
}

return MethodNodes.createMethod(getContext().getCoreLibrary().getMethodClass(), self, method);
return Layouts.METHOD.createMethod(getContext().getCoreLibrary().getMethodFactory(), self, method);
}

}
@@ -1940,17 +1941,17 @@ private DynamicObject finishFormat(ByteList format, PackResult result) {
final DynamicObject string = Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), new ByteList(result.getOutput(), 0, result.getOutputLength()), StringSupport.CR_UNKNOWN, null);

if (format.length() == 0) {
StringNodes.forceEncoding(string, USASCIIEncoding.INSTANCE);
StringOperations.forceEncoding(string, USASCIIEncoding.INSTANCE);
} else {
switch (result.getEncoding()) {
case DEFAULT:
case ASCII_8BIT:
break;
case US_ASCII:
StringNodes.forceEncoding(string, USASCIIEncoding.INSTANCE);
StringOperations.forceEncoding(string, USASCIIEncoding.INSTANCE);
break;
case UTF_8:
StringNodes.forceEncoding(string, UTF8Encoding.INSTANCE);
StringOperations.forceEncoding(string, UTF8Encoding.INSTANCE);
break;
default:
throw new UnsupportedOperationException();
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@
import org.jruby.truffle.runtime.array.ArrayUtils;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.ArrayOperations;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.ByteList;
import org.jruby.util.CodeRangeable;
@@ -69,7 +70,7 @@ public static Object end(DynamicObject matchData, int index) {
return Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(matchData)).getContext().getCoreLibrary().getNilObject();
}

final CodeRangeable sourceWrapped = StringNodes.getCodeRangeable(Layouts.MATCH_DATA.getSource(matchData));
final CodeRangeable sourceWrapped = StringOperations.getCodeRangeable(Layouts.MATCH_DATA.getSource(matchData));
if (!StringSupport.isSingleByteOptimizable(sourceWrapped, sourceWrapped.getByteList().getEncoding())) {
updateCharOffset(matchData);
e = Layouts.MATCH_DATA.getCharOffsets(matchData).end[index];
Original file line number Diff line number Diff line change
@@ -44,10 +44,6 @@
@CoreClass(name = "Method")
public abstract class MethodNodes {

public static DynamicObject createMethod(DynamicObject rubyClass, Object receiver, InternalMethod method) {
return Layouts.METHOD.createMethod(Layouts.CLASS.getInstanceFactory(rubyClass), receiver, method);
}

@CoreMethod(names = { "==", "eql?" }, required = 1)
public abstract static class EqualNode extends CoreMethodArrayArgumentsNode {

@@ -223,7 +219,7 @@ public UnbindNode(RubyContext context, SourceSection sourceSection) {
@Specialization
public DynamicObject unbind(VirtualFrame frame, DynamicObject method) {
final DynamicObject receiverClass = classNode.executeGetClass(frame, Layouts.METHOD.getReceiver(method));
return UnboundMethodNodes.createUnboundMethod(getContext().getCoreLibrary().getUnboundMethodClass(), receiverClass, Layouts.METHOD.getMethod(method));
return Layouts.UNBOUND_METHOD.createUnboundMethod(getContext().getCoreLibrary().getUnboundMethodFactory(), receiverClass, Layouts.METHOD.getMethod(method));
}

}
Original file line number Diff line number Diff line change
@@ -1592,7 +1592,7 @@ public DynamicObject publicInstanceMethod(DynamicObject module, String name) {
throw new RaiseException(getContext().getCoreLibrary().nameErrorPrivateMethod(name, module, this));
}

return UnboundMethodNodes.createUnboundMethod(getContext().getCoreLibrary().getUnboundMethodClass(), module, method);
return Layouts.UNBOUND_METHOD.createUnboundMethod(getContext().getCoreLibrary().getUnboundMethodFactory(), module, method);
}

}
@@ -1697,7 +1697,7 @@ public DynamicObject instanceMethod(DynamicObject module, String name) {
throw new RaiseException(getContext().getCoreLibrary().nameErrorUndefinedMethod(name, module, this));
}

return UnboundMethodNodes.createUnboundMethod(getContext().getCoreLibrary().getUnboundMethodClass(), module, method);
return Layouts.UNBOUND_METHOD.createUnboundMethod(getContext().getCoreLibrary().getUnboundMethodFactory(), module, method);
}

}
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
package org.jruby.truffle.nodes.core;

import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.StringSupport;

@@ -25,7 +26,7 @@ public static boolean isRegexpLiteral(DynamicObject regexp) {
}

public static boolean isValidEncoding(DynamicObject string) {
return StringNodes.scanForCodeRange(string) != StringSupport.CR_BROKEN;
return StringOperations.scanForCodeRange(string) != StringSupport.CR_BROKEN;
}

}
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyCallStack;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.*;

@@ -92,10 +93,10 @@ public static Object matchCommon(DynamicObject regexp, DynamicObject source, boo
final byte[] stringBytes = Layouts.STRING.getByteList(source).bytes();

final ByteList bl = Layouts.REGEXP.getSource(regexp);
final Encoding enc = checkEncoding(regexp, StringNodes.getCodeRangeable(source), true);
final Encoding enc = checkEncoding(regexp, StringOperations.getCodeRangeable(source), true);
final ByteList preprocessed = RegexpSupport.preprocess(Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(regexp)).getContext().getRuntime(), bl, enc, new Encoding[]{null}, RegexpSupport.ErrorMode.RAISE);

final Regex r = new Regex(preprocessed.getUnsafeBytes(), preprocessed.getBegin(), preprocessed.getBegin() + preprocessed.getRealSize(), Layouts.REGEXP.getOptions(regexp).toJoniOptions(), checkEncoding(regexp, StringNodes.getCodeRangeable(source), true));
final Regex r = new Regex(preprocessed.getUnsafeBytes(), preprocessed.getBegin(), preprocessed.getBegin() + preprocessed.getRealSize(), Layouts.REGEXP.getOptions(regexp).toJoniOptions(), checkEncoding(regexp, StringOperations.getCodeRangeable(source), true));
final Matcher matcher = r.matcher(stringBytes);
int range = stringBytes.length;

@@ -319,7 +320,7 @@ public static DynamicObject[] split(DynamicObject regexp, final DynamicObject st

// Suppress trailing empty fields if not using a limit and the supplied limit isn't negative.
if (!useLimit && limit == 0) {
while (! strings.isEmpty() && (StringNodes.length(strings.get(strings.size() - 1)) == 0)) {
while (! strings.isEmpty() && (StringOperations.length(strings.get(strings.size() - 1)) == 0)) {
strings.remove(strings.size() - 1);
}
}
@@ -570,7 +571,7 @@ public QuoteNode(RubyContext context, SourceSection sourceSection) {
@TruffleBoundary
@Specialization(guards = "isRubyString(raw)")
public DynamicObject quoteString(DynamicObject raw) {
boolean isAsciiOnly = Layouts.STRING.getByteList(raw).getEncoding().isAsciiCompatible() && StringNodes.scanForCodeRange(raw) == CR_7BIT;
boolean isAsciiOnly = Layouts.STRING.getByteList(raw).getEncoding().isAsciiCompatible() && StringOperations.scanForCodeRange(raw) == CR_7BIT;
return Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), org.jruby.RubyRegexp.quote19(Layouts.STRING.getByteList(raw), isAsciiOnly), StringSupport.CR_UNKNOWN, null);
}

Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
import com.oracle.truffle.api.object.DynamicObject;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.CodeRangeSupport;
import org.jruby.util.StringSupport;
@@ -21,7 +22,7 @@ public class StringGuards {

public static boolean isSingleByteOptimizable(DynamicObject string) {
assert RubyGuards.isRubyString(string);
return StringSupport.isSingleByteOptimizable(StringNodes.getCodeRangeable(string), Layouts.STRING.getByteList(string).getEncoding());
return StringSupport.isSingleByteOptimizable(StringOperations.getCodeRangeable(string), Layouts.STRING.getByteList(string).getEncoding());
}

public static boolean isAsciiCompatible(DynamicObject string) {
@@ -42,7 +43,7 @@ public static boolean isSingleByte(DynamicObject string) {

public static boolean isValidOr7BitEncoding(DynamicObject string) {
assert RubyGuards.isRubyString(string);
return StringNodes.isCodeRangeValid(string) || CodeRangeSupport.isCodeRangeAsciiOnly(StringNodes.getCodeRangeable(string));
return StringOperations.isCodeRangeValid(string) || CodeRangeSupport.isCodeRangeAsciiOnly(StringOperations.getCodeRangeable(string));
}

public static boolean isFixedWidthEncoding(DynamicObject string) {
@@ -52,6 +53,6 @@ public static boolean isFixedWidthEncoding(DynamicObject string) {

public static boolean isValidUtf8(DynamicObject string) {
assert RubyGuards.isRubyString(string);
return StringNodes.isCodeRangeValid(string) && Layouts.STRING.getByteList(string).getEncoding() instanceof UTF8Encoding;
return StringOperations.isCodeRangeValid(string) && Layouts.STRING.getByteList(string).getEncoding() instanceof UTF8Encoding;
}
}
241 changes: 53 additions & 188 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -35,10 +35,6 @@
@CoreClass(name = "UnboundMethod")
public abstract class UnboundMethodNodes {

public static DynamicObject createUnboundMethod(DynamicObject rubyClass, DynamicObject origin, InternalMethod method) {
return Layouts.UNBOUND_METHOD.createUnboundMethod(Layouts.CLASS.getInstanceFactory(rubyClass), origin, method);
}

@CoreMethod(names = "==", required = 1)
public abstract static class EqualNode extends CoreMethodArrayArgumentsNode {

@@ -100,7 +96,7 @@ public DynamicObject bind(VirtualFrame frame, DynamicObject unboundMethod, Objec
}
}

return MethodNodes.createMethod(getContext().getCoreLibrary().getMethodClass(), object, Layouts.UNBOUND_METHOD.getMethod(unboundMethod));
return Layouts.METHOD.createMethod(getContext().getCoreLibrary().getMethodFactory(), object, Layouts.UNBOUND_METHOD.getMethod(unboundMethod));
}

protected DynamicObject metaClass(VirtualFrame frame, Object object) {
Original file line number Diff line number Diff line change
@@ -56,6 +56,7 @@
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.ArrayOperations;
import org.jruby.truffle.runtime.core.CoreSourceSection;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.methods.Arity;
import org.jruby.truffle.runtime.methods.InternalMethod;
@@ -2507,17 +2508,17 @@ private DynamicObject finishPack(ByteList format, PackResult result) {
final DynamicObject string = Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), new ByteList(result.getOutput(), 0, result.getOutputLength()), StringSupport.CR_UNKNOWN, null);

if (format.length() == 0) {
StringNodes.forceEncoding(string, USASCIIEncoding.INSTANCE);
StringOperations.forceEncoding(string, USASCIIEncoding.INSTANCE);
} else {
switch (result.getEncoding()) {
case DEFAULT:
case ASCII_8BIT:
break;
case US_ASCII:
StringNodes.forceEncoding(string, USASCIIEncoding.INSTANCE);
StringOperations.forceEncoding(string, USASCIIEncoding.INSTANCE);
break;
case UTF_8:
StringNodes.forceEncoding(string, UTF8Encoding.INSTANCE);
StringOperations.forceEncoding(string, UTF8Encoding.INSTANCE);
break;
default:
throw new UnsupportedOperationException();
Original file line number Diff line number Diff line change
@@ -16,9 +16,9 @@
import org.jruby.truffle.nodes.core.CoreClass;
import org.jruby.truffle.nodes.core.CoreMethod;
import org.jruby.truffle.nodes.core.CoreMethodArrayArgumentsNode;
import org.jruby.truffle.nodes.core.StringNodes;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.ByteList;

@@ -111,7 +111,7 @@ public Object getByte(DynamicObject bytes, DynamicObject pattern, int start, int
if (index == -1) {
return nil();
} else {
return start + index + StringNodes.length(pattern);
return start + index + StringOperations.length(pattern);
}
}

Original file line number Diff line number Diff line change
@@ -23,12 +23,12 @@
import org.jcodings.transcode.EConvResult;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.core.EncodingConverterNodes;
import org.jruby.truffle.nodes.core.StringNodes;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.ByteList;
import org.jruby.util.StringSupport;
@@ -79,8 +79,8 @@ public Object encodingConverterPrimitiveConvert(DynamicObject encodingConverter,

// Taken from org.jruby.RubyConverter#primitive_convert.

StringNodes.modify(source);
StringNodes.clearCodeRange(source);
StringOperations.modify(source);
StringOperations.clearCodeRange(source);

return primitiveConvertHelper(encodingConverter, Layouts.STRING.getByteList(source), source, target, offset, size, options);
}
@@ -92,8 +92,8 @@ private Object primitiveConvertHelper(DynamicObject encodingConverter, ByteList

final boolean nonNullSource = source != nil();

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

final ByteList outBytes = Layouts.STRING.getByteList(target);

Original file line number Diff line number Diff line change
@@ -47,12 +47,12 @@
import jnr.constants.platform.Fcntl;
import jnr.ffi.Pointer;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.core.StringNodes;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.ArrayOperations;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.sockets.FDSet;
import org.jruby.truffle.runtime.sockets.FDSetFactory;
@@ -151,7 +151,7 @@ public IOOpenPrimitiveNode(RubyContext context, SourceSection sourceSection) {

@Specialization(guards = "isRubyString(path)")
public int open(DynamicObject path, int mode, int permission) {
return posix().open(StringNodes.getString(path), mode, permission);
return posix().open(StringOperations.getString(path), mode, permission);
}

}
@@ -171,7 +171,7 @@ public int truncate(DynamicObject path, int length) {

@Specialization(guards = "isRubyString(path)")
public int truncate(DynamicObject path, long length) {
final int result = posix().truncate(StringNodes.getString(path), length);
final int result = posix().truncate(StringOperations.getString(path), length);
if (result == -1) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().errnoError(posix().errno(), this));
@@ -356,7 +356,7 @@ public IOReopenPathPrimitiveNode(RubyContext context, SourceSection sourceSectio
@TruffleBoundary
public void performReopenPath(DynamicObject file, DynamicObject path, int mode) {
int fd = Layouts.IO.getDescriptor(file);
final String pathString = StringNodes.getString(path);
final String pathString = StringOperations.getString(path);

int otherFd = posix().open(pathString, mode, 666);
if (otherFd < 0) {
Original file line number Diff line number Diff line change
@@ -20,9 +20,9 @@
import org.joni.Regex;
import org.jruby.truffle.nodes.core.RegexpGuards;
import org.jruby.truffle.nodes.core.RegexpNodes;
import org.jruby.truffle.nodes.core.StringNodes;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.ByteList;
import org.jruby.util.RegexpSupport;
@@ -137,10 +137,10 @@ public Object searchRegionInvalidEncoding(DynamicObject regexp, DynamicObject st
public Object searchRegion(DynamicObject regexp, DynamicObject string, int start, int end, boolean forward) {
final ByteList stringBl = Layouts.STRING.getByteList(string);
final ByteList bl = Layouts.REGEXP.getSource(regexp);
final Encoding enc = RegexpNodes.checkEncoding(regexp, StringNodes.getCodeRangeable(string), true);
final Encoding enc = RegexpNodes.checkEncoding(regexp, StringOperations.getCodeRangeable(string), true);
final ByteList preprocessed = RegexpSupport.preprocess(getContext().getRuntime(), bl, enc, new Encoding[]{null}, RegexpSupport.ErrorMode.RAISE);

final Regex r = new Regex(preprocessed.getUnsafeBytes(), preprocessed.getBegin(), preprocessed.getBegin() + preprocessed.getRealSize(), Layouts.REGEXP.getRegex(regexp).getOptions(), RegexpNodes.checkEncoding(regexp, StringNodes.getCodeRangeable(string), true));
final Regex r = new Regex(preprocessed.getUnsafeBytes(), preprocessed.getBegin(), preprocessed.getBegin() + preprocessed.getRealSize(), Layouts.REGEXP.getRegex(regexp).getOptions(), RegexpNodes.checkEncoding(regexp, StringOperations.getCodeRangeable(string), true));
final Matcher matcher = r.matcher(stringBl.getUnsafeBytes(), stringBl.begin(), stringBl.begin() + stringBl.realSize());

if (forward) {
Original file line number Diff line number Diff line change
@@ -76,6 +76,7 @@
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.ByteList;
import org.jruby.util.ConvertBytes;
@@ -139,7 +140,7 @@ public DynamicObject stringAwkSplit(DynamicObject string, int lim) {
boolean skip = true;

int e = 0, b = 0;
final boolean singlebyte = StringSupport.isSingleByteOptimizable(StringNodes.getCodeRangeable(string), enc);
final boolean singlebyte = StringSupport.isSingleByteOptimizable(StringOperations.getCodeRangeable(string), enc);
while (p < end) {
final int c;
if (singlebyte) {
@@ -228,7 +229,7 @@ public Object stringByteSubstring(DynamicObject string, int index, int length) {
return nil();
}

final int normalizedIndex = StringNodes.normalizeIndex(string, index);
final int normalizedIndex = StringOperations.normalizeIndex(string, index);

if (normalizedIndex < 0 || normalizedIndex > bytes.length()) {
return nil();
@@ -448,7 +449,7 @@ public boolean stringEqual(DynamicObject string, DynamicObject other) {
final ByteList b = Layouts.STRING.getByteList(other);

if (incompatibleEncodingProfile.profile((a.getEncoding() != b.getEncoding()) &&
(org.jruby.RubyEncoding.areCompatible(StringNodes.getCodeRangeable(string), StringNodes.getCodeRangeable(other)) == null))) {
(org.jruby.RubyEncoding.areCompatible(StringOperations.getCodeRangeable(string), StringOperations.getCodeRangeable(other)) == null))) {
return false;
}

@@ -624,8 +625,8 @@ public Object stringIndex(VirtualFrame frame, DynamicObject string, DynamicObjec
// Rubinius will pass in a byte index for the `start` value, but StringSupport.index requires a character index.
final int charIndex = byteIndexToCharIndexNode.executeStringBytCharacterIndex(frame, string, start, 0);

final int index = StringSupport.index(StringNodes.getCodeRangeable(string),
StringNodes.getCodeRangeable(pattern),
final int index = StringSupport.index(StringOperations.getCodeRangeable(string),
StringOperations.getCodeRangeable(pattern),
charIndex, Layouts.STRING.getByteList(string).getEncoding());

if (index == -1) {
@@ -736,7 +737,7 @@ public Object stringCharacterIndex(DynamicObject string, DynamicObject pattern,
final byte[] stringBytes = Layouts.STRING.getByteList(string).getUnsafeBytes();
final byte[] patternBytes = Layouts.STRING.getByteList(pattern).getUnsafeBytes();

if (StringSupport.isSingleByteOptimizable(StringNodes.getCodeRangeable(string), Layouts.STRING.getByteList(string).getEncoding())) {
if (StringSupport.isSingleByteOptimizable(StringOperations.getCodeRangeable(string), Layouts.STRING.getByteList(string).getEncoding())) {
for(s = p += offset, ss = pp; p < e; s = ++p) {
if (stringBytes[p] != patternBytes[pp]) continue;

@@ -866,11 +867,11 @@ public Object stringByteIndex(DynamicObject string, DynamicObject pattern, int o

if (match_size == 0) return offset;

if (StringNodes.scanForCodeRange(string) == StringSupport.CR_BROKEN) {
if (StringOperations.scanForCodeRange(string) == StringSupport.CR_BROKEN) {
return nil();
}

final Encoding encoding = StringNodes.checkEncoding(string, StringNodes.getCodeRangeable(pattern), this);
final Encoding encoding = StringOperations.checkEncoding(string, StringOperations.getCodeRangeable(pattern), this);
int p = Layouts.STRING.getByteList(string).getBegin();
final int e = p + Layouts.STRING.getByteList(string).getRealSize();
int pp = Layouts.STRING.getByteList(pattern).getBegin();
@@ -1227,17 +1228,17 @@ public Object stringSubstring(DynamicObject string, int beg, int len) {
}
return makeSubstring(string, p - s, e - p);
} else {
beg += StringSupport.strLengthFromRubyString(StringNodes.getCodeRangeable(string), enc);
beg += StringSupport.strLengthFromRubyString(StringOperations.getCodeRangeable(string), enc);
if (beg < 0) {
return nil();
}
}
} else if (beg > 0 && beg > StringSupport.strLengthFromRubyString(StringNodes.getCodeRangeable(string), enc)) {
} else if (beg > 0 && beg > StringSupport.strLengthFromRubyString(StringOperations.getCodeRangeable(string), enc)) {
return nil();
}
if (len == 0) {
p = 0;
} else if (StringNodes.isCodeRangeValid(string) && enc instanceof UTF8Encoding) {
} else if (StringOperations.isCodeRangeValid(string) && enc instanceof UTF8Encoding) {
p = StringSupport.utf8Nth(bytes, s, end, beg);
len = StringSupport.utf8Offset(bytes, p, end, len);
} else if (enc.isFixedWidth()) {
Original file line number Diff line number Diff line change
@@ -153,7 +153,9 @@ public class CoreLibrary {
private final DynamicObject bigDecimalClass;
private final DynamicObject encodingCompatibilityErrorClass;
private final DynamicObject methodClass;
private final DynamicObjectFactory methodFactory;
private final DynamicObject unboundMethodClass;
private final DynamicObjectFactory unboundMethodFactory;
private final DynamicObject byteArrayClass;
private final DynamicObject fiberErrorClass;
private final DynamicObject threadErrorClass;
@@ -361,7 +363,8 @@ public CoreLibrary(RubyContext context) {
matchDataClass = defineClass("MatchData");
Layouts.CLASS.setInstanceFactoryUnsafe(matchDataClass, Layouts.MATCH_DATA.createMatchDataShape(matchDataClass, matchDataClass));
methodClass = defineClass("Method");
Layouts.CLASS.setInstanceFactoryUnsafe(methodClass, Layouts.METHOD.createMethodShape(methodClass, methodClass));
methodFactory = Layouts.METHOD.createMethodShape(methodClass, methodClass);
Layouts.CLASS.setInstanceFactoryUnsafe(methodClass, methodFactory);
final DynamicObject mutexClass = defineClass("Mutex");
Layouts.CLASS.setInstanceFactoryUnsafe(mutexClass, Layouts.MUTEX.createMutexShape(mutexClass, mutexClass));
nilClass = defineClass("NilClass");
@@ -393,7 +396,8 @@ public CoreLibrary(RubyContext context) {
Layouts.CLASS.setInstanceFactoryUnsafe(timeClass, Layouts.TIME.createTimeShape(timeClass, timeClass));
trueClass = defineClass("TrueClass");
unboundMethodClass = defineClass("UnboundMethod");
Layouts.CLASS.setInstanceFactoryUnsafe(unboundMethodClass, Layouts.UNBOUND_METHOD.createUnboundMethodShape(unboundMethodClass, unboundMethodClass));
unboundMethodFactory = Layouts.UNBOUND_METHOD.createUnboundMethodShape(unboundMethodClass, unboundMethodClass);
Layouts.CLASS.setInstanceFactoryUnsafe(unboundMethodClass, unboundMethodFactory);
final DynamicObject ioClass = defineClass("IO");
Layouts.CLASS.setInstanceFactoryUnsafe(ioClass, Layouts.IO.createIOShape(ioClass, ioClass));
internalBufferClass = defineClass(ioClass, objectClass, "InternalBuffer");
@@ -1477,10 +1481,18 @@ public DynamicObject getUnboundMethodClass() {
return unboundMethodClass;
}

public DynamicObjectFactory getUnboundMethodFactory() {
return unboundMethodFactory;
}

public DynamicObject getMethodClass() {
return methodClass;
}

public DynamicObjectFactory getMethodFactory() {
return methodFactory;
}

public DynamicObject getComplexClass() {
return complexClass;
}
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@
import com.oracle.truffle.api.object.DynamicObject;
import org.jcodings.Encoding;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.core.StringNodes;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.ByteList;
import org.jruby.util.CodeRangeable;
@@ -33,12 +32,12 @@ public int getCodeRange() {

@Override
public int scanForCodeRange() {
return StringNodes.scanForCodeRange(string);
return StringOperations.scanForCodeRange(string);
}

@Override
public boolean isCodeRangeValid() {
return StringNodes.isCodeRangeValid(string);
return StringOperations.isCodeRangeValid(string);
}

@Override
@@ -48,32 +47,32 @@ public final void setCodeRange(int newCodeRange) {

@Override
public final void clearCodeRange() {
StringNodes.clearCodeRange(string);
StringOperations.clearCodeRange(string);
}

@Override
public final void keepCodeRange() {
StringNodes.keepCodeRange(string);
StringOperations.keepCodeRange(string);
}

@Override
public final void modify() {
StringNodes.modify(string);
StringOperations.modify(string);
}

@Override
public final void modify(int length) {
StringNodes.modify(string, length);
StringOperations.modify(string, length);
}

@Override
public final void modifyAndKeepCodeRange() {
StringNodes.modifyAndKeepCodeRange(string);
StringOperations.modifyAndKeepCodeRange(string);
}

@Override
public Encoding checkEncoding(CodeRangeable other) {
return StringNodes.checkEncoding(string, other);
return StringOperations.checkEncoding(string, other);
}

@Override
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
* Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*
* Contains code modified from JRuby's RubyString.java
*
* Copyright (C) 2001 Alan Moore <alan_moore@gmx.net>
* Copyright (C) 2001-2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
* Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
* Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
* Copyright (C) 2002-2006 Thomas E Enebo <enebo@acm.org>
* Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
* Copyright (C) 2004 David Corbin <dcorbin@users.sourceforge.net>
* Copyright (C) 2005 Tim Azzopardi <tim@tigerfive.com>
* Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
* Copyright (C) 2006 Ola Bini <ola@ologix.com>
* Copyright (C) 2007 Nick Sieger <nicksieger@gmail.com>
*
*/
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;
import org.jcodings.Encoding;
import org.jruby.runtime.Helpers;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.ByteList;
import org.jruby.util.CodeRangeable;
import org.jruby.util.StringSupport;
import org.jruby.util.io.EncodingUtils;

public abstract class StringOperations {

// Since ByteList.toString does not decode properly
@CompilerDirectives.TruffleBoundary
public static String getString(DynamicObject string) {
return Helpers.decodeByteList(Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(string)).getContext().getRuntime(), Layouts.STRING.getByteList(string));
}

public static StringCodeRangeableWrapper getCodeRangeable(DynamicObject string) {
StringCodeRangeableWrapper wrapper = Layouts.STRING.getCodeRangeableWrapper(string);

if (wrapper == null) {
wrapper = new StringCodeRangeableWrapper(string);
Layouts.STRING.setCodeRangeableWrapper(string, wrapper);
}

return wrapper;
}

@CompilerDirectives.TruffleBoundary
public static int scanForCodeRange(DynamicObject string) {
int cr = Layouts.STRING.getCodeRange(string);

if (cr == StringSupport.CR_UNKNOWN) {
cr = slowCodeRangeScan(string);
Layouts.STRING.setCodeRange(string, cr);
}

return cr;
}

public static boolean isCodeRangeValid(DynamicObject string) {
return Layouts.STRING.getCodeRange(string) == StringSupport.CR_VALID;
}

public static void clearCodeRange(DynamicObject string) {
Layouts.STRING.setCodeRange(string, StringSupport.CR_UNKNOWN);
}

public static void keepCodeRange(DynamicObject string) {
if (Layouts.STRING.getCodeRange(string) == StringSupport.CR_BROKEN) {
clearCodeRange(string);
}
}

public static void modify(DynamicObject string) {
// TODO (nirvdrum 16-Feb-15): This should check whether the underlying ByteList is being shared and copy if necessary.
Layouts.STRING.getByteList(string).invalidate();
}

public static void modify(DynamicObject string, int length) {
// TODO (nirvdrum Jan. 13, 2015): This should check whether the underlying ByteList is being shared and copy if necessary.
Layouts.STRING.getByteList(string).ensure(length);
Layouts.STRING.getByteList(string).invalidate();
}

public static void modifyAndKeepCodeRange(DynamicObject string) {
modify(string);
keepCodeRange(string);
}

@CompilerDirectives.TruffleBoundary
public static Encoding checkEncoding(DynamicObject string, CodeRangeable other) {
final Encoding encoding = StringSupport.areCompatible(getCodeRangeable(string), other);

// TODO (nirvdrum 23-Mar-15) We need to raise a proper Truffle+JRuby exception here, rather than a non-Truffle JRuby exception.
if (encoding == null) {
throw Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(string)).getContext().getRuntime().newEncodingCompatibilityError(
String.format("incompatible character encodings: %s and %s",
Layouts.STRING.getByteList(string).getEncoding().toString(),
other.getByteList().getEncoding().toString()));
}

return encoding;
}

@CompilerDirectives.TruffleBoundary
private static int slowCodeRangeScan(DynamicObject string) {
final ByteList byteList = Layouts.STRING.getByteList(string);
return StringSupport.codeRangeScan(byteList.getEncoding(), byteList);
}

public static void forceEncoding(DynamicObject string, Encoding encoding) {
modify(string);
clearCodeRange(string);
StringSupport.associateEncoding(getCodeRangeable(string), encoding);
clearCodeRange(string);
}

public static int length(DynamicObject string) {
if (CompilerDirectives.injectBranchProbability(
CompilerDirectives.FASTPATH_PROBABILITY,
StringSupport.isSingleByteOptimizable(getCodeRangeable(string), Layouts.STRING.getByteList(string).getEncoding()))) {

return Layouts.STRING.getByteList(string).getRealSize();

} else {
return StringSupport.strLengthFromRubyString(getCodeRangeable(string));
}
}

public static int normalizeIndex(int length, int index) {
return ArrayOperations.normalizeIndex(length, index);
}

public static int normalizeIndex(DynamicObject rubyString, int index) {
return normalizeIndex(length(rubyString), index);
}

public static int clampExclusiveIndex(DynamicObject string, int index) {
assert RubyGuards.isRubyString(string);
return ArrayOperations.clampExclusiveIndex(Layouts.STRING.getByteList(string).length(), index);
}

@CompilerDirectives.TruffleBoundary
public static Encoding checkEncoding(DynamicObject string, CodeRangeable other, Node node) {
final Encoding encoding = StringSupport.areCompatible(getCodeRangeable(string), other);

if (encoding == null) {
throw new RaiseException(
Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(string)).getContext().getCoreLibrary().encodingCompatibilityErrorIncompatible(
Layouts.STRING.getByteList(string).getEncoding().toString(),
other.getByteList().getEncoding().toString(),
node)
);
}

return encoding;
}

public static boolean singleByteOptimizable(DynamicObject string) {
return StringSupport.isSingleByteOptimizable(getCodeRangeable(string), EncodingUtils.STR_ENC_GET(getCodeRangeable(string)));
}

}

0 comments on commit ef8d772

Please sign in to comment.