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

Commits on Jan 25, 2016

  1. Copy the full SHA
    9ca086f View commit details
  2. Copy the full SHA
    71dbedf View commit details
  3. Copy the full SHA
    d9d7536 View commit details
  4. Copy the full SHA
    fcf0d33 View commit details
  5. Copy the full SHA
    1948432 View commit details

Commits on Jan 26, 2016

  1. Copy the full SHA
    1c10760 View commit details
  2. Improved handling of Rubinius's @DaTa in String.

    * Unified with the String#data method.
    * Used Rubinius::ByteArray and removed our Rubinius::StringData shim.
    * Cached value in String DynamicObject and invalidate on Rope update.
    nirvdrum committed Jan 26, 2016
    Copy the full SHA
    4dadf16 View commit details
  3. Copy the full SHA
    3922168 View commit details
  4. Copy the full SHA
    f66e523 View commit details

Commits on Jan 27, 2016

  1. Copy the full SHA
    d597c4b View commit details
  2. Copy the full SHA
    3fc9525 View commit details
  3. Copy the full SHA
    0b72e28 View commit details
Showing with 549 additions and 315 deletions.
  1. +12 −8 truffle/src/main/java/org/jruby/truffle/nodes/StringCachingGuards.java
  2. +7 −3 truffle/src/main/java/org/jruby/truffle/nodes/core/InterpolatedRegexpNode.java
  3. +6 −5 truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
  4. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/core/RegexpGuards.java
  5. +45 −31 truffle/src/main/java/org/jruby/truffle/nodes/core/RegexpNodes.java
  6. +97 −22 truffle/src/main/java/org/jruby/truffle/nodes/core/RopeNodes.java
  7. +5 −0 truffle/src/main/java/org/jruby/truffle/nodes/core/StringGuards.java
  8. +62 −46 truffle/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
  9. +9 −8 truffle/src/main/java/org/jruby/truffle/nodes/core/TruffleInteropNodes.java
  10. +52 −0 truffle/src/main/java/org/jruby/truffle/nodes/core/TrufflePrimitiveNodes.java
  11. +4 −3 truffle/src/main/java/org/jruby/truffle/nodes/core/array/ArrayNodes.java
  12. +17 −2 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/ByteArrayNodes.java
  13. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/EncodingConverterPrimitiveNodes.java
  14. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/PosixNodes.java
  15. +11 −10 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/RegexpPrimitiveNodes.java
  16. +10 −10 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/StringPrimitiveNodes.java
  17. +1 −1 truffle/src/main/java/org/jruby/truffle/runtime/core/StringCodeRangeableWrapper.java
  18. +8 −34 truffle/src/main/java/org/jruby/truffle/runtime/core/StringOperations.java
  19. +4 −4 truffle/src/main/java/org/jruby/truffle/runtime/layouts/RegexpLayout.java
  20. +3 −3 truffle/src/main/java/org/jruby/truffle/runtime/layouts/StringLayout.java
  21. +4 −42 truffle/src/main/java/org/jruby/truffle/runtime/rope/ConcatRope.java
  22. +4 −18 truffle/src/main/java/org/jruby/truffle/runtime/rope/LeafRope.java
  23. +16 −4 truffle/src/main/java/org/jruby/truffle/runtime/rope/Rope.java
  24. +158 −1 truffle/src/main/java/org/jruby/truffle/runtime/rope/RopeOperations.java
  25. +2 −23 truffle/src/main/java/org/jruby/truffle/runtime/rope/SubstringRope.java
  26. +8 −6 truffle/src/main/java/org/jruby/truffle/translator/BodyTranslator.java
  27. +0 −27 truffle/src/main/ruby/core/shims.rb
Original file line number Diff line number Diff line change
@@ -13,33 +13,37 @@
import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.rope.Rope;
import org.jruby.util.ByteList;

