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

Commits on Jun 21, 2016

  1. [Truffle] Minor clean-up.

    nirvdrum committed Jun 21, 2016
    Copy the full SHA
    28f0a59 View commit details
  2. Copy the full SHA
    7c3b576 View commit details
  3. [Truffle] Store the Ruby string name, rather than ByteList name, with…

    … the ruby encoding.
    
    This also fixes the semantics of Encoding#{name,to_s}. In MRI, multiple calls to the method
    returns the same frozen string object. We were allocating a new string on each call and not
    freezing it.
    nirvdrum committed Jun 21, 2016
    Copy the full SHA
    16178f3 View commit details
5 changes: 4 additions & 1 deletion test/truffle/compiler/pe/core/encoding_pe.rb
Original file line number Diff line number Diff line change
@@ -7,4 +7,7 @@
# GNU Lesser General Public License version 2.1

example "Encoding::US_ASCII.ascii_compatible?", true
example "Encoding::UTF_16BE.ascii_compatible?", false
example "Encoding::UTF_16BE.ascii_compatible?", false

example "Encoding::ISO_2022_JP.dummy?", true
example "Encoding::UTF_8.dummy?", false
Original file line number Diff line number Diff line change
@@ -1081,7 +1081,7 @@ public void initializeEncodingConstants() {
getContext().getJRubyRuntime().getEncodingService().defineEncodings(new EncodingService.EncodingDefinitionVisitor() {
@Override
public void defineEncoding(EncodingDB.Entry encodingEntry, byte[] name, int p, int end) {
DynamicObject re = EncodingNodes.newEncoding(encodingClass, null, name, p, end, encodingEntry.isDummy());
DynamicObject re = EncodingNodes.newEncoding(getContext(), encodingClass, null, name, p, end, encodingEntry.isDummy());
EncodingNodes.storeEncoding(encodingEntry.getIndex(), re);
}

Original file line number Diff line number Diff line change
@@ -129,7 +129,8 @@ private IRubyObject toJRuby(Object object) {
if (RubyGuards.isRubyString(object)) {
return getContext().getJRubyRuntime().newString(RopeOperations.toByteListCopy(StringOperations.rope((DynamicObject) object)));
} else if (RubyGuards.isRubyEncoding(object)) {
return getContext().getJRubyRuntime().getEncodingService().rubyEncodingFromObject(getContext().getJRubyRuntime().newString(Layouts.ENCODING.getName((DynamicObject) object)));
final Rope rope = StringOperations.rope(Layouts.ENCODING.getName((DynamicObject) object));
return getContext().getJRubyRuntime().getEncodingService().rubyEncodingFromObject(getContext().getJRubyRuntime().newString(RopeOperations.toByteListCopy(rope)));
} else {
throw new UnsupportedOperationException();
}
Original file line number Diff line number Diff line change
@@ -15,7 +15,6 @@
import com.oracle.truffle.api.object.dsl.Nullable;
import org.jcodings.Encoding;
import org.jruby.truffle.core.basicobject.BasicObjectLayout;
import org.jruby.util.ByteList;

@Layout
public interface EncodingLayout extends BasicObjectLayout {
@@ -25,7 +24,7 @@ DynamicObjectFactory createEncodingShape(DynamicObject logicalClass,

DynamicObject createEncoding(DynamicObjectFactory factory,
@Nullable Encoding encoding,
ByteList name,
DynamicObject name,
boolean dummy);

boolean isEncoding(DynamicObject object);
@@ -34,7 +33,7 @@ DynamicObject createEncoding(DynamicObjectFactory factory,
Encoding getEncoding(DynamicObject object);
void setEncoding(DynamicObject object, Encoding value);

ByteList getName(DynamicObject object);
DynamicObject getName(DynamicObject object);

boolean getDummy(DynamicObject object);

Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@
import org.jruby.truffle.core.cast.ToStrNodeGen;
import org.jruby.truffle.core.rope.CodeRange;
import org.jruby.truffle.core.rope.Rope;
import org.jruby.truffle.core.rope.RopeOperations;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.control.RaiseException;
@@ -94,8 +95,14 @@ public static void storeAlias(String aliasName, DynamicObject encoding) {
LOOKUP.put(aliasName.toLowerCase(Locale.ENGLISH), encoding);
}

public static DynamicObject newEncoding(DynamicObject encodingClass, Encoding encoding, byte[] name, int p, int end, boolean dummy) {
return createRubyEncoding(encodingClass, encoding, new ByteList(name, p, end), dummy);
@TruffleBoundary
public static DynamicObject newEncoding(RubyContext context, DynamicObject encodingClass, Encoding encoding, byte[] name, int p, int end, boolean dummy) {
// TODO (nirvdrum 21-Jun-16): We probably don't need to create a ByteList and two Ropes. Without any guarantees on the code range of the encoding name, however, we must be conservative.
final Rope rope = StringOperations.ropeFromByteList(new ByteList(name, p, end));
final Rope cachedRope = context.getRopeTable().getRope(rope.getBytes(), rope.getEncoding(), rope.getCodeRange());
final DynamicObject string = context.getFrozenStrings().getFrozenString(cachedRope);

return createRubyEncoding(encodingClass, encoding, string, dummy);
}

public static Object[] cloneEncodingList() {
@@ -106,19 +113,17 @@ public static Object[] cloneEncodingList() {
return clone;
}

public static DynamicObject createRubyEncoding(DynamicObject encodingClass, Encoding encoding, ByteList name, boolean dummy) {
public static DynamicObject createRubyEncoding(DynamicObject encodingClass, Encoding encoding, DynamicObject name, boolean dummy) {
return Layouts.ENCODING.createEncoding(Layouts.CLASS.getInstanceFactory(encodingClass), encoding, name, dummy);
}

@CoreMethod(names = "ascii_compatible?")
public abstract static class AsciiCompatibleNode extends CoreMethodArrayArgumentsNode {

@Specialization(guards = {
"encoding == cachedEncoding",
}, limit = "getCacheLimit()")
@Specialization(guards = "encoding == cachedEncoding", limit = "getCacheLimit()")
public boolean isCompatibleCached(DynamicObject encoding,
@Cached("encoding") DynamicObject cachedEncoding,
@Cached("isAsciiCompatible(encoding)") boolean isAsciiCompatible) {
@Cached("isAsciiCompatible(cachedEncoding)") boolean isAsciiCompatible) {
return isAsciiCompatible;
}

@@ -441,8 +446,25 @@ public DynamicObject localeCharacterMap() {
@CoreMethod(names = "dummy?")
public abstract static class DummyNode extends CoreMethodArrayArgumentsNode {

@Specialization
public boolean isDummy(DynamicObject encoding) {
@Specialization(guards = "encoding == cachedEncoding", limit = "getCacheLimit()")
public boolean isDummyCached(DynamicObject encoding,
@Cached("encoding") DynamicObject cachedEncoding,
@Cached("isDummy(cachedEncoding)") boolean isDummy) {
return isDummy;
}

@Specialization(contains = "isDummyCached")
public boolean isDummyUncached(DynamicObject encoding) {
return isDummy(encoding);
}

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

protected static boolean isDummy(DynamicObject encoding) {
assert RubyGuards.isRubyEncoding(encoding);

return Layouts.ENCODING.getDummy(encoding);
}
}
@@ -472,7 +494,7 @@ public Object encodingMap(VirtualFrame frame) {

final DynamicObject[] encodings = ENCODING_LIST;
for (int i = 0; i < encodings.length; i++) {
final Object upcased = upcaseNode.call(frame, createString(Layouts.ENCODING.getName(encodings[i])), "upcase", null);
final Object upcased = upcaseNode.call(frame, Layouts.ENCODING.getName(encodings[i]), "upcase", null);
final Object key = toSymNode.call(frame, upcased, "to_sym", null);
final Object value = newTupleNode.call(frame, coreLibrary().getTupleClass(), "create", null, nil(), i);

@@ -529,10 +551,11 @@ public Object indexLookup(DynamicObject[] encodings, Encoding encoding) {
return nil();
}

final ByteList encodingName = new ByteList(encoding.getName());
final Rope encodingNameRope = RopeOperations.create(encoding.getName(), ASCIIEncoding.INSTANCE, CodeRange.CR_UNKNOWN);

for (int i = 0; i < encodings.length; i++) {
if (Layouts.ENCODING.getName(encodings[i]).equals(encodingName)) {
final Rope nameRope = StringOperations.rope(Layouts.ENCODING.getName(encodings[i]));
if (nameRope.equals(encodingNameRope)) {
return i;
}
}
@@ -544,13 +567,11 @@ public Object indexLookup(DynamicObject[] encodings, Encoding encoding) {
@CoreMethod(names = { "name", "to_s" })
public abstract static class ToSNode extends CoreMethodArrayArgumentsNode {

@TruffleBoundary
@Specialization
public DynamicObject toS(DynamicObject encoding) {
final ByteList name = Layouts.ENCODING.getName(encoding).dup();
name.setEncoding(ASCIIEncoding.INSTANCE);
return createString(name);
return Layouts.ENCODING.getName(encoding);
}

}

@CoreMethod(names = "allocate", constructor = true)
Original file line number Diff line number Diff line change
@@ -18,6 +18,8 @@
import org.jcodings.Encoding;
import org.jcodings.EncodingDB;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.core.rope.Rope;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.util.ByteList;

public abstract class EncodingOperations {
@@ -29,7 +31,7 @@ public static Encoding getEncoding(DynamicObject rubyEncoding) {
// Bounded by the number of encodings
CompilerDirectives.transferToInterpreterAndInvalidate();

final ByteList name = Layouts.ENCODING.getName(rubyEncoding);
final Rope name = StringOperations.rope(Layouts.ENCODING.getName(rubyEncoding));
encoding = loadEncoding(name);
Layouts.ENCODING.setEncoding(rubyEncoding, encoding);
}
@@ -38,22 +40,22 @@ public static Encoding getEncoding(DynamicObject rubyEncoding) {
}

@TruffleBoundary
private static EncodingDB.Entry findEncodingEntry(ByteList bytes) {
return EncodingDB.getEncodings().get(bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getBegin() + bytes.getRealSize());
private static EncodingDB.Entry findEncodingEntry(Rope name) {
return EncodingDB.getEncodings().get(name.getBytes(), 0, name.byteLength());
}

@TruffleBoundary
private static EncodingDB.Entry findAliasEntry(ByteList bytes) {
return EncodingDB.getAliases().get(bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getBegin() + bytes.getRealSize());
private static EncodingDB.Entry findAliasEntry(Rope name) {
return EncodingDB.getAliases().get(name.getBytes(), 0, name.byteLength());
}

private static EncodingDB.Entry findEncodingOrAliasEntry(ByteList bytes) {
final EncodingDB.Entry e = findEncodingEntry(bytes);
return e != null ? e : findAliasEntry(bytes);
private static EncodingDB.Entry findEncodingOrAliasEntry(Rope name) {
final EncodingDB.Entry e = findEncodingEntry(name);
return e != null ? e : findAliasEntry(name);
}

@TruffleBoundary
private static Encoding loadEncoding(ByteList name) {
private static Encoding loadEncoding(Rope name) {
final EncodingDB.Entry entry = findEncodingOrAliasEntry(name);

if (entry == null) {