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: 4c7963a2bd0a
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 006902ba345f
Choose a head ref
  • 12 commits
  • 13 files changed
  • 1 contributor

Commits on Nov 3, 2016

  1. Copy the full SHA
    92ec337 View commit details
  2. Copy the full SHA
    c377d70 View commit details
  3. Copy the full SHA
    96430d6 View commit details
  4. Copy the full SHA
    698553d View commit details
  5. Copy the full SHA
    0a84af9 View commit details
  6. Copy the full SHA
    498664a View commit details

Commits on Nov 4, 2016

  1. Copy the full SHA
    c4a9cdd View commit details
  2. Copy the full SHA
    eac97e8 View commit details
  3. Copy the full SHA
    3723749 View commit details
  4. Copy the full SHA
    0cde4fd View commit details
  5. Copy the full SHA
    d477f0a View commit details
  6. Copy the full SHA
    006902b View commit details
Original file line number Diff line number Diff line change
@@ -97,7 +97,7 @@ public DynamicObject defaultInternal(VirtualFrame frame, Object encoding) {
}

final DynamicObject encodingName = toStrNode.executeToStr(frame, encoding);
getContext().getJRubyRuntime().setDefaultInternalEncoding(EncodingOperations.getEncoding(getContext().getEncodingManager().getRubyEncoding(encodingName.toString())));
getContext().getJRubyInterop().setDefaultInternalEncoding(EncodingOperations.getEncoding(getContext().getEncodingManager().getRubyEncoding(encodingName.toString())));

return encodingName;
}
Original file line number Diff line number Diff line change
@@ -1341,7 +1341,7 @@ public Object powBignum(long a, DynamicObject b) {
return null; // Primitive failure
}

