Skip to content

Commit

Permalink
TruffleStrings: move special CompareNode behavior on UTF16 and UTF32 …
Browse files Browse the repository at this point in the history
…to dedicated nodes.
  • Loading branch information
djoooooe committed Jan 13, 2022
1 parent 6510f5f commit 8925754
Show file tree
Hide file tree
Showing 11 changed files with 384 additions and 54 deletions.
6 changes: 5 additions & 1 deletion truffle/docs/TruffleStrings.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,12 @@ The list of currently available operations is:
Find the last occurrence of a given substring in a string and return its codepoint-based index.
* [LastByteIndexOfString](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/strings/TruffleString.LastByteIndexOfStringNode.html):
Find the last occurrence of a given substring in a string and return its byte-based index.
* [Compare](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/strings/TruffleString.CompareNode.html):
* [CompareBytes](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/strings/TruffleString.CompareBytesNode.html):
Compare two strings byte-by-byte.
* [CompareCharsUTF16](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/strings/TruffleString.CompareCharsUTF16Node.html):
Compare two UTF-16 strings char-by-char.
* [CompareIntsUTF32](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/strings/TruffleString.CompareIntsUTF32Node.html):
Compare two UTF-32 strings int-by-int.
* [RegionEqual](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/strings/TruffleString.RegionEqualNode.html):
Check if two strings are equal in a given region defined by a codepoint-based offset and length.
* [RegionEqualByteIndex](https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/strings/TruffleString.RegionEqualByteIndexNode.html):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@ abstract static class CompareTStringNode extends Node {

@Specialization
int bench(TruffleString a, TruffleString b,
@Cached TruffleString.CompareNode compareNode) {
return compareNode.execute(a, b, TruffleString.Encoding.UTF_16);
@Cached TruffleString.CompareCharsUTF16Node compareNode) {
return compareNode.execute(a, b);
}

@Specialization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,9 @@ public void testFromByteArray() throws Exception {
}
sbCMP.appendCodePointUncached(codepoints[codepoints.length - 1] - 1);
TruffleString cmp = sbCMP.toStringUncached();
Assert.assertEquals(0, s.compareUncached(s, encoding));
Assert.assertTrue(s.compareUncached(cmp, encoding) > 0);
Assert.assertTrue(cmp.compareUncached(s, encoding) < 0);
Assert.assertEquals(0, s.compareBytesUncached(s, encoding));
Assert.assertTrue(s.compareBytesUncached(cmp, encoding) > 0);
Assert.assertTrue(cmp.compareBytesUncached(s, encoding) < 0);
s.toJavaStringUncached();
TruffleStringIterator it = s.createCodePointIteratorUncached(encoding);
Assert.assertEquals(codepoints.length, s.codePointLengthUncached(encoding));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ public interface TestSE {
void run(AbstractTruffleString a, TruffleString.Encoding encoding);
}

public interface TestSS {
void run(AbstractTruffleString a, AbstractTruffleString b);
}

public interface TestSEE {
void run(AbstractTruffleString a, TruffleString.Encoding expectedEncoding, TruffleString.Encoding targetEncoding);
}
Expand Down Expand Up @@ -257,6 +261,11 @@ public static void checkNullSEE(TestSEE test) throws Exception {
expectNullPointerException(() -> test.run(S_UTF8, UTF_8, null));
}

public static void checkNullSS(TestSS test) throws Exception {
expectNullPointerException(() -> test.run(null, S_UTF8));
expectNullPointerException(() -> test.run(S_UTF8, null));
}

public static void checkNullSSE(TestSSE test) throws Exception {
expectNullPointerException(() -> test.run(null, S_UTF8, UTF_8));
expectNullPointerException(() -> test.run(S_UTF8, null, UTF_8));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,38 +57,63 @@
@RunWith(Parameterized.class)
public class TStringCompareTest extends TStringTestBase {

@Parameter public TruffleString.CompareNode node;
@Parameter(0) public TruffleString.CompareBytesNode node;
@Parameter(1) public TruffleString.CompareCharsUTF16Node nodeUTF16;
@Parameter(2) public TruffleString.CompareIntsUTF32Node nodeUTF32;

@Parameters(name = "{0}")
public static Iterable<TruffleString.CompareNode> data() {
return Arrays.asList(TruffleString.CompareNode.create(), TruffleString.CompareNode.getUncached());
public static Iterable<Object[]> data() {
return Arrays.asList(
new Object[]{TruffleString.CompareBytesNode.create(), TruffleString.CompareCharsUTF16Node.create(), TruffleString.CompareIntsUTF32Node.create()},
new Object[]{TruffleString.CompareBytesNode.getUncached(), TruffleString.CompareCharsUTF16Node.getUncached(), TruffleString.CompareIntsUTF32Node.getUncached()});
}

@Test
public void testAll() throws Exception {
forAllStrings(true, (a, arrayA, codeRangeA, isValidA, encodingA, codepointsA, byteIndicesA) -> {
forAllStrings(new TruffleString.Encoding[]{encodingA}, true, (b, arrayB, codeRangeB, isValidB, encodingB, codepointsB, byteIndicesB) -> {
Assert.assertEquals(compare(codepointsA, codepointsB), node.execute(a, b, encodingA));
Assert.assertEquals(compare(arrayA, arrayB), node.execute(a, b, encodingA));
if (encodingA == TruffleString.Encoding.UTF_16) {
Assert.assertEquals(compare(codepointsA, codepointsB), nodeUTF16.execute(a, b));
} else if (encodingA == TruffleString.Encoding.UTF_32) {
Assert.assertEquals(compare(codepointsA, codepointsB), nodeUTF32.execute(a, b));
}
});
});
}

private static int compare(byte[] a, byte[] b) {
for (int i = 0; i < Math.min(a.length, b.length); i++) {
int cmp = Byte.toUnsignedInt(a[i]) - Byte.toUnsignedInt(b[i]);
if (cmp != 0) {
return cmp > 0 ? 1 : -1;
}
}
return compareTail(a.length, b.length);
}

private static int compare(int[] a, int[] b) {
for (int i = 0; i < Math.min(a.length, b.length); i++) {
int cmp = a[i] - b[i];
if (cmp != 0) {
return cmp > 0 ? 1 : -1;
}
}
if (a.length == b.length) {
return compareTail(a.length, b.length);
}

private static int compareTail(int lengthA, int lengthB) {
if (lengthA == lengthB) {
return 0;
} else {
return a.length < b.length ? -1 : 1;
return lengthA < lengthB ? -1 : 1;
}
}

@Test
public void testNull() throws Exception {
checkNullSSE((s1, s2, e) -> node.execute(s1, s2, e));
checkNullSS((s1, s2) -> nodeUTF16.execute(s1, s2));
checkNullSS((s1, s2) -> nodeUTF32.execute(s1, s2));
}
}
34 changes: 26 additions & 8 deletions truffle/src/com.oracle.truffle.api.strings/snapshot.sigtest
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ meth public final int codePointAtByteIndexUncached(int,com.oracle.truffle.api.st
meth public final int codePointAtIndexUncached(int,com.oracle.truffle.api.strings.TruffleString$Encoding)
meth public final int codePointIndexToByteIndexUncached(int,int,com.oracle.truffle.api.strings.TruffleString$Encoding)
meth public final int codePointLengthUncached(com.oracle.truffle.api.strings.TruffleString$Encoding)
meth public final int compareUncached(com.oracle.truffle.api.strings.AbstractTruffleString,com.oracle.truffle.api.strings.TruffleString$Encoding)
meth public final int compareBytesUncached(com.oracle.truffle.api.strings.AbstractTruffleString,com.oracle.truffle.api.strings.TruffleString$Encoding)
meth public final int compareCharsUTF16Uncached(com.oracle.truffle.api.strings.AbstractTruffleString)
meth public final int compareIntsUTF32Uncached(com.oracle.truffle.api.strings.AbstractTruffleString)
meth public final int hashCode()
meth public final int hashCodeUncached(com.oracle.truffle.api.strings.TruffleString$Encoding)
meth public final int indexOfCodePointUncached(int,int,int,com.oracle.truffle.api.strings.TruffleString$Encoding)
Expand Down Expand Up @@ -250,7 +252,9 @@ innr public abstract static CodePointAtIndexNode
innr public abstract static CodePointIndexToByteIndexNode
innr public abstract static CodePointLengthNode
innr public abstract static CodeRangeEqualsNode
innr public abstract static CompareNode
innr public abstract static CompareBytesNode
innr public abstract static CompareCharsUTF16Node
innr public abstract static CompareIntsUTF32Node
innr public abstract static ConcatNode
innr public abstract static CopyToByteArrayNode
innr public abstract static CopyToNativeMemoryNode
Expand Down Expand Up @@ -410,11 +414,25 @@ meth public static com.oracle.truffle.api.strings.TruffleString$CodeRangeEqualsN
meth public static com.oracle.truffle.api.strings.TruffleString$CodeRangeEqualsNode getUncached()
supr com.oracle.truffle.api.nodes.Node

CLSS public abstract static com.oracle.truffle.api.strings.TruffleString$CompareNode
CLSS public abstract static com.oracle.truffle.api.strings.TruffleString$CompareBytesNode
outer com.oracle.truffle.api.strings.TruffleString
meth public abstract int execute(com.oracle.truffle.api.strings.AbstractTruffleString,com.oracle.truffle.api.strings.AbstractTruffleString,com.oracle.truffle.api.strings.TruffleString$Encoding)
meth public static com.oracle.truffle.api.strings.TruffleString$CompareNode create()
meth public static com.oracle.truffle.api.strings.TruffleString$CompareNode getUncached()
meth public static com.oracle.truffle.api.strings.TruffleString$CompareBytesNode create()
meth public static com.oracle.truffle.api.strings.TruffleString$CompareBytesNode getUncached()
supr com.oracle.truffle.api.nodes.Node

CLSS public abstract static com.oracle.truffle.api.strings.TruffleString$CompareCharsUTF16Node
outer com.oracle.truffle.api.strings.TruffleString
meth public abstract int execute(com.oracle.truffle.api.strings.AbstractTruffleString,com.oracle.truffle.api.strings.AbstractTruffleString)
meth public static com.oracle.truffle.api.strings.TruffleString$CompareCharsUTF16Node create()
meth public static com.oracle.truffle.api.strings.TruffleString$CompareCharsUTF16Node getUncached()
supr com.oracle.truffle.api.nodes.Node

CLSS public abstract static com.oracle.truffle.api.strings.TruffleString$CompareIntsUTF32Node
outer com.oracle.truffle.api.strings.TruffleString
meth public abstract int execute(com.oracle.truffle.api.strings.AbstractTruffleString,com.oracle.truffle.api.strings.AbstractTruffleString)
meth public static com.oracle.truffle.api.strings.TruffleString$CompareIntsUTF32Node create()
meth public static com.oracle.truffle.api.strings.TruffleString$CompareIntsUTF32Node getUncached()
supr com.oracle.truffle.api.nodes.Node

CLSS public abstract static com.oracle.truffle.api.strings.TruffleString$ConcatNode
Expand Down Expand Up @@ -560,7 +578,7 @@ meth public static com.oracle.truffle.api.strings.TruffleString$Encoding fromJCo
meth public static com.oracle.truffle.api.strings.TruffleString$Encoding valueOf(java.lang.String)
meth public static com.oracle.truffle.api.strings.TruffleString$Encoding[] values()
supr java.lang.Enum<com.oracle.truffle.api.strings.TruffleString$Encoding>
hfds EMPTY_STRINGS,ENCODINGS_TABLE,J_CODINGS_NAME_MAP,J_CODINGS_TABLE,MAX_COMPATIBLE_CODE_RANGE,NATURAL_STRIDE,id,jCoding,maxCompatibleCodeRange,name,naturalStride
hfds EMPTY_STRINGS,ENCODINGS_TABLE,J_CODINGS_NAME_MAP,J_CODINGS_TABLE,MAX_COMPATIBLE_CODE_RANGE,id,jCoding,maxCompatibleCodeRange,name,naturalStride

CLSS public abstract static com.oracle.truffle.api.strings.TruffleString$EqualNode
outer com.oracle.truffle.api.strings.TruffleString
Expand Down Expand Up @@ -826,7 +844,7 @@ meth public static com.oracle.truffle.api.strings.TruffleString$WithMask create(
meth public static com.oracle.truffle.api.strings.TruffleString$WithMask createUTF16(com.oracle.truffle.api.strings.AbstractTruffleString,char[])
meth public static com.oracle.truffle.api.strings.TruffleString$WithMask createUTF32(com.oracle.truffle.api.strings.AbstractTruffleString,int[])
supr java.lang.Object
hfds mask,string
hfds DUMMY,mask,string

CLSS public final com.oracle.truffle.api.strings.TruffleStringBuilder
innr public abstract static AppendByteNode
Expand Down Expand Up @@ -929,7 +947,7 @@ hcls AppendArrayIntlNodeGen,AppendByteNodeGen,AppendCharArrayIntlNodeGen,AppendC
CLSS public final com.oracle.truffle.api.strings.TruffleStringFactory
cons public init()
supr java.lang.Object
hcls AsManagedNodeGen,AsTruffleStringNodeGen,ByteIndexOfAnyByteNodeGen,ByteIndexOfCodePointNodeGen,ByteIndexOfStringNodeGen,ByteLengthOfCodePointNodeGen,CharIndexOfAnyCharUTF16NodeGen,CodePointAtByteIndexNodeGen,CodePointAtIndexNodeGen,CodePointIndexToByteIndexNodeGen,CodePointLengthNodeGen,CodeRangeEqualsNodeGen,CompareNodeGen,ConcatNodeGen,CopyToByteArrayNodeGen,CopyToNativeMemoryNodeGen,CreateBackwardCodePointIteratorNodeGen,CreateCodePointIteratorNodeGen,EqualNodeGen,ForceEncodingNodeGen,FromByteArrayNodeGen,FromCharArrayUTF16NodeGen,FromCodePointNodeGen,FromIntArrayUTF32NodeGen,FromJavaStringNodeGen,FromLongNodeGen,FromNativePointerNodeGen,GetByteCodeRangeNodeGen,GetCodeRangeNodeGen,GetInternalByteArrayNodeGen,GetInternalNativePointerNodeGen,HashCodeNodeGen,IndexOfCodePointNodeGen,IndexOfStringNodeGen,IntIndexOfAnyIntUTF32NodeGen,IsValidNodeGen,LastByteIndexOfCodePointNodeGen,LastByteIndexOfStringNodeGen,LastIndexOfCodePointNodeGen,LastIndexOfStringNodeGen,MaterializeNodeGen,ParseDoubleNodeGen,ParseIntNodeGen,ParseLongNodeGen,ReadByteNodeGen,ReadCharUTF16NodeGen,RegionEqualByteIndexNodeGen,RegionEqualNodeGen,RepeatNodeGen,SubstringByteIndexNodeGen,SubstringNodeGen,SwitchEncodingNodeGen,ToIndexableNodeGen,ToJavaStringNodeGen
hcls AsManagedNodeGen,AsTruffleStringNodeGen,ByteIndexOfAnyByteNodeGen,ByteIndexOfCodePointNodeGen,ByteIndexOfStringNodeGen,ByteLengthOfCodePointNodeGen,CharIndexOfAnyCharUTF16NodeGen,CodePointAtByteIndexNodeGen,CodePointAtIndexNodeGen,CodePointIndexToByteIndexNodeGen,CodePointLengthNodeGen,CodeRangeEqualsNodeGen,CompareBytesNodeGen,CompareCharsUTF16NodeGen,CompareIntsUTF32NodeGen,ConcatNodeGen,CopyToByteArrayNodeGen,CopyToNativeMemoryNodeGen,CreateBackwardCodePointIteratorNodeGen,CreateCodePointIteratorNodeGen,EqualNodeGen,ForceEncodingNodeGen,FromByteArrayNodeGen,FromCharArrayUTF16NodeGen,FromCodePointNodeGen,FromIntArrayUTF32NodeGen,FromJavaStringNodeGen,FromLongNodeGen,FromNativePointerNodeGen,GetByteCodeRangeNodeGen,GetCodeRangeNodeGen,GetInternalByteArrayNodeGen,GetInternalNativePointerNodeGen,HashCodeNodeGen,IndexOfCodePointNodeGen,IndexOfStringNodeGen,IntIndexOfAnyIntUTF32NodeGen,IsValidNodeGen,LastByteIndexOfCodePointNodeGen,LastByteIndexOfStringNodeGen,LastIndexOfCodePointNodeGen,LastIndexOfStringNodeGen,MaterializeNodeGen,ParseDoubleNodeGen,ParseIntNodeGen,ParseLongNodeGen,ReadByteNodeGen,ReadCharUTF16NodeGen,RegionEqualByteIndexNodeGen,RegionEqualNodeGen,RepeatNodeGen,SubstringByteIndexNodeGen,SubstringNodeGen,SwitchEncodingNodeGen,ToIndexableNodeGen,ToJavaStringNodeGen

CLSS public final com.oracle.truffle.api.strings.TruffleStringIterator
innr public abstract static NextNode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -766,13 +766,33 @@ public final int lastByteIndexOfStringUncached(TruffleString.WithMask b, int fro
}

/**
* Shorthand for calling the uncached version of {@link TruffleString.CompareNode}.
* Shorthand for calling the uncached version of {@link TruffleString.CompareBytesNode}.
*
* @since 22.1
*/
@TruffleBoundary
public final int compareUncached(AbstractTruffleString b, TruffleString.Encoding expectedEncoding) {
return TruffleString.CompareNode.getUncached().execute(this, b, expectedEncoding);
public final int compareBytesUncached(AbstractTruffleString b, TruffleString.Encoding expectedEncoding) {
return TruffleString.CompareBytesNode.getUncached().execute(this, b, expectedEncoding);
}

/**
* Shorthand for calling the uncached version of {@link TruffleString.CompareCharsUTF16Node}.
*
* @since 22.1
*/
@TruffleBoundary
public final int compareCharsUTF16Uncached(AbstractTruffleString b) {
return TruffleString.CompareCharsUTF16Node.getUncached().execute(this, b);
}

/**
* Shorthand for calling the uncached version of {@link TruffleString.CompareIntsUTF32Node}.
*
* @since 22.1
*/
@TruffleBoundary
public final int compareIntsUTF32Uncached(AbstractTruffleString b) {
return TruffleString.CompareIntsUTF32Node.getUncached().execute(this, b);
}

/**
Expand Down
Loading

0 comments on commit 8925754

Please sign in to comment.