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

Commits on Jan 14, 2015

  1. Copy the full SHA
    253cd0e View commit details
  2. Replaced usages of RubyString#isCodeRangeAsciiOnly with CodeRangeSupp…

    …ort.isCodeRangeAsciiOnly.
    nirvdrum committed Jan 14, 2015
    Copy the full SHA
    e6b0dc9 View commit details
  3. Copy the full SHA
    0e1f54a View commit details
  4. Copy the full SHA
    87d9fbb View commit details
  5. Copy the full SHA
    c70a612 View commit details
  6. Work on moving the core logic of RubyString#replaceInternal to String…

    …Support.replaceInternal.
    nirvdrum committed Jan 14, 2015
    Copy the full SHA
    a80f883 View commit details
  7. Copy the full SHA
    2a65f1a View commit details
  8. Copy the full SHA
    b6708a3 View commit details
  9. Copy the full SHA
    09bad19 View commit details
  10. [Truffle] Fixed an issue with String#[]= and an inclusive Range index…

    … and a negative end.
    
    We can't just increment the end value if it's negative because it messes up the byte range.  Instead we need to calculate the byte range with the current end value and then increment it to account for the inclusive range.
    nirvdrum committed Jan 14, 2015
    Copy the full SHA
    e37a347 View commit details
  11. Copy the full SHA
    85f99ff View commit details
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyEncoding.java
Original file line number Diff line number Diff line change
@@ -166,7 +166,7 @@ public static Encoding areCompatible(IRubyObject obj1, IRubyObject obj2) {
}

