diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
index 06ab7c3d948fc06a2985e605e2f33bb0f0e16cec..801e09494b604a1f630b7c351f4d1208a3bff218 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
@@ -236,7 +236,7 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 {
             return RRuntime.isNA(v) ? cna : ComplexVectorPrinter.encodeComplex(v);
         } else if (o instanceof RRaw) {
             RRaw v = (RRaw) o;
-            return RRuntime.rawToHexString(v);
+            return RRuntime.rawToHexString(v.getValue());
         }
         throw RInternalError.unimplemented();
     }
@@ -278,7 +278,7 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 {
         }
         if (x instanceof RAbstractRawVector) {
             RAbstractRawVector v = (RAbstractRawVector) x;
-            return RRuntime.rawToHexString(v.getDataAt(indx));
+            return RRuntime.rawToHexString(v.getRawDataAt(indx));
         }
         throw RInternalError.unimplemented();
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index fde2672e65496f22e486229d7825a936b70d9a2b..8cc095f317a69c49a74bed0bca31fda99b4689ae 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -182,11 +182,15 @@ public class RRuntime {
     public static final RSymbol PSEUDO_NULL = new RSymbol("\u0001NULL\u0001");
     public static final String UNBOUND = "UNBOUND";
 
+    @CompilationFinal(dimensions = 1) private static final String[] rawStringCache = new String[256];
     @CompilationFinal(dimensions = 1) private static final String[] numberStringCache = new String[4096];
     private static final int MIN_CACHED_NUMBER = -numberStringCache.length / 2;
     private static final int MAX_CACHED_NUMBER = numberStringCache.length / 2 - 1;
 
     static {
+        for (int i = 0; i < rawStringCache.length; i++) {
+            rawStringCache[i] = Utils.intern(new String(new char[]{Character.forDigit((i & 0xF0) >> 4, 16), Character.forDigit(i & 0x0F, 16)}));
+        }
         for (int i = 0; i < numberStringCache.length; i++) {
             numberStringCache[i] = String.valueOf(i + MIN_CACHED_NUMBER);
         }
@@ -347,10 +351,8 @@ public class RRuntime {
         return int2complex(raw2int(r));
     }
 
-    public static String rawToHexString(RRaw operand) {
-        int value = raw2int(operand);
-        char[] digits = new char[]{Character.forDigit((value & 0xF0) >> 4, 16), Character.forDigit(value & 0x0F, 16)};
-        return new String(digits);
+    public static String rawToHexString(byte operand) {
+        return rawStringCache[raw2int(operand)];
     }
 
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java
index 2ca9d8a581587934efcf76dd962dc8f4196d76d5..cb1324370958ceeb0c2aea5b6536eefb1a2a32c6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java
@@ -245,7 +245,7 @@ final class RRawToStringVectorClosure extends RToStringVectorClosure {
 
     @Override
     public String getDataAt(int index) {
-        return RRuntime.rawToHexString(vector.getDataAt(index));
+        return RRuntime.rawToHexString(vector.getRawDataAt(index));
     }
 }