Skip to content

Commit

Permalink
Showing 1 changed file with 68 additions and 68 deletions.
136 changes: 68 additions & 68 deletions truffle/src/main/java/org/jruby/truffle/core/string/StringNodes.java
Original file line number Diff line number Diff line change
@@ -124,6 +124,7 @@
import org.jruby.truffle.core.rope.RopeNodesFactory;
import org.jruby.truffle.core.rope.RopeOperations;
import org.jruby.truffle.core.rope.SubstringRope;
import org.jruby.truffle.core.string.StringNodesFactory.StringAreComparableNodeGen;
import org.jruby.truffle.language.NotProvided;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;
@@ -2957,13 +2958,71 @@ private String formatError(int start) {

}

@NodeChildren({ @NodeChild("first"), @NodeChild("second") })
public static abstract class StringAreComparableNode extends RubyNode {

public abstract boolean executeAreComparable(DynamicObject first, DynamicObject second);

@Specialization
protected boolean areComparable(DynamicObject first, DynamicObject second,
@Cached("createBinaryProfile()") ConditionProfile sameEncodingProfile,
@Cached("createBinaryProfile()") ConditionProfile firstStringEmptyProfile,
@Cached("createBinaryProfile()") ConditionProfile secondStringEmptyProfile,
@Cached("createBinaryProfile()") ConditionProfile firstStringCR7BitProfile,
@Cached("createBinaryProfile()") ConditionProfile secondStringCR7BitProfile,
@Cached("createBinaryProfile()") ConditionProfile firstStringAsciiCompatible,
@Cached("createBinaryProfile()") ConditionProfile secondStringAsciiCompatible) {
final Rope firstRope = Layouts.STRING.getRope(first);
final Rope secondRope = Layouts.STRING.getRope(second);

if (sameEncodingProfile.profile(firstRope.getEncoding() == secondRope.getEncoding())) {
return true;
}

if (firstStringEmptyProfile.profile(firstRope.isEmpty())) {
return true;
}

if (secondStringEmptyProfile.profile(secondRope.isEmpty())) {
return true;
}

final CodeRange firstCodeRange = firstRope.getCodeRange();
final CodeRange secondCodeRange = secondRope.getCodeRange();

if (firstStringCR7BitProfile.profile(firstCodeRange == CodeRange.CR_7BIT)) {
if (secondStringCR7BitProfile.profile(secondCodeRange == CodeRange.CR_7BIT)) {
return true;
}

if (secondStringAsciiCompatible.profile(secondRope.getEncoding().isAsciiCompatible())) {
return true;
}
}

if (secondStringCR7BitProfile.profile(secondCodeRange == CodeRange.CR_7BIT)) {
if (firstStringAsciiCompatible.profile(firstRope.getEncoding().isAsciiCompatible())) {
return true;
}
}

return false;
}

}