getContext().getJRubyRuntime().getWarnings().warn("in a**b, b may be too big");
getContext().getJRubyInterop().warn("in a**b, b may be too big");
// b >= 2**63 && (a > 1 || a < -1) => larger than largest double
// MRI behavior/bug: always positive Infinity even if a negative and b odd (likely due to libc pow(a, +inf)).
return Double.POSITIVE_INFINITY;
Original file line number Diff line number Diff line change
@@ -104,7 +104,7 @@ public static abstract class RandomizerGenSeedPrimitiveNode extends PrimitiveArr
@TruffleBoundary
@Specialization
public DynamicObject randomizerGenSeed(DynamicObject randomizerClass) {
final BigInteger seed = RubyRandom.randomSeedBigInteger(getContext().getJRubyRuntime().getRandom());
final BigInteger seed = RubyRandom.randomSeedBigInteger(getContext().getJRubyInterop().getRandom());
return createBignum(seed);
}
}
270 changes: 262 additions & 8 deletions truffle/src/main/java/org/jruby/truffle/core/string/StringNodes.java
Original file line number Diff line number Diff line change
@@ -7,8 +7,9 @@
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*
* Some of the code in this class is transposed from org.jruby.RubyString,
* licensed under the same EPL1.0/GPL 2.0/LGPL 2.1 used throughout.
* Some of the code in this class is transposed from org.jruby.RubyString
* and String Support and licensed under the same EPL1.0/GPL 2.0/LGPL 2.1
* used throughout.
*
* Copyright (C) 2001 Alan Moore <alan_moore@gmx.net>
* Copyright (C) 2001-2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
@@ -83,7 +84,6 @@
import org.jcodings.specific.ASCIIEncoding;
import org.jcodings.specific.USASCIIEncoding;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.RubyString;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.builtins.CoreClass;
@@ -140,6 +140,8 @@
import org.jruby.truffle.language.objects.AllocateObjectNode;
import org.jruby.truffle.language.objects.IsFrozenNode;
import org.jruby.truffle.language.objects.IsFrozenNodeGen;
import org.jruby.truffle.language.objects.IsTaintedNode;
import org.jruby.truffle.language.objects.IsTaintedNodeGen;
import org.jruby.truffle.language.objects.TaintNode;
import org.jruby.truffle.language.objects.TaintNodeGen;
import org.jruby.truffle.platform.posix.TrufflePosix;
@@ -150,6 +152,7 @@
import org.jruby.util.StringSupport;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -1761,7 +1764,154 @@ public DynamicObject dump(DynamicObject string) {
@TruffleBoundary
private ByteList dumpCommon(DynamicObject string) {
assert RubyGuards.isRubyString(string);
return StringSupport.dumpCommon(getContext().getJRubyRuntime(), StringOperations.getByteListReadOnly(string));
return dumpCommon(StringOperations.getByteListReadOnly(string));
}

private ByteList dumpCommon(ByteList byteList) {
ByteList buf = null;
Encoding enc = byteList.getEncoding();

int p = byteList.getBegin();
int end = p + byteList.getRealSize();
byte[]bytes = byteList.getUnsafeBytes();

int len = 2;
while (p < end) {
int c = bytes[p++] & 0xff;

switch (c) {
case '"':case '\\':case '\n':case '\r':case '\t':case '\f':
case '\013': case '\010': case '\007': case '\033':
len += 2;
break;
case '#':
len += isEVStr(bytes, p, end) ? 2 : 1;
break;
default:
if (ASCIIEncoding.INSTANCE.isPrint(c)) {
len++;
} else {
if (enc.isUTF8()) {
int n = preciseLength(enc, bytes, p - 1, end) - 1;
if (n > 0) {
if (buf == null) buf = new ByteList();
int cc = codePointX(enc, bytes, p - 1, end);
buf.append(String.format("%x", cc).getBytes(StandardCharsets.US_ASCII));
len += buf.getRealSize() + 4;
buf.setRealSize(0);
p += n;
break;
}
}
len += 4;
}
break;
}
}

if (!enc.isAsciiCompatible()) {
len += ".force_encoding(\"".length() + enc.getName().length + "\")".length();
}

ByteList outBytes = new ByteList(len);
byte out[] = outBytes.getUnsafeBytes();
int q = 0;
p = byteList.getBegin();
end = p + byteList.getRealSize();

out[q++] = '"';
while (p < end) {
int c = bytes[p++] & 0xff;
if (c == '"' || c == '\\') {
out[q++] = '\\';
out[q++] = (byte)c;
} else if (c == '#') {
if (isEVStr(bytes, p, end)) out[q++] = '\\';
out[q++] = '#';
} else if (c == '\n') {
out[q++] = '\\';
out[q++] = 'n';
} else if (c == '\r') {
out[q++] = '\\';
out[q++] = 'r';
} else if (c == '\t') {
out[q++] = '\\';
out[q++] = 't';
} else if (c == '\f') {
out[q++] = '\\';
out[q++] = 'f';
} else if (c == '\013') {
out[q++] = '\\';
out[q++] = 'v';
} else if (c == '\010') {
out[q++] = '\\';
out[q++] = 'b';
} else if (c == '\007') {
out[q++] = '\\';
out[q++] = 'a';
} else if (c == '\033') {
out[q++] = '\\';
out[q++] = 'e';
} else if (ASCIIEncoding.INSTANCE.isPrint(c)) {
out[q++] = (byte)c;
} else {
out[q++] = '\\';
if (enc.isUTF8()) {
int n = preciseLength(enc, bytes, p - 1, end) - 1;
if (n > 0) {
int cc = codePointX(enc, bytes, p - 1, end);
p += n;
outBytes.setRealSize(q);
outBytes.append(String.format("u{%x}", cc).getBytes(StandardCharsets.US_ASCII));
q = outBytes.getRealSize();
continue;
}
}
outBytes.setRealSize(q);
outBytes.append(String.format("x%02X", c).getBytes(StandardCharsets.US_ASCII));
q = outBytes.getRealSize();
}
}
out[q++] = '"';
outBytes.setRealSize(q);
assert out == outBytes.getUnsafeBytes(); // must not reallocate

return outBytes;
}

private static boolean isEVStr(byte[] bytes, int p, int end) {
return p < end ? isEVStr(bytes[p] & 0xff) : false;
}

private static boolean isEVStr(int c) {
return c == '$' || c == '@' || c == '{';
}

// rb_enc_precise_mbclen
private static int preciseLength(Encoding enc, byte[]bytes, int p, int end) {
if (p >= end) return -1 - (1);
int n = enc.length(bytes, p, end);
if (n > end - p) return MBCLEN_NEEDMORE(n - (end - p));
return n;
}

private static int MBCLEN_NEEDMORE(int n) {
return -1 - n;
}

private static int codePoint(Encoding enc, byte[] bytes, int p, int end) {
if (p >= end) throw new IllegalArgumentException("empty string");
int cl = preciseLength(enc, bytes, p, end);
if (cl <= 0) throw new IllegalArgumentException("invalid byte sequence in " + enc);
return enc.mbcToCode(bytes, p, end);
}

private int codePointX(Encoding enc, byte[] bytes, int p, int end) {
try {
return codePoint(enc, bytes, p, end);
} catch (IllegalArgumentException e) {
throw new RaiseException(getContext().getCoreExceptions().argumentError(e.getMessage(), this));
}
}
}

