Skip to content

Commit 74de527

Browse files
committed
[GR-44829] TruffleStrings: introduce specialized TruffleStringBuilder types for better performance on UTF encodings.
PullRequest: graal/14397
2 parents 92bd8c4 + a9a82a7 commit 74de527

File tree

13 files changed

+1132
-427
lines changed

13 files changed

+1132
-427
lines changed

truffle/CHANGELOG.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,19 @@
22

33
This changelog summarizes major changes between Truffle versions relevant to languages implementors building upon the Truffle framework. The main focus is on APIs exported by Truffle.
44

5-
## 23.1.0
5+
## Version 23.1.0
66

77
* GR-45123 Added `GenerateInline#inlineByDefault` to force usage of inlined node variant even when the node has also a cached variant (`@GenerateCached(true)`).
88
* GR-45036 Improved IGV IR dumping. Dump folders for Truffle now include the compilation tier to differentiate compilations better. Inlined IR graphs are now additionally dumped in separate folders if dump level is >= 2.
99
* GR-45036 Improved IGV AST dumping. The Truffle AST is now dumped as part of the IR dump folder. The dumped AST tree now shows all inlined ASTS in a single tree. Individual functions can be grouped using the "Cluster nodes" function in IGV (top status bar). Root nodes now display their name e.g. `SLFunctionBody (root add)`. Every AST node now has a property `graalIRNode` that allows to find the corresponding Graal IR constant if there is one.
1010
* GR-45284 Added Graal debug options `TruffleTrustedNonNullCast` and `TruffleTrustedTypeCast` that allow disabling trusted non-null and type casts in Truffle, respectively. Note that disabling trusted type casts effectively disables non-null casts, too.
11-
## Version 23.1.0
12-
1311
* GR-44211 Added `TruffleLanguage.Env#newTruffleThreadBuilder(Runnable)` to create a builder for threads that have access to the appropriate `TruffleContext`. All existing `TruffleLanguage.Env#createThread` methods have been deprecated. On top of what the deprecated methods provided, the builder now allows to specify `beforeEnter` and `afterLeave` callbacks for the created threads.
1412
* GR-44211 Added `TruffleContext#leaveAndEnter(Node, Interrupter, InterruptibleFunction, Object)` to be able to interrupt the function run when the context is not entered. The exisiting API `TruffleContext#leaveAndEnter(Node, Supplier)` is deprecated.
1513
* GR-44211 Removed the deprecated method `TruffleSafepoint#setBlocked(Node, Interrupter, Interruptible, Object, Runnable, Runnable)`.
1614
* GR-44211 Added `TruffleSafepoint#setBlocked(Node, Interrupter, Interruptible, Object, Runnable, Consumer)`. It replaces the method `TruffleSafepoint#setBlockedWithException(Node, Interrupter, Interruptible, Object, Runnable, Consumer)` that is now deprecated.
1715
* GR-44211 Added `TruffleSafepoint#setBlockedFunction(Node, Interrupter, InterruptibleFunction, Object, Runnable, Consumer)` to be able to return an object from the interruptible functional method.
1816
* GR-44211 Added `TruffleSafepoint#setBlockedThreadInterruptibleFunction(Node, InterruptibleFunction, Object)` as a short-cut method to allow setting the blocked status for methods that throw `InterruptedException` and support interrupting using `Thread#interrupt()`.
19-
17+
* GR-44829 TruffleStrings: added specialized TruffleStringBuilder types for better performance on UTF encodings.
2018

2119

2220
## Version 23.0.0

truffle/src/com.oracle.truffle.api.strings.test/src/com/oracle/truffle/api/strings/test/TStringUTF16Tests.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
import org.junit.Test;
4848

4949
import com.oracle.truffle.api.strings.TruffleString;
50+
import com.oracle.truffle.api.strings.TruffleStringBuilder;
51+
import com.oracle.truffle.api.strings.TruffleStringBuilderUTF16;
5052
import com.oracle.truffle.api.strings.TruffleStringIterator;
5153