@Primitive(name = "string_equal", needsSelf = true)
@ImportStatic(StringGuards.class)
public static abstract class StringEqualPrimitiveNode extends PrimitiveArrayArgumentsNode {

@Child StringAreComparableNode areComparableNode;

This comment has been minimized.

Copy link
@pitr-ch

pitr-ch Jun 11, 2016

Member

Wouldn't this be better @Cached on each specialisation?

This comment has been minimized.

Copy link
@eregon

eregon Jun 11, 2016

Author Member

Maybe, one problem is it's used in guards and @Cached does not adopt it the node, which makes replacements fail.
I would guess encodings are rather stable for a given code location so I think in practice it's fine to have only one.

This comment has been minimized.

Copy link
@pitr-ch

pitr-ch Jun 11, 2016

Member

Yeah, I've run into that :/, the creation method used by @Cached could adopt it with insert though. But as you said it does not matter in this case.


public abstract boolean executeStringEqual(DynamicObject string, DynamicObject other);

@Specialization(guards = "ropeReferenceEqual(string, other)")
@Specialization(guards = {
"isRubyString(other)",
"ropeReferenceEqual(string, other)"
})
public boolean stringEqualsRopeEquals(DynamicObject string, DynamicObject other) {
return true;
}
@@ -2981,33 +3040,19 @@ public boolean stringEqualsBytesEquals(DynamicObject string, DynamicObject other
"isRubyString(other)",
"!ropeReferenceEqual(string, other)",
"!bytesReferenceEqual(string, other)",
"!areComparable(string, other, sameEncodingProfile, firstStringEmptyProfile, secondStringEmptyProfile, firstStringCR7BitProfile, secondStringCR7BitProfile, firstStringAsciiCompatible, secondStringAsciiCompatible)"
"!areComparable(string, other)"
})
public boolean stringEqualNotComparable(DynamicObject string, DynamicObject other,
@Cached("createBinaryProfile()") ConditionProfile sameEncodingProfile,
@Cached("createBinaryProfile()") ConditionProfile firstStringEmptyProfile,
@Cached("createBinaryProfile()") ConditionProfile secondStringEmptyProfile,
@Cached("createBinaryProfile()") ConditionProfile firstStringCR7BitProfile,
@Cached("createBinaryProfile()") ConditionProfile secondStringCR7BitProfile,
@Cached("createBinaryProfile()") ConditionProfile firstStringAsciiCompatible,
@Cached("createBinaryProfile()") ConditionProfile secondStringAsciiCompatible) {
public boolean stringEqualNotComparable(DynamicObject string, DynamicObject other) {
return false;
}

@Specialization(guards = {
"isRubyString(other)",
"!ropeReferenceEqual(string, other)",
"!bytesReferenceEqual(string, other)",
"areComparable(string, other, sameEncodingProfile, firstStringEmptyProfile, secondStringEmptyProfile, firstStringCR7BitProfile, secondStringCR7BitProfile, firstStringAsciiCompatible, secondStringAsciiCompatible)"
"areComparable(string, other)"
})
public boolean equal(DynamicObject string, DynamicObject other,
@Cached("createBinaryProfile()") ConditionProfile sameEncodingProfile,
@Cached("createBinaryProfile()") ConditionProfile firstStringEmptyProfile,
@Cached("createBinaryProfile()") ConditionProfile secondStringEmptyProfile,
@Cached("createBinaryProfile()") ConditionProfile firstStringCR7BitProfile,
@Cached("createBinaryProfile()") ConditionProfile secondStringCR7BitProfile,
@Cached("createBinaryProfile()") ConditionProfile firstStringAsciiCompatible,
@Cached("createBinaryProfile()") ConditionProfile secondStringAsciiCompatible,
@Cached("createBinaryProfile()") ConditionProfile differentSizeProfile) {

final Rope a = Layouts.STRING.getRope(string);
@@ -3020,65 +3065,20 @@ public boolean equal(DynamicObject string, DynamicObject other,
return a.equals(b);
}

protected boolean areComparable(DynamicObject first, DynamicObject second,
ConditionProfile sameEncodingProfile,
ConditionProfile firstStringEmptyProfile,
ConditionProfile secondStringEmptyProfile,
ConditionProfile firstStringCR7BitProfile,
ConditionProfile secondStringCR7BitProfile,
ConditionProfile firstStringAsciiCompatible,
ConditionProfile secondStringAsciiCompatible) {
assert RubyGuards.isRubyString(first);
assert RubyGuards.isRubyString(second);

final Rope firstRope = Layouts.STRING.getRope(first);
final Rope secondRope = Layouts.STRING.getRope(second);

if (sameEncodingProfile.profile(firstRope.getEncoding() == secondRope.getEncoding())) {
return true;
}

if (firstStringEmptyProfile.profile(firstRope.isEmpty())) {
return true;
}

if (secondStringEmptyProfile.profile(secondRope.isEmpty())) {
return true;
}

final CodeRange firstCodeRange = firstRope.getCodeRange();
final CodeRange secondCodeRange = secondRope.getCodeRange();

if (firstStringCR7BitProfile.profile(firstCodeRange == CodeRange.CR_7BIT)) {
if (secondStringCR7BitProfile.profile(secondCodeRange == CodeRange.CR_7BIT)) {
return true;
}

if (secondStringAsciiCompatible.profile(secondRope.getEncoding().isAsciiCompatible())) {
return true;
}
}

if (secondStringCR7BitProfile.profile(secondCodeRange == CodeRange.CR_7BIT)) {
if (firstStringAsciiCompatible.profile(firstRope.getEncoding().isAsciiCompatible())) {
return true;
}
protected boolean areComparable(DynamicObject first, DynamicObject second) {
if (areComparableNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
areComparableNode = insert(StringAreComparableNodeGen.create(null, null));
}

return false;
return areComparableNode.executeAreComparable(first, second);
}

protected static boolean ropeReferenceEqual(DynamicObject first, DynamicObject second) {
assert RubyGuards.isRubyString(first);
assert RubyGuards.isRubyString(second);

return rope(first) == rope(second);
}

protected static boolean bytesReferenceEqual(DynamicObject first, DynamicObject second) {
assert RubyGuards.isRubyString(first);
assert RubyGuards.isRubyString(second);

final Rope firstRope = rope(first);
final Rope secondRope = rope(second);

0 comments on commit 6f670b6

Please sign in to comment.