@@ -3107,12 +3257,116 @@ protected static boolean hasRawBytes(DynamicObject string) {
@Primitive(name = "string_escape", needsSelf = false)
public abstract static class StringEscapePrimitiveNode extends PrimitiveArrayArgumentsNode {

@TruffleBoundary
@Child private IsTaintedNode isTaintedNode = IsTaintedNodeGen.create(null, null, null);
@Child private TaintNode taintNode = TaintNodeGen.create(null, null, null);
private final ConditionProfile taintedProfile = ConditionProfile.createBinaryProfile();

@Specialization
public DynamicObject string_escape(DynamicObject string) {
final org.jruby.RubyString rubyString = new RubyString(getContext().getJRubyRuntime(), getContext().getJRubyRuntime().getString(),
StringOperations.getByteListReadOnly(string));
return createString(((RubyString) org.jruby.RubyString.rbStrEscape(getContext().getJRubyRuntime().getCurrentContext(), rubyString)).getByteList());
final DynamicObject result = create7BitString(rbStrEscape(StringOperations.getByteListReadOnly(string)), USASCIIEncoding.INSTANCE);

if (taintedProfile.profile(isTaintedNode.isTainted(string))) {
taintNode.executeTaint(result);
}

return result;
}

// MRI: rb_str_escape
@TruffleBoundary
private static ByteList rbStrEscape(ByteList str) {
Encoding enc = str.getEncoding();
ByteList strBL = str;
byte[] pBytes = strBL.unsafeBytes();
int p = strBL.begin();
int pend = p + strBL.realSize();
int prev = p;
ByteList result = new ByteList();
boolean unicode_p = enc.isUnicode();
boolean asciicompat = enc.isAsciiCompatible();

while (p < pend) {
int c, cc;
int n = enc.length(pBytes, p, pend);
if (!MBCLEN_CHARFOUND_P(n)) {
if (p > prev) result.append(pBytes, prev, p - prev);
n = enc.minLength();
if (pend < p + n)
n = (int)(pend - p);
while ((n--) > 0) {
result.append(String.format("\\x%02X", (long) (pBytes[p] & 0377)).getBytes(StandardCharsets.US_ASCII));
prev = ++p;
}
continue;
}
n = MBCLEN_CHARFOUND_LEN(n);
c = enc.mbcToCode(pBytes, p, pend);
p += n;
switch (c) {
case '\n': cc = 'n'; break;
case '\r': cc = 'r'; break;
case '\t': cc = 't'; break;
case '\f': cc = 'f'; break;
case '\013': cc = 'v'; break;
case '\010': cc = 'b'; break;
case '\007': cc = 'a'; break;
case 033: cc = 'e'; break;
default: cc = 0; break;
}
if (cc != 0) {
if (p - n > prev) result.append(pBytes, prev, p - n - prev);
result.append('\\');
result.append((byte) cc);
prev = p;
}
else if (asciicompat && Encoding.isAscii(c) && (c < 0x7F && c > 31 /*ISPRINT(c)*/)) {
}
else {
if (p - n > prev) result.append(pBytes, prev, p - n - prev);

if (unicode_p && (c & 0xFFFFFFFFL) < 0x7F && Encoding.isAscii(c) && ASCIIEncoding.INSTANCE.isPrint(c)) {
result.append(String.format("%c", (char) (c & 0xFFFFFFFFL)).getBytes(StandardCharsets.US_ASCII));
} else {
result.append(String.format(escapedCharFormat(c, unicode_p), (long) (c & 0xFFFFFFFFL)).getBytes(StandardCharsets.US_ASCII));
}

prev = p;
}
}
if (p > prev) result.append(pBytes, prev, p - prev);

return result;
}

private static int MBCLEN_CHARFOUND_LEN(int r) {
return r;
}

// MBCLEN_CHARFOUND_P, ONIGENC_MBCLEN_CHARFOUND_P
private static boolean MBCLEN_CHARFOUND_P(int r) {
return 0 < r;
}

private static String escapedCharFormat(int c, boolean isUnicode) {
String format;
// c comparisons must be unsigned 32-bit
if (isUnicode) {

if ((c & 0xFFFFFFFFL) < 0x7F && Encoding.isAscii(c) && ASCIIEncoding.INSTANCE.isPrint(c)) {
throw new UnsupportedOperationException();
} else if (c < 0x10000) {
format = "\\u%04X";
} else {
format = "\\u{%X}";
}
} else {
if ((c & 0xFFFFFFFFL) < 0x100) {
format = "\\x%02X";
} else {
format = "\\x{%X}";
}
}
return format;
}

}
Loading