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

Commits on Mar 24, 2016

  1. [Truffle] Added a node for altering the encoding of a rope.

    Also updated String#b to use this new node.
    nirvdrum committed Mar 24, 2016
    2
    Copy the full SHA
    5653941 View commit details
  2. Copy the full SHA
    1ba8d20 View commit details
  3. Copy the full SHA
    05c797b View commit details
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -252,6 +252,7 @@ public class Options {
public static final Option<Integer> TRUFFLE_CLASS_CACHE = integer(TRUFFLE, "truffle.class.cache", TRUFFLE_DEFAULT_CACHE.load(), ".class and .metaclass cache size");
public static final Option<Integer> TRUFFLE_ENCODING_COMPATIBLE_QUERY_CACHE = integer(TRUFFLE, "truffle.encoding_compatible_query.cache", TRUFFLE_DEFAULT_CACHE.load(), "Encoding.compatible? cache size");
public static final Option<Integer> TRUFFLE_THREAD_CACHE = integer(TRUFFLE, "truffle.thread.cache", TRUFFLE_DEFAULT_CACHE.load(), "Cache size of operations that depend on a particular thread");
public static final Option<Integer> TRUFFLE_ROPE_CLASS_CACHE = integer(TRUFFLE, "truffle.rope_class.cache", 6, "Cache size for rope operations that depend on a concrete rope implementation to avoid virtual calls");

public static final Option<Boolean> TRUFFLE_CLONE_DEFAULT = bool(TRUFFLE, "truffle.clone.default", true, "Default option for cloning.");
public static final Option<Boolean> TRUFFLE_INLINE_DEFAULT = bool(TRUFFLE, "truffle.inline.default", true, "Default option for inlining.");
2 changes: 2 additions & 0 deletions test/truffle/compiler/pe/core/string_pe.rb
Original file line number Diff line number Diff line change
@@ -28,6 +28,8 @@

example "'aba'[0] == 'aca'[-1]", true

example "x = 'abc'; x == x.b", true

example "'abc'.ascii_only?", true
example "'こにちわ'.ascii_only?", false

Original file line number Diff line number Diff line change
@@ -2003,17 +2003,17 @@ private DynamicObject finishFormat(int formatLength, PackResult result) {
final DynamicObject string = createString(new ByteList((byte[]) result.getOutput(), 0, result.getOutputLength()));

if (formatLength == 0) {
StringOperations.forceEncoding(string, USASCIIEncoding.INSTANCE);
StringOperations.forceEncodingVerySlow(string, USASCIIEncoding.INSTANCE);
} else {
switch (result.getEncoding()) {
case DEFAULT:
case ASCII_8BIT:
break;
case US_ASCII:
StringOperations.forceEncoding(string, USASCIIEncoding.INSTANCE);
StringOperations.forceEncodingVerySlow(string, USASCIIEncoding.INSTANCE);
break;
case UTF_8:
StringOperations.forceEncoding(string, UTF8Encoding.INSTANCE);
StringOperations.forceEncodingVerySlow(string, UTF8Encoding.INSTANCE);
break;
default:
throw new UnsupportedOperationException();
Original file line number Diff line number Diff line change
@@ -56,9 +56,9 @@ public Object execute(VirtualFrame frame) {
final Rope source = Layouts.REGEXP.getSource(regexp);

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

Original file line number Diff line number Diff line change
@@ -295,7 +295,7 @@ public static Regex compile(Node currentNode, RubyContext context, Rope bytes, R
//if (regexpOptions.isEncodingNone()) setEncodingNone();

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

return ret;
} catch (ValueException e) {
72 changes: 68 additions & 4 deletions truffle/src/main/java/org/jruby/truffle/core/rope/RopeNodes.java
Original file line number Diff line number Diff line change
@@ -17,7 +17,6 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.CreateCast;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
@@ -29,7 +28,7 @@
import org.jcodings.specific.USASCIIEncoding;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.numeric.FixnumLowerNodeGen;
import org.jruby.truffle.language.NotProvided;
import org.jruby.truffle.language.RubyNode;
import org.jruby.util.ByteList;
import org.jruby.util.StringSupport;
@@ -76,7 +75,7 @@ public Rope substringZeroBytes(Rope base, int offset, int byteLength,
return RopeConstants.EMPTY_ASCII_8BIT_ROPE;
}

return RopeOperations.withEncoding(RopeConstants.EMPTY_UTF8_ROPE, base.getEncoding());
return RopeOperations.withEncodingVerySlow(RopeConstants.EMPTY_UTF8_ROPE, base.getEncoding());
}

@Specialization(guards = "byteLength == 1")
@@ -98,7 +97,7 @@ public Rope substringOneByte(Rope base, int offset, int byteLength,
return RopeConstants.ASCII_8BIT_SINGLE_BYTE_ROPES[index];
}

return RopeOperations.withEncoding(RopeConstants.ASCII_8BIT_SINGLE_BYTE_ROPES[index], base.getEncoding());
return RopeOperations.withEncodingVerySlow(RopeConstants.ASCII_8BIT_SINGLE_BYTE_ROPES[index], base.getEncoding());
}

@Specialization(guards = { "byteLength > 1", "sameAsBase(base, offset, byteLength)" })
@@ -298,6 +297,10 @@ protected static boolean isMutableRope(Rope rope) {
})
public abstract static class MakeLeafRopeNode extends RubyNode {

public static MakeLeafRopeNode create(RubyContext context, SourceSection sourceSection) {
return RopeNodesFactory.MakeLeafRopeNodeGen.create(context, sourceSection, null, null, null, null);
}

public MakeLeafRopeNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}
@@ -563,4 +566,65 @@ private void printPreamble(int level) {
}

}

@NodeChildren({
@NodeChild(type = RubyNode.class, value = "rope"),
@NodeChild(type = RubyNode.class, value = "encoding"),
@NodeChild(type = RubyNode.class, value = "codeRange")
})
public abstract static class WithEncodingNode extends RubyNode {

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

public abstract Rope executeWithEncoding(Rope rope, Encoding encoding, CodeRange codeRange);

@Specialization(guards = "rope.getEncoding() == encoding")
public Rope withEncodingSameEncoding(Rope rope, Encoding encoding, CodeRange codeRange) {
return rope;
}

@Specialization(guards = {
"rope.getEncoding() != encoding",
"rope.getCodeRange() == codeRange"
})
public Rope withEncodingSameCodeRange(Rope rope, Encoding encoding, CodeRange codeRange) {
return rope.withEncoding(encoding, codeRange);
}

@Specialization(guards = {
"rope.getEncoding() != encoding",
"rope.getCodeRange() != codeRange",
"isAsciiCompatbileChange(rope, encoding)",
"rope.getClass() == cachedRopeClass"
}, limit = "getCacheLimit()")
public Rope withEncodingCr7Bit(Rope rope, Encoding encoding, CodeRange codeRange,
@Cached("rope.getClass()") Class<? extends Rope> cachedRopeClass) {
return cachedRopeClass.cast(rope).withEncoding(encoding, CodeRange.CR_7BIT);
}

@Specialization(guards = {
"rope.getEncoding() != encoding",
"rope.getCodeRange() != codeRange",
"!isAsciiCompatbileChange(rope, encoding)"
})
public Rope withEncoding(Rope rope, Encoding encoding, CodeRange codeRange,
@Cached("create(getContext(), getSourceSection())") MakeLeafRopeNode makeLeafRopeNode) {
return makeLeafRopeNode.executeMake(rope.getBytes(), encoding, codeRange, NotProvided.INSTANCE);
}

protected static boolean isAsciiCompatbileChange(Rope rope, Encoding encoding) {
return rope.getCodeRange() == CR_7BIT && encoding.isAsciiCompatible();
}

protected static boolean is7Bit(Rope rope) {
return rope.getCodeRange() == CR_7BIT;
}

protected int getCacheLimit() {
return getContext().getOptions().ROPE_CLASS_CACHE;
}

}
}
Original file line number Diff line number Diff line change
@@ -85,7 +85,7 @@ public static LeafRope create(byte[] bytes, Encoding encoding, CodeRange codeRan
}
}

