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

Commits on Dec 18, 2014

  1. Made RubyString#positionEnd a static utility method so it can be used…

    … outside of RubyString.
    nirvdrum committed Dec 18, 2014
    Copy the full SHA
    3594f3e View commit details
  2. [Truffle] RubyRegexp#scan no longer get stuck in an infinite loop and…

    … can now return captured values.
    nirvdrum committed Dec 18, 2014
    Copy the full SHA
    33bd0e1 View commit details
Showing with 64 additions and 21 deletions.
  1. +5 −5 core/src/main/java/org/jruby/RubyString.java
  2. +59 −16 core/src/main/java/org/jruby/truffle/runtime/core/RubyRegexp.java
10 changes: 5 additions & 5 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -4140,7 +4140,7 @@ public IRubyObject scan(ThreadContext context, IRubyObject arg, Block block) {
return scan19(context, arg, block);
}

private int positionEnd(Matcher matcher, Encoding enc, int begin, int range) {
public static int positionEnd(ByteList value, Matcher matcher, Encoding enc, int begin, int range) {
int end = matcher.getEnd();
if (matcher.getBegin() == end) {
if (value.getRealSize() > end) {
@@ -4207,7 +4207,7 @@ private IRubyObject scanIter19(ThreadContext context, Regex pattern, Regex prepa
RubyMatchData match = null;
if (pattern.numberOfCaptures() == 0) {
while (RubyRegexp.matcherSearch(runtime, matcher, begin + end, range, Option.NONE) >= 0) {
end = positionEnd(matcher, enc, begin, range);
end = positionEnd(value, matcher, enc, begin, range);
match = RubyRegexp.createMatchData19(context, this, matcher, pattern);
match.regexp = regexp;
RubyString substr = makeShared19(runtime, matcher.getBegin(), matcher.getEnd() - matcher.getBegin());
@@ -4219,7 +4219,7 @@ private IRubyObject scanIter19(ThreadContext context, Regex pattern, Regex prepa
}
} else {
while (RubyRegexp.matcherSearch(runtime, matcher, begin + end, range, Option.NONE) >= 0) {
end = positionEnd(matcher, enc, begin, range);
end = positionEnd(value, matcher, enc, begin, range);
match = RubyRegexp.createMatchData19(context, this, matcher, pattern);
match.regexp = regexp;
match.infectBy(tuFlags);
@@ -4244,14 +4244,14 @@ private IRubyObject scanNoIter19(ThreadContext context, Regex pattern, Regex pre
int end = 0;
if (pattern.numberOfCaptures() == 0) {
while (RubyRegexp.matcherSearch(runtime, matcher, begin + end, range, Option.NONE) >= 0) {
end = positionEnd(matcher, enc, begin, range);
end = positionEnd(value, matcher, enc, begin, range);
RubyString substr = makeShared19(runtime, matcher.getBegin(), matcher.getEnd() - matcher.getBegin());
substr.infectBy(tuFlags);
ary.append(substr);
}
} else {
while (RubyRegexp.matcherSearch(runtime, matcher, begin + end, range, Option.NONE) >= 0) {
end = positionEnd(matcher, enc, begin, range);
end = positionEnd(value, matcher, enc, begin, range);
ary.append(populateCapturesForScan(runtime, matcher, range, tuFlags, true));
}
}
75 changes: 59 additions & 16 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyRegexp.java
Original file line number Diff line number Diff line change
@@ -16,7 +16,6 @@
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.FrameSlot;
import org.jcodings.Encoding;
import org.jcodings.specific.UTF8Encoding;
import org.joni.*;
import org.joni.exception.SyntaxException;
import org.joni.exception.ValueException;
@@ -29,6 +28,7 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
* Represents the Ruby {@code Regexp} class.
@@ -92,13 +92,20 @@ public ByteList getSource() {

@CompilerDirectives.SlowPath
public Object matchCommon(ByteList bytes, boolean operator, boolean setNamedCaptures) {
final byte[] stringBytes = bytes.bytes();
final Matcher matcher = regex.matcher(stringBytes);
int range = stringBytes.length;

return matchCommon(bytes, operator, setNamedCaptures, matcher, 0, range);
}

@CompilerDirectives.SlowPath
public Object matchCommon(ByteList bytes, boolean operator, boolean setNamedCaptures, Matcher matcher, int startPos, int range) {
final RubyContext context = getContext();

final Frame frame = Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_WRITE, false);

final byte[] stringBytes = bytes.bytes();
final Matcher matcher = regex.matcher(stringBytes);
final int match = matcher.search(0, stringBytes.length, Option.DEFAULT);
final int match = matcher.search(startPos, range, Option.DEFAULT);

final RubyNilClass nil = getContext().getCoreLibrary().getNilObject();

@@ -327,29 +334,65 @@ public RubyString[] split(String string) {
}

@CompilerDirectives.SlowPath
public RubyString[] scan(RubyString string) {
public Object scan(RubyString string) {
final RubyContext context = getContext();

final byte[] stringBytes = string.getBytes().bytes();
final Encoding encoding = string.getBytes().getEncoding();
final Matcher matcher = regex.matcher(stringBytes);

final ArrayList<RubyString> strings = new ArrayList<>();
int p = string.getBytes().getBegin();
int end = 0;
int range = p + string.getBytes().getRealSize();

int p = 0;
if (regex.numberOfCaptures() == 0) {
final ArrayList<RubyString> strings = new ArrayList<>();

while (true) {
final int match = matcher.search(p, stringBytes.length, Option.DEFAULT);
while (true) {
Object matchData = matchCommon(string.getBytes(), false, true, matcher, p + end, range);

if (match == -1) {
break;
} else {
strings.add(context.makeString(StandardCharsets.UTF_8.decode(ByteBuffer.wrap(stringBytes, matcher.getBegin(), matcher.getEnd() - matcher.getBegin())).toString()));
if (matchData == context.getCoreLibrary().getNilObject()) {
break;
}

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

assert values.length == 1;

strings.add((RubyString) values[0]);

end = org.jruby.RubyString.positionEnd(string.getBytes(), matcher, encoding, p, range);
}

p = matcher.getEnd();
}
return strings.toArray(new RubyString[strings.size()]);
} else {
final List<RubyArray> strings = new ArrayList<>();

return strings.toArray(new RubyString[strings.size()]);
while (true) {
Object matchData = matchCommon(string.getBytes(), false, true, matcher, p + end, stringBytes.length);

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

RubyMatchData md = (RubyMatchData) matchData;

final List<RubyString> parts = new ArrayList<>();

Object[] values = md.getValues();
for (int i = 1; i < values.length; i++) {
parts.add((RubyString) values[i]);
}

RubyString[] matches = parts.toArray(new RubyString[parts.size()]);
strings.add(RubyArray.fromObjects(getContext().getCoreLibrary().getArrayClass(), matches));

end = org.jruby.RubyString.positionEnd(string.getBytes(), matcher, encoding, p, range);
}

return strings.toArray(new Object[strings.size()]);
}
}

@Override