public abstract class StringCachingGuards {

public static ByteList privatizeByteList(DynamicObject string) {
public static Rope privatizeRope(DynamicObject string) {
if (RubyGuards.isRubyString(string)) {
return StringOperations.getByteListReadOnly(string).dup();
// TODO (nirvdrum 25-Jan-16) Should we flatten the rope to avoid caching a potentially deep rope tree?
return StringOperations.rope(string);
} else {
return null;
}
}

public static boolean byteListsEqual(DynamicObject string, ByteList byteList) {
public static boolean ropesEqual(DynamicObject string, Rope rope) {
if (RubyGuards.isRubyString(string)) {
final Rope stringRope = StringOperations.rope(string);

// equal below does not check encoding
if (Layouts.STRING.getRope(string).getEncoding() != byteList.getEncoding()) {
if (stringRope.getEncoding() != rope.getEncoding()) {
return false;
}
// TODO CS 8-Nov-15 this code goes off into the woods - need to break it apart and branch profile it
return StringOperations.getByteListReadOnly(string).equal(byteList);

return stringRope.equals(rope);
} else {
return false;
}
}

public static int byteListLength(ByteList byteList) {
return byteList.length();
public static int ropeLength(Rope rope) {
return rope.byteLength();
}

}
Original file line number Diff line number Diff line change
@@ -19,6 +19,8 @@
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.rope.Rope;
import org.jruby.truffle.runtime.rope.RopeOperations;
import org.jruby.truffle.translator.BodyTranslator;
import org.jruby.util.RegexpOptions;

@@ -48,13 +50,15 @@ public Object execute(VirtualFrame frame) {

final org.jruby.RubyString preprocessed = org.jruby.RubyRegexp.preprocessDRegexp(getContext().getRuntime(), strings, options);

final DynamicObject regexp = RegexpNodes.createRubyRegexp(getContext(), this, getContext().getCoreLibrary().getRegexpClass(), preprocessed.getByteList(), options);
final DynamicObject regexp = RegexpNodes.createRubyRegexp(getContext(), this, getContext().getCoreLibrary().getRegexpClass(), StringOperations.ropeFromByteList(preprocessed.getByteList()), options);

if (options.isEncodingNone()) {
final Rope source = Layouts.REGEXP.getSource(regexp);

if (!BodyTranslator.all7Bit(preprocessed.getByteList().bytes())) {
Layouts.REGEXP.getSource(regexp).setEncoding(getContext().getRuntime().getEncodingService().getAscii8bitEncoding());
Layouts.REGEXP.setSource(regexp, RopeOperations.withEncoding(source, getContext().getRuntime().getEncodingService().getAscii8bitEncoding()));
} else {
Layouts.REGEXP.getSource(regexp).setEncoding(getContext().getRuntime().getEncodingService().getUSAsciiEncoding());
Layouts.REGEXP.setSource(regexp, RopeOperations.withEncoding(source, getContext().getRuntime().getEncodingService().getUSAsciiEncoding()));
}
}

Original file line number Diff line number Diff line change
@@ -72,6 +72,7 @@
import org.jruby.truffle.runtime.loader.FeatureLoader;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
import org.jruby.truffle.runtime.rope.Rope;
import org.jruby.truffle.runtime.subsystems.ThreadManager.BlockingAction;
import org.jruby.truffle.translator.TranslatorDriver;
import org.jruby.truffle.translator.TranslatorDriver.ParserContext;
@@ -511,7 +512,7 @@ public RubyRootNode getRootNode() {

@Specialization(guards = {
"isRubyString(source)",
"byteListsEqual(source, cachedSource)",
"ropesEqual(source, cachedSource)",
"!parseDependsOnDeclarationFrame(cachedRootNode)"
}, limit = "getCacheLimit()")
public Object evalNoBindingCached(
@@ -520,7 +521,7 @@ public Object evalNoBindingCached(
NotProvided binding,
NotProvided filename,
NotProvided lineNumber,
@Cached("privatizeByteList(source)") ByteList cachedSource,
@Cached("privatizeRope(source)") Rope cachedSource,
@Cached("compileSource(frame, source)") RootNodeWrapper cachedRootNode,
@Cached("createCallTarget(cachedRootNode)") CallTarget cachedCallTarget,
@Cached("create(cachedCallTarget)") DirectCallNode callNode
@@ -1870,13 +1871,13 @@ public SprintfNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization(guards = { "isRubyString(format)", "byteListsEqual(format, cachedFormat)" })
@Specialization(guards = { "isRubyString(format)", "ropesEqual(format, cachedFormat)" })
public DynamicObject formatCached(
VirtualFrame frame,
DynamicObject format,
Object[] arguments,
@Cached("privatizeByteList(format)") ByteList cachedFormat,
@Cached("byteListLength(cachedFormat)") int cachedFormatLength,
@Cached("privatizeRope(format)") Rope cachedFormat,
@Cached("ropeLength(cachedFormat)") int cachedFormatLength,
@Cached("create(compileFormat(format))") DirectCallNode callPackNode) {
final PackResult result;

Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ public static boolean isRegexpLiteral(DynamicObject regexp) {
}

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

}
76 changes: 45 additions & 31 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/RegexpNodes.java
Original file line number Diff line number Diff line change
@@ -39,6 +39,8 @@
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.rope.Rope;
import org.jruby.truffle.runtime.rope.RopeOperations;
import org.jruby.util.*;

import java.nio.charset.StandardCharsets;
@@ -54,17 +56,17 @@ public static Object matchCommon(RubyContext context, DynamicObject regexp, Dyna
assert RubyGuards.isRubyRegexp(regexp);
assert RubyGuards.isRubyString(source);

final ByteList sourceByteList = StringOperations.getByteListReadOnly(source);
final Rope sourceRope = StringOperations.rope(source);

final ByteList bl = Layouts.REGEXP.getSource(regexp);
final Encoding enc = checkEncoding(regexp, StringOperations.getCodeRangeableReadOnly(source), true);
final ByteList preprocessed = RegexpSupport.preprocess(context.getRuntime(), bl, enc, new Encoding[] { null }, RegexpSupport.ErrorMode.RAISE);
final Rope regexpSourceRope = Layouts.REGEXP.getSource(regexp);
final Encoding enc = checkEncoding(regexp, sourceRope, true);
final ByteList preprocessed = RegexpSupport.preprocess(context.getRuntime(), regexpSourceRope.getUnsafeByteList(), 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, StringOperations.getCodeRangeableReadOnly(source), true));
final Matcher matcher = r.matcher(sourceByteList.unsafeBytes(), sourceByteList.begin(), sourceByteList.begin() + sourceByteList.realSize());
int range = sourceByteList.begin() + sourceByteList.realSize();
final Regex r = new Regex(preprocessed.getUnsafeBytes(), preprocessed.getBegin(), preprocessed.getBegin() + preprocessed.getRealSize(), Layouts.REGEXP.getOptions(regexp).toJoniOptions(), checkEncoding(regexp, sourceRope, true));
final Matcher matcher = r.matcher(sourceRope.getBytes(), sourceRope.begin(), sourceRope.begin() + sourceRope.realSize());
int range = sourceRope.begin() + sourceRope.realSize();

return matchCommon(context, regexp, source, operator, setNamedCaptures, matcher, sourceByteList.begin() + startPos, range);
return matchCommon(context, regexp, source, operator, setNamedCaptures, matcher, sourceRope.begin() + startPos, range);
}

@TruffleBoundary
@@ -196,7 +198,7 @@ private static void setLocalVariable(Frame frame, String name, Object value) {
}
}

public static ByteList shimModifiers(ByteList bytes) {
public static Rope shimModifiers(Rope bytes) {
// Joni doesn't support (?u) etc but we can shim some common cases

String bytesString = bytes.toString();
@@ -222,14 +224,15 @@ public static ByteList shimModifiers(ByteList bytes) {
throw new UnsupportedOperationException();
}

bytes = ByteList.create(bytesString);
// TODO (nirvdrum 25-Jan-16): We probably just want a way to create a Rope from a java.lang.String.
bytes = StringOperations.ropeFromByteList(ByteList.create(bytesString));
}

return bytes;
}

@TruffleBoundary
public static Regex compile(Node currentNode, RubyContext context, ByteList bytes, RegexpOptions options) {
public static Regex compile(Node currentNode, RubyContext context, Rope bytes, RegexpOptions options) {
bytes = shimModifiers(bytes);

try {
@@ -248,13 +251,14 @@ public static Regex compile(Node currentNode, RubyContext context, ByteList byte
}
*/

final ByteList byteList = bytes.getUnsafeByteList();
Encoding enc = bytes.getEncoding();
Encoding[] fixedEnc = new Encoding[]{null};
ByteList unescaped = RegexpSupport.preprocess(context.getRuntime(), bytes, enc, fixedEnc, RegexpSupport.ErrorMode.RAISE);
ByteList unescaped = RegexpSupport.preprocess(context.getRuntime(), byteList, enc, fixedEnc, RegexpSupport.ErrorMode.RAISE);
if (fixedEnc[0] != null) {
if ((fixedEnc[0] != enc && options.isFixed()) ||
(fixedEnc[0] != ASCIIEncoding.INSTANCE && options.isEncodingNone())) {
RegexpSupport.raiseRegexpError19(context.getRuntime(), bytes, enc, options, "incompatible character encoding");
RegexpSupport.raiseRegexpError19(context.getRuntime(), byteList, enc, options, "incompatible character encoding");
}
if (fixedEnc[0] != ASCIIEncoding.INSTANCE) {
options.setFixed(true);
@@ -267,10 +271,8 @@ public static Regex compile(Node currentNode, RubyContext context, ByteList byte
if (fixedEnc[0] != null) options.setFixed(true);
//if (regexpOptions.isEncodingNone()) setEncodingNone();

bytes.setEncoding(enc);

Regex ret = new Regex(unescaped.getUnsafeBytes(), unescaped.getBegin(), unescaped.getBegin() + unescaped.getRealSize(), options.toJoniOptions(), enc, Syntax.RUBY);
ret.setUserObject(bytes);
ret.setUserObject(RopeOperations.withEncoding(bytes, enc));

return ret;
} catch (ValueException e) {
@@ -292,7 +294,7 @@ public static void setRegex(DynamicObject regexp, Regex regex) {
Layouts.REGEXP.setRegex(regexp, regex);
}

public static void setSource(DynamicObject regexp, ByteList source) {
public static void setSource(DynamicObject regexp, Rope source) {
Layouts.REGEXP.setSource(regexp, source);
}

@@ -301,7 +303,7 @@ public static void setOptions(DynamicObject regexp, RegexpOptions options) {
}

// TODO (nirvdrum 03-June-15) Unify with JRuby in RegexpSupport.
public static Encoding checkEncoding(DynamicObject regexp, CodeRangeable str, boolean warn) {
public static Encoding checkEncoding(DynamicObject regexp, Rope str, boolean warn) {
assert RubyGuards.isRubyRegexp(regexp);

final Regex pattern = Layouts.REGEXP.getRegex(regexp);
@@ -312,7 +314,7 @@ public static Encoding checkEncoding(DynamicObject regexp, CodeRangeable str, bo
}
*/
//check();
Encoding enc = str.getByteList().getEncoding();
Encoding enc = str.getEncoding();
if (!enc.isAsciiCompatible()) {
if (enc != pattern.getEncoding()) {
//encodingMatchError(getRuntime(), pattern, enc);
@@ -335,31 +337,42 @@ public static Encoding checkEncoding(DynamicObject regexp, CodeRangeable str, bo
return enc;
}

public static void initialize(RubyContext context, DynamicObject regexp, Node currentNode, ByteList setSource, int options) {
public static void initialize(RubyContext context, DynamicObject regexp, Node currentNode, Rope setSource, int options) {
assert RubyGuards.isRubyRegexp(regexp);
setSource(regexp, setSource);
setOptions(regexp, RegexpOptions.fromEmbeddedOptions(options));
setRegex(regexp, compile(currentNode, context, setSource, Layouts.REGEXP.getOptions(regexp)));
final RegexpOptions regexpOptions = RegexpOptions.fromEmbeddedOptions(options);
final Regex regex = compile(currentNode, context, setSource, regexpOptions);

// The RegexpNodes.compile operation may modify the encoding of the source rope. This modified copy is stored
// in the Regex object as the "user object". Since ropes are immutable, we need to take this updated copy when
// constructing the final regexp.
setSource(regexp, (Rope) regex.getUserObject());
setOptions(regexp, regexpOptions);
setRegex(regexp, regex);
}

public static void initialize(DynamicObject regexp, Regex setRegex, ByteList setSource) {
public static void initialize(DynamicObject regexp, Regex setRegex, Rope setSource) {
assert RubyGuards.isRubyRegexp(regexp);
setRegex(regexp, setRegex);
setSource(regexp, setSource);
}

public static DynamicObject createRubyRegexp(RubyContext context, Node currentNode, DynamicObject regexpClass, ByteList regex, RegexpOptions options) {
return Layouts.REGEXP.createRegexp(Layouts.CLASS.getInstanceFactory(regexpClass), RegexpNodes.compile(currentNode, context, regex, options), regex, options, null);
public static DynamicObject createRubyRegexp(RubyContext context, Node currentNode, DynamicObject regexpClass, Rope source, RegexpOptions options) {
final Regex regexp = RegexpNodes.compile(currentNode, context, source, options);

// The RegexpNodes.compile operation may modify the encoding of the source rope. This modified copy is stored
// in the Regex object as the "user object". Since ropes are immutable, we need to take this updated copy when
// constructing the final regexp.
return Layouts.REGEXP.createRegexp(Layouts.CLASS.getInstanceFactory(regexpClass), regexp, (Rope) regexp.getUserObject(), options, null);
}

public static DynamicObject createRubyRegexp(DynamicObject regexpClass, Regex regex, ByteList source, RegexpOptions options) {
public static DynamicObject createRubyRegexp(DynamicObject regexpClass, Regex regex, Rope source, RegexpOptions options) {
final DynamicObject regexp = Layouts.REGEXP.createRegexp(Layouts.CLASS.getInstanceFactory(regexpClass), null, null, RegexpOptions.NULL_OPTIONS, null);
RegexpNodes.setOptions(regexp, options);
RegexpNodes.initialize(regexp, regex, source);
return regexp;
}

public static DynamicObject createRubyRegexp(DynamicObject regexpClass, Regex regex, ByteList source) {
public static DynamicObject createRubyRegexp(DynamicObject regexpClass, Regex regex, Rope source) {
final DynamicObject regexp = Layouts.REGEXP.createRegexp(Layouts.CLASS.getInstanceFactory(regexpClass), null, null, RegexpOptions.NULL_OPTIONS, null);
RegexpNodes.initialize(regexp, regex, source);
return regexp;
@@ -466,7 +479,8 @@ public QuoteNode(RubyContext context, SourceSection sourceSection) {
@TruffleBoundary
@Specialization(guards = "isRubyString(raw)")
public DynamicObject quoteString(DynamicObject raw) {
boolean isAsciiOnly = Layouts.STRING.getRope(raw).getEncoding().isAsciiCompatible() && StringOperations.scanForCodeRange(raw) == CR_7BIT;
final Rope rope = StringOperations.rope(raw);
boolean isAsciiOnly = rope.getEncoding().isAsciiCompatible() && rope.getCodeRange() == CR_7BIT;
return createString(org.jruby.RubyRegexp.quote19(StringOperations.getByteListReadOnly(raw), isAsciiOnly));
}

@@ -500,7 +514,7 @@ public SourceNode(RubyContext context, SourceSection sourceSection) {

@Specialization
public DynamicObject source(DynamicObject regexp) {
return createString(Layouts.REGEXP.getSource(regexp).dup());
return createString(Layouts.REGEXP.getSource(regexp));
}

}
@@ -515,7 +529,7 @@ public ToSNode(RubyContext context, SourceSection sourceSection) {
@TruffleBoundary
@Specialization
public DynamicObject toS(DynamicObject regexp) {
return createString(((org.jruby.RubyString) org.jruby.RubyRegexp.newRegexp(getContext().getRuntime(), Layouts.REGEXP.getSource(regexp), Layouts.REGEXP.getRegex(regexp).getOptions()).to_s()).getByteList());
return createString(((org.jruby.RubyString) org.jruby.RubyRegexp.newRegexp(getContext().getRuntime(), Layouts.REGEXP.getSource(regexp).getUnsafeByteList(), Layouts.REGEXP.getRegex(regexp).getOptions()).to_s()).getByteList());
}

}
Loading