public static Rope withEncoding(Rope originalRope, Encoding newEncoding, CodeRange newCodeRange) {
public static Rope withEncodingVerySlow(Rope originalRope, Encoding newEncoding, CodeRange newCodeRange) {
if ((originalRope.getEncoding() == newEncoding) && (originalRope.getCodeRange() == newCodeRange)) {
return originalRope;
}
@@ -101,8 +101,8 @@ public static Rope withEncoding(Rope originalRope, Encoding newEncoding, CodeRan
return create(originalRope.getBytes(), newEncoding, newCodeRange);
}

public static Rope withEncoding(Rope originalRope, Encoding newEncoding) {
return withEncoding(originalRope, newEncoding, originalRope.getCodeRange());
public static Rope withEncodingVerySlow(Rope originalRope, Encoding newEncoding) {
return withEncodingVerySlow(originalRope, newEncoding, originalRope.getCodeRange());
}

@TruffleBoundary
Original file line number Diff line number Diff line change
@@ -546,7 +546,7 @@ private Object sliceRange(VirtualFrame frame, DynamicObject string, int begin, i
if (begin == stringLength) {
final ByteList byteList = new ByteList();
byteList.setEncoding(encoding(string));
return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(string), RopeOperations.withEncoding(RopeConstants.EMPTY_ASCII_8BIT_ROPE, encoding(string)), null);
return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(string), RopeOperations.withEncodingVerySlow(RopeConstants.EMPTY_ASCII_8BIT_ROPE, encoding(string)), null);
}

end = StringOperations.normalizeIndex(stringLength, end);
@@ -667,13 +667,18 @@ public boolean asciiOnly(DynamicObject string) {
@CoreMethod(names = "b", taintFromSelf = true)
public abstract static class BNode extends CoreMethodArrayArgumentsNode {

@Child private RopeNodes.WithEncodingNode withEncodingNode;

public BNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
withEncodingNode = RopeNodesFactory.WithEncodingNodeGen.create(context, sourceSection, null, null, null);
}

@Specialization
public DynamicObject b(DynamicObject string) {
return createString(RopeOperations.withEncoding(rope(string), ASCIIEncoding.INSTANCE));
final Rope newRope = withEncodingNode.executeWithEncoding(rope(string), ASCIIEncoding.INSTANCE, CodeRange.CR_UNKNOWN);

return createString(newRope);
}

}
@@ -1202,10 +1207,12 @@ public DynamicObject encoding(DynamicObject string) {
@CoreMethod(names = "force_encoding", required = 1, raiseIfFrozenSelf = true)
public abstract static class ForceEncodingNode extends CoreMethodArrayArgumentsNode {

@Child private RopeNodes.WithEncodingNode withEncodingNode;
@Child private ToStrNode toStrNode;

public ForceEncodingNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
withEncodingNode = RopeNodesFactory.WithEncodingNodeGen.create(context, sourceSection, null, null, null);
}

@TruffleBoundary
@@ -1228,7 +1235,8 @@ public DynamicObject forceEncodingEncoding(DynamicObject string, DynamicObject r
if (mutableRopeProfile.profile(rope instanceof MutableRope)) {
((MutableRope) rope).getByteList().setEncoding(encoding);
} else {
StringOperations.forceEncoding(string, encoding);
final Rope newRope = withEncodingNode.executeWithEncoding(rope, encoding, CodeRange.CR_UNKNOWN);
StringOperations.setRope(string, newRope);
}
}

@@ -2670,7 +2678,7 @@ public ClearNode(RubyContext context, SourceSection sourceSection) {

@Specialization
public DynamicObject clear(DynamicObject string) {
StringOperations.setRope(string, RopeOperations.withEncoding(EMPTY_UTF8_ROPE, encoding(string)));
StringOperations.setRope(string, RopeOperations.withEncodingVerySlow(EMPTY_UTF8_ROPE, encoding(string)));

return string;
}
Original file line number Diff line number Diff line change
@@ -165,9 +165,9 @@ public static Encoding checkEncoding(DynamicObject string, CodeRangeable other)
return encoding;
}

public static void forceEncoding(DynamicObject string, Encoding encoding) {
public static void forceEncodingVerySlow(DynamicObject string, Encoding encoding) {
final Rope oldRope = Layouts.STRING.getRope(string);
StringOperations.setRope(string, RopeOperations.withEncoding(oldRope, encoding, CodeRange.CR_UNKNOWN));
StringOperations.setRope(string, RopeOperations.withEncodingVerySlow(oldRope, encoding, CodeRange.CR_UNKNOWN));
}

public static int normalizeIndex(int length, int index) {
2 changes: 2 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/language/Options.java
Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@
import static org.jruby.util.cli.Options.TRUFFLE_PACK_RECOVER_LOOP_MIN;
import static org.jruby.util.cli.Options.TRUFFLE_PACK_UNROLL_LIMIT;
import static org.jruby.util.cli.Options.TRUFFLE_PLATFORM_USE_JAVA;
import static org.jruby.util.cli.Options.TRUFFLE_ROPE_CLASS_CACHE;
import static org.jruby.util.cli.Options.TRUFFLE_ROPE_LAZY_SUBSTRINGS;
import static org.jruby.util.cli.Options.TRUFFLE_SYMBOL_TO_PROC_CACHE;
import static org.jruby.util.cli.Options.TRUFFLE_THREAD_CACHE;
@@ -94,6 +95,7 @@ public class Options {
public final int CLASS_CACHE = TRUFFLE_CLASS_CACHE.load();
public final int ENCODING_COMPATIBILE_QUERY_CACHE = TRUFFLE_ENCODING_COMPATIBLE_QUERY_CACHE.load();
public final int THREAD_CACHE = TRUFFLE_THREAD_CACHE.load();
public final int ROPE_CLASS_CACHE = TRUFFLE_ROPE_CLASS_CACHE.load();

// Cloning and inlining