5254
public class TStringUTF16Tests extends TStringTestBase {
@@ -132,4 +134,10 @@ public void testBrokenUTF16ToUTF8() {
132134
byte[] actualUTF8Bytes = utf8.copyToByteArrayUncached(TruffleString.Encoding.UTF_8);
133135
Assert.assertArrayEquals(Arrays.toString(actualUTF8Bytes), expectedUTF8Bytes, actualUTF8Bytes);
134136
}
137+
138+
@Test(expected = OutOfMemoryError.class)
139+
public void testStringBuilderAppendCodePoint() {
140+
TruffleStringBuilderUTF16 sb = TruffleStringBuilder.createUTF16();
141+
sb.appendCodePointUncached(Character.MAX_CODE_POINT, Integer.MAX_VALUE - 10, false);
142+
}
135143
}

truffle/src/com.oracle.truffle.api.strings.test/src/com/oracle/truffle/api/strings/test/TStringUTF8Tests.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646

4747
import java.nio.charset.StandardCharsets;
4848

49+
import com.oracle.truffle.api.strings.TruffleStringBuilder;
50+
import com.oracle.truffle.api.strings.TruffleStringBuilderUTF8;
4951
import org.graalvm.shadowed.org.jcodings.specific.UTF8Encoding;
5052
import org.junit.Assert;
5153
import org.junit.Assume;
@@ -228,4 +230,10 @@ public void testIteratorPrev() {
228230
it.previousUncached();
229231
Assert.assertEquals(5, it.getByteIndex());
230232
}
233+
234+
@Test(expected = OutOfMemoryError.class)
235+
public void testStringBuilderAppendCodePoint() {
236+
TruffleStringBuilderUTF8 sb = TruffleStringBuilder.createUTF8();
237+
sb.appendCodePointUncached(Character.MAX_CODE_POINT, Integer.MAX_VALUE - 10, false);
238+
}
231239
}

truffle/src/com.oracle.truffle.api.strings/snapshot.sigtest

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ meth public static com.oracle.truffle.api.strings.TruffleString$WithMask$CreateU
994994
meth public static com.oracle.truffle.api.strings.TruffleString$WithMask$CreateUTF32Node getUncached()
995995
supr com.oracle.truffle.api.nodes.Node
996996

