2222 */
2323package com .oracle .truffle .r .runtime .ffi ;
2424
25+ import java .lang .ref .SoftReference ;
2526import java .nio .charset .StandardCharsets ;
27+ import java .util .concurrent .atomic .AtomicReference ;
2628
2729import com .oracle .truffle .api .CompilerDirectives ;
2830import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
@@ -163,6 +165,18 @@ public static StudyNode create() {
163165 }
164166
165167 public static final class ExecNode extends NativeCallNode {
168+ private static final class BytesCache {
169+ private final String input ;
170+ private final byte [] bytes ;
171+
172+ BytesCache (String input , byte [] bytes ) {
173+ this .input = input ;
174+ this .bytes = bytes ;
175+ }
176+ }
177+
178+ private AtomicReference <SoftReference <BytesCache >> cachedBytes = new AtomicReference <>();
179+
166180 private ExecNode (DownCallNodeFactory factory ) {
167181 super (factory .createDownCallNode (NativeFunction .exec ));
168182 }
@@ -174,8 +188,18 @@ public int execute(long code, long extra, String subject, int offset, int option
174188 }
175189
176190 @ TruffleBoundary
177- private static byte [] getBytes (String subject ) {
178- return subject .getBytes (StandardCharsets .UTF_8 );
191+ private byte [] getBytes (String subject ) {
192+ if (subject .length () <= 32 ) {
193+ return subject .getBytes (StandardCharsets .UTF_8 );
194+ }
195+ SoftReference <BytesCache > cacheRef = cachedBytes .get ();
196+ BytesCache cache = cacheRef == null ? null : cacheRef .get ();
197+ if (cache != null && cache .input == subject ) {
198+ return cache .bytes ;
199+ }
200+ byte [] result = subject .getBytes (StandardCharsets .UTF_8 );
201+ cachedBytes .set (new SoftReference <>(new BytesCache (subject , result )));
202+ return result ;
179203 }
180204
181205 public static ExecNode create () {
0 commit comments