Skip to content

Commit bc68268

Browse files
committed
[GR-40766] Optimize conversion of j.l.String to TruffleString via InteropLibrary#asTruffleString()
PullRequest: graal/12571
2 parents 9136c9a + 0efe40d commit bc68268

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/DefaultStringExports.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@
4141
package com.oracle.truffle.api.interop;
4242

4343
import com.oracle.truffle.api.TruffleLanguage;
44+
import com.oracle.truffle.api.dsl.Cached;
4445
import com.oracle.truffle.api.library.ExportLibrary;
4546
import com.oracle.truffle.api.library.ExportMessage;
4647
import com.oracle.truffle.api.source.SourceSection;
48+
import com.oracle.truffle.api.strings.TruffleString;
4749

4850
@ExportLibrary(value = InteropLibrary.class, receiverType = String.class)
4951
@SuppressWarnings("unused")
@@ -59,6 +61,12 @@ static String asString(String receiver) {
5961
return receiver;
6062
}
6163

64+
@ExportMessage
65+
static TruffleString asTruffleString(String receiver,
66+
@Cached TruffleString.FromJavaStringNode fromJavaStringNode) {
67+
return fromJavaStringNode.execute(receiver, TruffleString.Encoding.UTF_16);
68+
}
69+
6270
/*
6371
* We export these messages explicitly because the legacy default is very costly. Remove with
6472
* the complicated legacy implementation in InteropLibrary.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1542,7 +1542,8 @@ TruffleString doNonEmpty(String javaString, int charOffset, int length, final bo
15421542
TruffleString ret = TruffleString.createFromArray(array, offset, length, stride, Encoding.UTF_16, codePointLength, codeRange);
15431543
if (length == javaString.length()) {
15441544
assert charOffset == 0;
1545-
ret.cacheInsert(TruffleString.createWrapJavaString(javaString, codePointLength, codeRange));
1545+
TruffleString wrapped = TruffleString.createWrapJavaString(javaString, codePointLength, codeRange);
1546+
ret.cacheInsertFirstBeforePublished(wrapped);
15461547
}
15471548
return ret;
15481549
}

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ private static VarHandle initializeNextUpdater() {
140140

141141
private final int codePointLength;
142142
private final byte codeRange;
143-
private TruffleString next;
143+
TruffleString next;
144144

145145
private TruffleString(Object data, int offset, int length, int stride, Encoding encoding, int codePointLength, int codeRange, boolean isCacheHead) {
146146
super(data, offset, length, stride, encoding, isCacheHead ? FLAG_CACHE_HEAD : 0);
@@ -305,6 +305,20 @@ void cacheInsert(TruffleString entry) {
305305
} while (!setNextAtomic(cacheHead, cacheHeadNext, entry));
306306
}
307307

308+
/*
309+
* Simpler and faster insertion for the case `this` and `entry` were just allocated together and
310+
* before they are published. The CAS is not needed in that case since we know nobody could
311+
* write to `next` fields before us.
312+
*/
313+
void cacheInsertFirstBeforePublished(TruffleString entry) {
314+
assert !entry.isCacheHead();
315+
assert isCacheHead();
316+
assert next == null;
317+
TruffleString cacheHead = this;
318+
entry.next = cacheHead;
319+
cacheHead.next = entry;
320+
}
321+
308322
private static boolean hasDuplicateEncoding(TruffleString cacheHead, TruffleString start, TruffleString insertEntry) {
309323
if (start == null) {
310324
return false;
@@ -2024,7 +2038,7 @@ public abstract static class FromJavaStringNode extends Node {
20242038
* @since 22.1
20252039
*/
20262040
public final TruffleString execute(String value, Encoding encoding) {
2027-
return execute(value, 0, value.length(), encoding, true);
2041+
return execute(value, 0, value.length(), encoding, false);
20282042
}
20292043

20302044
/**

0 commit comments

Comments
 (0)