997-
CLSS public final com.oracle.truffle.api.strings.TruffleStringBuilder
997+
CLSS public abstract com.oracle.truffle.api.strings.TruffleStringBuilder
998998
innr public abstract static AppendByteNode
999999
innr public abstract static AppendCharUTF16Node
10001000
innr public abstract static AppendCodePointNode
@@ -1004,26 +1004,32 @@ innr public abstract static AppendLongNumberNode
10041004
innr public abstract static AppendStringNode
10051005
innr public abstract static AppendSubstringByteIndexNode
10061006
innr public abstract static ToStringNode
1007-
meth public boolean isEmpty()
1008-
meth public com.oracle.truffle.api.strings.TruffleString toStringUncached()
1009-
meth public int byteLength()
1010-
meth public java.lang.String toString()
1007+
meth public final boolean isEmpty()
1008+
meth public final com.oracle.truffle.api.strings.TruffleString toStringUncached()
1009+
meth public final int byteLength()
1010+
meth public final java.lang.String toString()
1011+
meth public final void appendByteUncached(byte)
1012+
meth public final void appendCharUTF16Uncached(char)
1013+
meth public final void appendCodePointUncached(int)
1014+
meth public final void appendCodePointUncached(int,int)
1015+
meth public final void appendCodePointUncached(int,int,boolean)
1016+
meth public final void appendIntNumberUncached(int)
1017+
meth public final void appendJavaStringUTF16Uncached(java.lang.String)
1018+
meth public final void appendJavaStringUTF16Uncached(java.lang.String,int,int)
1019+
meth public final void appendLongNumberUncached(long)
1020+
meth public final void appendStringUncached(com.oracle.truffle.api.strings.TruffleString)
1021+
meth public final void appendSubstringByteIndexUncached(com.oracle.truffle.api.strings.TruffleString,int,int)
10111022
meth public static com.oracle.truffle.api.strings.TruffleStringBuilder create(com.oracle.truffle.api.strings.TruffleString$Encoding)
10121023
meth public static com.oracle.truffle.api.strings.TruffleStringBuilder create(com.oracle.truffle.api.strings.TruffleString$Encoding,int)
1013-
meth public void appendByteUncached(byte)
1014-
meth public void appendCharUTF16Uncached(char)
1015-
meth public void appendCodePointUncached(int)
1016-
meth public void appendCodePointUncached(int,int)
1017-
meth public void appendCodePointUncached(int,int,boolean)
1018-
meth public void appendIntNumberUncached(int)
1019-
meth public void appendJavaStringUTF16Uncached(java.lang.String)
1020-
meth public void appendJavaStringUTF16Uncached(java.lang.String,int,int)
1021-
meth public void appendLongNumberUncached(long)
1022-
meth public void appendStringUncached(com.oracle.truffle.api.strings.TruffleString)
1023-
meth public void appendSubstringByteIndexUncached(com.oracle.truffle.api.strings.TruffleString,int,int)
1024+
meth public static com.oracle.truffle.api.strings.TruffleStringBuilderUTF16 createUTF16()
1025+
meth public static com.oracle.truffle.api.strings.TruffleStringBuilderUTF16 createUTF16(int)
1026+
meth public static com.oracle.truffle.api.strings.TruffleStringBuilderUTF32 createUTF32()
1027+
meth public static com.oracle.truffle.api.strings.TruffleStringBuilderUTF32 createUTF32(int)
1028+
meth public static com.oracle.truffle.api.strings.TruffleStringBuilderUTF8 createUTF8()
1029+
meth public static com.oracle.truffle.api.strings.TruffleStringBuilderUTF8 createUTF8(int)
10241030
supr java.lang.Object
1025-
hfds buf,codePointLength,codeRange,encoding,length,stride
1026-
hcls AppendArrayIntlNode,AppendCodePointIntlNode
1031+
hfds DEFAULT_INITIAL_CAPACITY,buf,codePointLength,codeRange,encoding,length,stride
1032+
hcls AppendCodePointIntlNode
10271033

10281034
CLSS public abstract static com.oracle.truffle.api.strings.TruffleStringBuilder$AppendByteNode
10291035
outer com.oracle.truffle.api.strings.TruffleStringBuilder
@@ -1095,8 +1101,16 @@ supr com.oracle.truffle.api.nodes.Node
10951101
CLSS public final com.oracle.truffle.api.strings.TruffleStringBuilderFactory
10961102
cons public init()
10971103
supr java.lang.Object
1098-
hfds COMPACTION_LEVEL_VALUES
1099-
hcls AppendArrayIntlNodeGen,AppendByteNodeGen,AppendCharUTF16NodeGen,AppendCodePointIntlNodeGen,AppendCodePointNodeGen,AppendIntNumberNodeGen,AppendJavaStringUTF16NodeGen,AppendLongNumberNodeGen,AppendStringNodeGen,AppendSubstringByteIndexNodeGen,ToStringNodeGen
1104+
hcls AppendByteNodeGen,AppendCharUTF16NodeGen,AppendCodePointIntlNodeGen,AppendCodePointNodeGen,AppendIntNumberNodeGen,AppendJavaStringUTF16NodeGen,AppendLongNumberNodeGen,AppendStringNodeGen,AppendSubstringByteIndexNodeGen,ToStringNodeGen
1105+
1106+
CLSS public final com.oracle.truffle.api.strings.TruffleStringBuilderUTF16
1107+
supr com.oracle.truffle.api.strings.TruffleStringBuilder
1108+
1109+
CLSS public final com.oracle.truffle.api.strings.TruffleStringBuilderUTF32
1110+
supr com.oracle.truffle.api.strings.TruffleStringBuilder
1111+
1112+
CLSS public final com.oracle.truffle.api.strings.TruffleStringBuilderUTF8
1113+
supr com.oracle.truffle.api.strings.TruffleStringBuilder
11001114

