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: 06e1efae40fe
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2924c96f595f
Choose a head ref
  • 14 commits
  • 23 files changed
  • 1 contributor

Commits on Jun 10, 2015

  1. Copy the full SHA
    214c49e View commit details
  2. Copy the full SHA
    d97d8e8 View commit details
  3. Copy the full SHA
    3b79d8b View commit details
  4. Copy the full SHA
    db7573b View commit details
  5. Copy the full SHA
    0acfcb3 View commit details
  6. Copy the full SHA
    a1fa5fe View commit details
  7. Copy the full SHA
    c1d6358 View commit details
  8. 1
    Copy the full SHA
    104b8dc View commit details
  9. Copy the full SHA
    8cdb822 View commit details
  10. Copy the full SHA
    fefb762 View commit details
  11. [Truffle] Fixed the 'string_index' primitive.

    Since we weren't converting from byte index to character index, we were using the offset for the index operation on multibyte characters.
    nirvdrum committed Jun 10, 2015
    Copy the full SHA
    1490688 View commit details
  12. Copy the full SHA
    1a3903a View commit details
  13. Copy the full SHA
    6f750f6 View commit details
  14. Copy the full SHA
    2924c96 View commit details
Showing with 313 additions and 230 deletions.
  1. +2 −1 core/src/main/java/org/jruby/RubyMatchData.java
  2. +0 −8 spec/truffle/tags/core/enumerable/chunk_tags.txt
  3. +0 −1 spec/truffle/tags/core/enumerable/cycle_tags.txt
  4. +0 −5 spec/truffle/tags/core/enumerable/slice_before_tags.txt
  5. +0 −3 spec/truffle/tags/core/string/element_set_tags.txt
  6. +0 −3 spec/truffle/tags/core/string/index_tags.txt
  7. +0 −10 spec/truffle/tags/core/string/match_tags.txt
  8. +0 −9 spec/truffle/tags/core/string/rindex_tags.txt
  9. +0 −1 spec/truffle/tags/core/string/rpartition_tags.txt
  10. +0 −10 spec/truffle/tags/core/string/scan_tags.txt
  11. +0 −1 spec/truffle/tags/core/string/split_tags.txt
  12. +3 −2 truffle/src/main/java/org/jruby/truffle/nodes/core/BignumNodes.java
  13. +2 −1 truffle/src/main/java/org/jruby/truffle/nodes/core/FloatNodes.java
  14. +34 −0 truffle/src/main/java/org/jruby/truffle/nodes/core/MatchDataNodes.java
  15. +6 −0 truffle/src/main/java/org/jruby/truffle/nodes/core/RegexpGuards.java
  16. +3 −2 truffle/src/main/java/org/jruby/truffle/nodes/core/StringGuards.java
  17. +4 −123 truffle/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
  18. +6 −5 truffle/src/main/java/org/jruby/truffle/nodes/core/fixnum/FixnumNodes.java
  19. +43 −12 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/RegexpPrimitiveNodes.java
  20. +18 −6 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/StringPrimitiveNodes.java
  21. +187 −15 truffle/src/main/java/org/jruby/truffle/runtime/core/RubyMatchData.java
  22. +5 −2 truffle/src/main/java/org/jruby/truffle/runtime/core/RubyRegexp.java
  23. +0 −10 truffle/src/main/ruby/core/shims.rb
3 changes: 2 additions & 1 deletion core/src/main/java/org/jruby/RubyMatchData.java
Original file line number Diff line number Diff line change
@@ -50,6 +50,7 @@
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.ByteListHolder;
import org.jruby.util.StringSupport;