// last block in rb_enc_compatible
static Encoding areCompatible(Encoding enc1, int cr1, Encoding enc2, int cr2) {
public static Encoding areCompatible(Encoding enc1, int cr1, Encoding enc2, int cr2) {
if (cr1 != cr2) {
/* may need to handle ENC_CODERANGE_BROKEN */
if (cr1 == StringSupport.CR_7BIT) return enc2;
72 changes: 19 additions & 53 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -178,10 +178,7 @@ public Encoding getMarshalEncoding() {
}

public void associateEncoding(Encoding enc) {
if (value.getEncoding() != enc) {
if (!isCodeRangeAsciiOnly() || !enc.isAsciiCompatible()) clearCodeRange();
value.setEncoding(enc);
}
StringSupport.associateEncoding(this, enc);
}

public final void setEncodingAndCodeRange(Encoding enc, int cr) {
@@ -204,6 +201,7 @@ public final void setCodeRange(int codeRange) {
flags |= codeRange & CR_MASK;
}

@Override
public final void clearCodeRange() {
flags &= ~CR_MASK;
}
@@ -214,7 +212,7 @@ private void keepCodeRange() {

// ENC_CODERANGE_ASCIIONLY
public final boolean isCodeRangeAsciiOnly() {
return getCodeRange() == CR_7BIT;
return CodeRangeSupport.isCodeRangeAsciiOnly(this);
}

// rb_enc_str_asciionly_p
@@ -231,12 +229,6 @@ public final boolean isCodeRangeBroken() {
return (flags & CR_MASK) == CR_BROKEN;
}

static int codeRangeAnd(int cr1, int cr2) {
if (cr1 == CR_7BIT) return cr2;
if (cr1 == CR_VALID) return cr2 == CR_7BIT ? CR_VALID : cr2;
return CR_UNKNOWN;
}

private void copyCodeRangeForSubstr(RubyString from, Encoding enc) {
int fromCr = from.getCodeRange();
if (fromCr == CR_7BIT) {
@@ -310,10 +302,7 @@ final Encoding isCompatibleWith(EncodingCapable other) {

// rb_enc_check
public final Encoding checkEncoding(RubyString other) {
Encoding enc = isCompatibleWith(other);
if (enc == null) throw getRuntime().newEncodingCompatibilityError("incompatible character encodings: " +
value.getEncoding() + " and " + other.value.getEncoding());
return enc;
return checkEncoding((ByteListHolder) other);
}

final Encoding checkEncoding(EncodingCapable other) {
@@ -323,6 +312,15 @@ final Encoding checkEncoding(EncodingCapable other) {
return enc;
}

@Override
public final Encoding checkEncoding(ByteListHolder other) {
// TODO (nirvdrum 13-Jan-15): This cast is untenable. It's a temporary measure until isCompatibleWith and its call graph are generalized.
Encoding enc = isCompatibleWith((RubyString) other);
if (enc == null) throw getRuntime().newEncodingCompatibilityError("incompatible character encodings: " +
value.getEncoding() + " and " + other.getByteList().getEncoding());
return enc;
}

private Encoding checkDummyEncoding() {
Encoding enc = value.getEncoding();
if (enc.isDummy()) throw getRuntime().newEncodingCompatibilityError(
@@ -1143,7 +1141,7 @@ public IRubyObject op_plus19(ThreadContext context, IRubyObject _str) {
RubyString str = _str.convertToString();
Encoding enc = checkEncoding(str);
RubyString resultStr = newStringNoCopy(context.runtime, addByteLists(value, str.value),
enc, codeRangeAnd(getCodeRange(), str.getCodeRange()));
enc, CodeRangeSupport.codeRangeAnd(getCodeRange(), str.getCodeRange()));
resultStr.infectBy(flags | str.flags);
return resultStr;
}
@@ -2943,47 +2941,15 @@ private IRubyObject multibyteSubstr19(Ruby runtime, Encoding enc, int len, int b

/* rb_str_splice */
private IRubyObject replaceInternal(int beg, int len, RubyString repl) {
int oldLength = value.getRealSize();
if (beg + len >= oldLength) len = oldLength - beg;
ByteList replBytes = repl.value;
int replLength = replBytes.getRealSize();
int newLength = oldLength + replLength - len;
StringSupport.replaceInternal(beg, len, this, repl);

byte[]oldBytes = value.getUnsafeBytes();
int oldBegin = value.getBegin();

modify(newLength);
if (replLength != len) {
System.arraycopy(oldBytes, oldBegin + beg + len, value.getUnsafeBytes(), beg + replLength, oldLength - (beg + len));
}

if (replLength > 0) System.arraycopy(replBytes.getUnsafeBytes(), replBytes.getBegin(), value.getUnsafeBytes(), beg, replLength);
value.setRealSize(newLength);
// TODO (nirvdrum 13-Jan-15) This should be part of the StringSupport definition but a general notion of tainted needs to emerge first.
return infectBy(repl);
}

private void replaceInternal19(int beg, int len, RubyString repl) {
Encoding enc = checkEncoding(repl);
int p = value.getBegin();
int e;
if (singleByteOptimizable()) {
p += beg;
e = p + len;
} else {
int end = p + value.getRealSize();
byte[]bytes = value.getUnsafeBytes();
p = StringSupport.nth(enc, bytes, p, end, beg);
if (p == -1) p = end;
e = StringSupport.nth(enc, bytes, p, end, len);
if (e == -1) e = end;
}

int cr = getCodeRange();
if (cr == CR_BROKEN) clearCodeRange();
replaceInternal(p - value.getBegin(), e - p, repl);
associateEncoding(enc);
cr = codeRangeAnd(cr, repl.getCodeRange());
if (cr != CR_BROKEN) setCodeRange(cr);
StringSupport.replaceInternal19(beg, len, this, repl);
infectBy(repl);
}

/** rb_str_aref, rb_str_aref_m
@@ -3984,7 +3950,7 @@ private IRubyObject justify19(IRubyObject arg0, IRubyObject arg1, int jflag) {
padStr.singleByteOptimizable(),
enc, width, jflag);
if (RubyFixnum.num2int(result.length19()) > RubyFixnum.num2int(length19())) result.infectBy(padStr);
int cr = codeRangeAnd(getCodeRange(), padStr.getCodeRange());
int cr = CodeRangeSupport.codeRangeAnd(getCodeRange(), padStr.getCodeRange());
if (cr != CR_BROKEN) result.setCodeRange(cr);
return result;
}
92 changes: 92 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
Original file line number Diff line number Diff line change
@@ -260,6 +260,98 @@ public Object slice(RubyString string, int start, int length) {

}

@CoreMethod(names = "[]=", required = 2, lowerFixnumParameters = 0)
public abstract static class ElementSetNode extends CoreMethodNode {

public ElementSetNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public ElementSetNode(ElementSetNode prev) {
super(prev);
}

@Specialization
public RubyString elementSet(RubyString string, int index, RubyString replacement) {
notDesignedForCompilation();

if (string.isFrozen()) {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().frozenError("String", this));
}

if (index < 0) {
if (-index > string.length()) {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().indexError(String.format("index %d out of string", index), this));
}

index = index + string.length();

} else if (index > string.length()) {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().indexError(String.format("index %d out of string", index), this));
}

StringSupport.replaceInternal19(index, 1, string, replacement);

return replacement;
}

@Specialization
public RubyString elementSet(RubyString string, RubyRange.IntegerFixnumRange range, RubyString replacement) {
notDesignedForCompilation();

if (string.isFrozen()) {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().frozenError("String", this));
}

int begin = range.getBegin();
int end = range.getEnd();
final int stringLength = string.length();

if (begin < 0) {
begin += stringLength;

if (begin < 0) {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().rangeError(range, this));
}

} else if (begin > stringLength) {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(getContext().getCoreLibrary().rangeError(range, this));
}

if (end > stringLength) {
end = stringLength;
} else if (end < 0) {
end += stringLength;
}

if (! range.doesExcludeEnd()) {
end++;
}

int length = end - begin;

if (length < 0) {
length = 0;
}

StringSupport.replaceInternal19(begin, length, string, replacement);

return replacement;
}
}

@CoreMethod(names = "=~", required = 1)
public abstract static class MatchOperatorNode extends CoreMethodNode {

Original file line number Diff line number Diff line change
@@ -707,6 +707,15 @@ public RubyException rangeError(String type, String value, String range, Node cu
return new RubyException(rangeErrorClass, context.makeString(String.format("%s %s out of range of %s", type, value, range)), RubyCallStack.getBacktrace(currentNode));
}

public RubyException rangeError(RubyRange.IntegerFixnumRange range, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(rangeErrorClass, context.makeString(String.format("%d..%s%d out of range",
range.getBegin(),
range.doesExcludeEnd() ? "." : "",
range.getEnd())),
RubyCallStack.getBacktrace(currentNode));
}

public RubyException internalError(String message, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(context.getCoreLibrary().getRubyTruffleErrorClass(), context.makeString("internal implementation error - " + message), RubyCallStack.getBacktrace(currentNode));
19 changes: 19 additions & 0 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyString.java
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.util.ByteList;
import org.jruby.util.ByteListHolder;
import org.jruby.util.CodeRangeable;
import org.jruby.util.StringSupport;

@@ -188,6 +189,24 @@ public final void setCodeRange(int codeRange) {
// TODO (nirvdrum Jan. 5, 2015): Make this work with the String's real code range, not just a stubbed value.
}

@Override
public final void clearCodeRange() {
// TODO (nirvdrum Jan. 13, 2015): Make this work with the String's real code range, not just a stubbed value.
}

@Override
public final void modify(int length) {
// TODO (nirvdrum Jan. 13, 2015): This should check whether the underlying ByteList is being shared and copy if necessary.
bytes.ensure(length);
bytes.invalidate();
}

@Override
public Encoding checkEncoding(ByteListHolder other) {
// TODO (nirvdrum Jan. 13, 2015): This should check if the encodings are compatible rather than just always succeeding.
return bytes.getEncoding();
}

@Override
public ByteList getByteList() {
return bytes;
35 changes: 35 additions & 0 deletions core/src/main/java/org/jruby/util/ByteListHolder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/***** BEGIN LICENSE BLOCK *****
* Version: EPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/

package org.jruby.util;

import org.jcodings.Encoding;

public interface ByteListHolder {
public ByteList getByteList();
public void modify(int length);
public Encoding checkEncoding(ByteListHolder other);
}
46 changes: 46 additions & 0 deletions core/src/main/java/org/jruby/util/CodeRangeSupport.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/***** BEGIN LICENSE BLOCK *****
* Version: EPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/

package org.jruby.util;

import static org.jruby.util.StringSupport.CR_7BIT;
import static org.jruby.util.StringSupport.CR_UNKNOWN;
import static org.jruby.util.StringSupport.CR_VALID;

public final class CodeRangeSupport {

// ENC_CODERANGE_ASCIIONLY
public static boolean isCodeRangeAsciiOnly(CodeRangeable string) {
return string.getCodeRange() == CR_7BIT;
}

public static int codeRangeAnd(int cr1, int cr2) {
if (cr1 == CR_7BIT) return cr2;
if (cr1 == CR_VALID) return cr2 == CR_7BIT ? CR_VALID : cr2;
return CR_UNKNOWN;
}

}
Loading