11011115
CLSS public final com.oracle.truffle.api.strings.TruffleStringFactory
11021116
cons public init()

truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/AbstractTruffleString.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,22 @@ static int rawIndex(int byteIndex, TruffleString.Encoding expectedEncoding) {
462462
return byteIndex >> expectedEncoding.naturalStride;
463463
}
464464

465+
static int rawIndexUTF16(int byteIndex) {
466+
if ((byteIndex & 1) != 0) {
467+
CompilerDirectives.transferToInterpreterAndInvalidate();
468+
throw InternalErrors.illegalArgument("misaligned byte index on UTF-16 string");
469+
}
470+
return byteIndex >> Encoding.UTF_16.naturalStride;
471+
}
472+
473+
static int rawIndexUTF32(int byteIndex) {
474+
if ((byteIndex & 3) != 0) {
475+
CompilerDirectives.transferToInterpreterAndInvalidate();
476+
throw InternalErrors.illegalArgument("misaligned byte index on UTF-32 string");
477+
}
478+
return byteIndex >> Encoding.UTF_32.naturalStride;
479+
}
480+
465481
static int byteIndex(int rawIndex, TruffleString.Encoding expectedEncoding) {
466482
assert rawIndex < 0 || (rawIndex << expectedEncoding.naturalStride) >= 0;
467483
assert rawIndex >= 0 || (rawIndex << expectedEncoding.naturalStride) < 0;

truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/TStringGuards.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,6 @@ static boolean isBrokenMultiByte(int codeRange) {
9999
return TSCodeRange.isBrokenMultiByte(codeRange);
100100
}
101101

102-
static boolean isBrokenMultiByte(TruffleStringBuilder sb) {
103-
return TSCodeRange.isBrokenMultiByte(sb.getCodeRange());
104-
}
105-
106102
public static boolean isValidOrBrokenMultiByte(int codeRange) {
107103
return TSCodeRange.isValidOrBrokenMultiByte(codeRange);
108104
}
@@ -180,10 +176,6 @@ static boolean isUTF16(Encoding enc) {
180176
return enc == Encoding.UTF_16;
181177
}
182178

183-
static boolean isUTF16(TruffleStringBuilder sb) {
184-
return isUTF16(sb.getEncoding());
185-
}
186-
187179
static boolean isUTF32(int enc) {
188180
return enc == Encoding.UTF_32.id;
189181
}
@@ -238,18 +230,6 @@ static boolean isStride2(AbstractTruffleString a) {
238230
return a.stride() == 2;
239231
}
240232

241-
static boolean isStride0(TruffleStringBuilder sb) {
242-
return sb.getStride() == 0;
243-
}
244-
245-
static boolean isStride1(TruffleStringBuilder sb) {
246-
return sb.getStride() == 1;
247-
}
248-
249-
static boolean isStride2(TruffleStringBuilder sb) {
250-
return sb.getStride() == 2;
251-
}
252-
253233
static boolean is7BitCompatible(Encoding encoding) {
254234
return encoding.is7BitCompatible();
255235
}

truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/TStringOpsNodes.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ final class TStringOpsNodes {
5757
*/
5858
static final String LIMIT_STRIDE = "9";
5959

60-
static final String SINGLE_LIMIT_STRIDE = "3";
61-
6260
abstract static class RawReadValueNode extends AbstractInternalNode {
6361

6462
abstract int execute(Node node, AbstractTruffleString a, Object arrayA, int i);

0 commit comments

Comments
 (0)