/**
@@ -398,7 +399,7 @@ private int nameToBackrefNumber(RubyString str) {
return nameToBackrefNumber(getRuntime(), pattern, regs, str);
}

private static int nameToBackrefNumber(Ruby runtime, Regex pattern, Region regs, RubyString str) {
private static int nameToBackrefNumber(Ruby runtime, Regex pattern, Region regs, ByteListHolder str) {
if (pattern == null) {
throw runtime.newIndexError("undefined group name reference: " + str);
}
8 changes: 0 additions & 8 deletions spec/truffle/tags/core/enumerable/chunk_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/cycle_tags.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
fails:Enumerable#cycle passed no argument or nil loops indefinitely
fails:Enumerable#cycle Enumerable with size when no block is given returned Enumerator size should be the result of multiplying the enumerable size by the argument passed
fails:Enumerable#cycle Enumerable with size when no block is given returned Enumerator size should be zero when the argument passed is 0 or less
fails:Enumerable#cycle Enumerable with size when no block is given returned Enumerator size should be Float::INFINITY when no argument is passed
5 changes: 0 additions & 5 deletions spec/truffle/tags/core/enumerable/slice_before_tags.txt

This file was deleted.

3 changes: 0 additions & 3 deletions spec/truffle/tags/core/string/element_set_tags.txt

This file was deleted.

3 changes: 0 additions & 3 deletions spec/truffle/tags/core/string/index_tags.txt

This file was deleted.

10 changes: 0 additions & 10 deletions spec/truffle/tags/core/string/match_tags.txt

This file was deleted.

9 changes: 0 additions & 9 deletions spec/truffle/tags/core/string/rindex_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/string/rpartition_tags.txt

This file was deleted.

10 changes: 0 additions & 10 deletions spec/truffle/tags/core/string/scan_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/string/split_tags.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jcodings.specific.USASCIIEncoding;
import org.jruby.truffle.nodes.cast.BooleanCastNode;
import org.jruby.truffle.nodes.cast.BooleanCastNodeGen;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
@@ -701,7 +702,7 @@ public ToSNode(RubyContext context, SourceSection sourceSection) {
@TruffleBoundary
@Specialization
public RubyBasicObject toS(RubyBasicObject value, NotProvided base) {
return createString(getBigIntegerValue(value).toString());
return createString(getBigIntegerValue(value).toString(), USASCIIEncoding.INSTANCE);
}

@TruffleBoundary
@@ -712,7 +713,7 @@ public RubyBasicObject toS(RubyBasicObject value, int base) {
throw new RaiseException(getContext().getCoreLibrary().argumentErrorInvalidRadix(base, this));
}

return createString(getBigIntegerValue(value).toString(base));
return createString(getBigIntegerValue(value).toString(base), USASCIIEncoding.INSTANCE);
}

}
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jcodings.specific.USASCIIEncoding;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.NotProvided;
@@ -678,7 +679,7 @@ public ToSNode(RubyContext context, SourceSection sourceSection) {
@TruffleBoundary
@Specialization
public RubyBasicObject toS(double value) {
return createString(Double.toString(value));
return createString(Double.toString(value), USASCIIEncoding.INSTANCE);
}

}
Original file line number Diff line number Diff line change
@@ -21,6 +21,8 @@
import org.jruby.truffle.nodes.coerce.ToIntNode;
import org.jruby.truffle.nodes.coerce.ToIntNodeGen;
import org.jruby.truffle.nodes.core.array.ArrayNodes;
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;
@@ -193,6 +195,38 @@ public Object end(RubyMatchData matchData, int index) {
}
}

@RubiniusOnly
@CoreMethod(names = "full")
public abstract static class FullNode extends CoreMethodArrayArgumentsNode {

@Child private CallDispatchHeadNode newTupleNode;

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

@Specialization
public Object full(VirtualFrame frame, RubyMatchData matchData) {
if (matchData.getFullTuple() != null) {
return matchData.getFullTuple();
}

if (newTupleNode == null) {
CompilerDirectives.transferToInterpreter();
newTupleNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

final Object fullTuple = newTupleNode.call(frame,
getContext().getCoreLibrary().getTupleClass(),
"create",
null, matchData.getFullBegin(), matchData.getFullEnd());

matchData.setFullTuple(fullTuple);

return fullTuple;
}
}

@CoreMethod(names = {"length", "size"})
public abstract static class LengthNode extends CoreMethodArrayArgumentsNode {

Original file line number Diff line number Diff line change
@@ -10,7 +10,9 @@

package org.jruby.truffle.nodes.core;

import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyRegexp;
import org.jruby.util.StringSupport;

public class RegexpGuards {

@@ -22,4 +24,8 @@ public static boolean isRegexpLiteral(RubyRegexp regexp) {
return regexp.getOptions().isLiteral();
}

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

}
Original file line number Diff line number Diff line change
@@ -25,8 +25,9 @@ public static boolean isAsciiCompatible(RubyString string) {
return StringNodes.getByteList(string).getEncoding().isAsciiCompatible();
}

public static boolean isSingleByteOptimizableOrAsciiCompatible(RubyString string) {
return isSingleByteOptimizable(string) || isAsciiCompatible(string);
public static boolean isSingleByteOptimizableOrAsciiOnly(RubyString string) {
// TODO (nirvdrnum 08-Jun-15) Rubinius tracks whether a String is ASCII-only via a field in the String.
return isSingleByteOptimizable(string);
}

public static boolean isSingleByte(RubyString string) {
127 changes: 4 additions & 123 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
Original file line number Diff line number Diff line change
@@ -39,8 +39,7 @@
import org.jcodings.exception.EncodingException;
import org.jcodings.specific.ASCIIEncoding;
import org.jcodings.specific.USASCIIEncoding;
import org.joni.Matcher;
import org.joni.Option;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.Ruby;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
@@ -245,11 +244,12 @@ public static RubyBasicObject createEmptyString(RubyClass stringClass) {
}

public static RubyBasicObject createString(RubyClass stringClass, String string) {
return createString(stringClass, string, USASCIIEncoding.INSTANCE);
return createString(stringClass, string, UTF8Encoding.INSTANCE);
}

@TruffleBoundary
public static RubyBasicObject createString(RubyClass stringClass, String string, Encoding encoding) {
return createString(stringClass, new ByteList(org.jruby.RubyEncoding.encodeUTF8(string), encoding, false));
return createString(stringClass, org.jruby.RubyString.encodeBytelist(string, encoding));
}

public static RubyBasicObject createString(RubyClass stringClass, byte[] bytes) {
@@ -745,19 +745,6 @@ protected boolean isRubiniusUndefined(Object object) {

}

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

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

@Specialization
public Object match(RubyString string, RubyRegexp regexp) {
return regexp.matchCommon(string, true, false);
}
}

@CoreMethod(names = "ascii_only?")
public abstract static class ASCIIOnlyNode extends CoreMethodArrayArgumentsNode {

@@ -1520,28 +1507,6 @@ public Object lstripBang(RubyString string) {
}
}

@CoreMethod(names = "match", required = 1, taintFromSelf = true)
public abstract static class MatchNode extends CoreMethodArrayArgumentsNode {

@Child private CallDispatchHeadNode regexpMatchNode;

public MatchNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
regexpMatchNode = DispatchHeadNodeFactory.createMethodCall(context);
}

@Specialization
public Object match(VirtualFrame frame, RubyString string, RubyString regexpString) {
final RubyRegexp regexp = new RubyRegexp(this, getContext().getCoreLibrary().getRegexpClass(), getByteList(regexpString), Option.DEFAULT);
return regexpMatchNode.call(frame, regexp, "match", null, string);
}

@Specialization
public Object match(VirtualFrame frame, RubyString string, RubyRegexp regexp) {
return regexpMatchNode.call(frame, regexp, "match", null, string);
}
}

@RubiniusOnly
@CoreMethod(names = "modify!", raiseIfFrozenSelf = true)
public abstract static class ModifyBangNode extends CoreMethodArrayArgumentsNode {
@@ -1802,90 +1767,6 @@ private ByteList dumpCommon(RubyString string) {
}
}

@CoreMethod(names = "scan", required = 1, needsBlock = true, taintFromParameter = 0)
public abstract static class ScanNode extends YieldingCoreMethodNode {

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

@Specialization
public RubyBasicObject scan(RubyString string, RubyString regexpString, NotProvided block) {
final RubyRegexp regexp = new RubyRegexp(this, getContext().getCoreLibrary().getRegexpClass(), getByteList(regexpString), Option.DEFAULT);
return scan(string, regexp, block);
}

@Specialization
public RubyBasicObject scan(VirtualFrame frame, RubyString string, RubyString regexpString, RubyProc block) {
final RubyRegexp regexp = new RubyRegexp(this, getContext().getCoreLibrary().getRegexpClass(), getByteList(regexpString), Option.DEFAULT);
return scan(frame, string, regexp, block);
}

@Specialization
public RubyBasicObject scan(RubyString string, RubyRegexp regexp, NotProvided block) {
return ArrayNodes.fromObjects(getContext().getCoreLibrary().getArrayClass(), (Object[]) regexp.scan(string));
}

@Specialization
public RubyBasicObject scan(VirtualFrame frame, RubyString string, RubyRegexp regexp, RubyProc block) {
CompilerDirectives.transferToInterpreter();

// TODO (nirvdrum 12-Jan-15) Figure out a way to make this not just a complete copy & paste of RubyRegexp#scan.

final RubyContext context = getContext();

final byte[] stringBytes = getByteList(string).bytes();
final Encoding encoding = getByteList(string).getEncoding();
final Matcher matcher = regexp.getRegex().matcher(stringBytes);

int p = getByteList(string).getBegin();
int end = 0;
int range = p + getByteList(string).getRealSize();

Object lastGoodMatchData = nil();

if (regexp.getRegex().numberOfCaptures() == 0) {
while (true) {
Object matchData = regexp.matchCommon(string, false, true, matcher, p + end, range);

if (matchData == context.getCoreLibrary().getNilObject()) {
break;
}

RubyMatchData md = (RubyMatchData) matchData;
Object[] values = md.getValues();

assert values.length == 1;

yield(frame, block, values[0]);

lastGoodMatchData = matchData;
end = StringSupport.positionEndForScan(getByteList(string), matcher, encoding, p, range);
}

regexp.setThread("$~", lastGoodMatchData);
} else {
while (true) {
Object matchData = regexp.matchCommon(string, false, true, matcher, p + end, stringBytes.length);

if (matchData == context.getCoreLibrary().getNilObject()) {
break;
}

final Object[] captures = ((RubyMatchData) matchData).getCaptures();
yield(frame, block, ArrayNodes.createArray(context.getCoreLibrary().getArrayClass(), captures, captures.length));

lastGoodMatchData = matchData;
end = StringSupport.positionEndForScan(getByteList(string), matcher, encoding, p, range);
}

regexp.setThread("$~", lastGoodMatchData);
}

return string;
}
}

@CoreMethod(names = "setbyte", required = 2, raiseIfFrozenSelf = true)
@NodeChildren({
@NodeChild(type = RubyNode.class, value = "string"),
Loading