diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
index 0050adfe49186425b3ab3a4976f68cb05493767a..7381ba8add245de9225446179d0878a1d82549cc 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -75,13 +75,16 @@ static jmethodID LENGTH_MethodID;
 static jmethodID Rf_asIntegerMethodID;
 //static jmethodID Rf_asRealMethodID;
 static jmethodID Rf_asCharMethodID;
+static jmethodID Rf_mkCharLenCEMethodID;
 static jmethodID Rf_asLogicalMethodID;
 static jmethodID Rf_PairToVectorListMethodID;
-static jclass SEXPTYPEClass;
 static jmethodID gnuRCodeForObjectMethodID;
 static jmethodID NAMED_MethodID;
+static jmethodID TYPEOF_MethodID;
 static jmethodID DUPLICATE_ATTRIB_MethodID;
 static jmethodID iS4ObjectMethodID;
+static jmethodID logObject_MethodID;
+
 static jclass RExternalPtrClass;
 static jmethodID createExternalPtrMethodID;
 static jmethodID externalPtrGetAddrMethodID;
@@ -91,10 +94,13 @@ static jmethodID externalPtrSetAddrMethodID;
 static jmethodID externalPtrSetTagMethodID;
 static jmethodID externalPtrSetProtMethodID;
 
+static jclass CharSXPWrapperClass;
+static jfieldID CharXSPWrapperContentsFieldID;
+
 void init_internals(JNIEnv *env) {
 	Rf_ScalarIntegerMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_ScalarInteger", "(I)Lcom/oracle/truffle/r/runtime/data/RIntVector;", 1);
 	Rf_ScalarDoubleMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_ScalarDouble", "(D)Lcom/oracle/truffle/r/runtime/data/RDoubleVector;", 1);
-	Rf_ScalarStringMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_ScalarString", "(Ljava/lang/String;)Lcom/oracle/truffle/r/runtime/data/RStringVector;", 1);
+	Rf_ScalarStringMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_ScalarString", "(Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/data/RStringVector;", 1);
 	Rf_ScalarLogicalMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_ScalarLogical", "(I)Lcom/oracle/truffle/r/runtime/data/RLogicalVector;", 1);
 	Rf_consMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_cons", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1);
 	Rf_evalMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_eval", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1);
@@ -122,33 +128,35 @@ void init_internals(JNIEnv *env) {
 	Rf_lengthgetsMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_lengthgets", "(Ljava/lang/Object;I)Ljava/lang/Object;", 1);
 //	Rf_rPsortMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_rPsort", "(Lcom/oracle/truffle/r/runtime/data/RDoubleVector;II)", 1);
 //	Rf_iPsortMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_iPsort", "(Lcom/oracle/truffle/r/runtime/data/RIntVector;II)", 1);
-    CADR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "CADR", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
-    TAG_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "TAG", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
-    PRINTNAME_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "PRINTNAME", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
-    CAR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "CAR", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
-    CDR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "CDR", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
-    SET_TAG_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "SET_TAG", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1);
-    SETCAR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "SETCAR", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1);
-    SETCDR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "SETCDR", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1);
+	CADR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "CADR", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
+	TAG_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "TAG", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
+	PRINTNAME_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "PRINTNAME", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
+	CAR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "CAR", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
+	CDR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "CDR", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
+	SET_TAG_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "SET_TAG", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1);
+	SETCAR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "SETCAR", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1);
+	SETCDR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "SETCDR", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 1);
 	SET_STRING_ELT_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "SET_STRING_ELT", "(Ljava/lang/Object;ILjava/lang/Object;)V", 1);
 	SET_VECTOR_ELT_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "SET_VECTOR_ELT", "(Ljava/lang/Object;ILjava/lang/Object;)V", 1);
 	RAW_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "RAW", "(Ljava/lang/Object;)[B", 1);
 	REAL_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "REAL", "(Ljava/lang/Object;)[D", 1);
 	LOGICAL_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "LOGICAL", "(Ljava/lang/Object;)[I", 1);
 	INTEGER_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "INTEGER", "(Ljava/lang/Object;)[I", 1);
-	STRING_ELT_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "STRING_ELT", "(Ljava/lang/Object;I)Ljava/lang/String;", 1);
+	STRING_ELT_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "STRING_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 1);
 	VECTOR_ELT_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "VECTOR_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 1);
 	LENGTH_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "LENGTH", "(Ljava/lang/Object;)I", 1);
 	Rf_asIntegerMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_asInteger", "(Ljava/lang/Object;)I", 1);
 //	Rf_asRealMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_asReal", "(Ljava/lang/Object;)D", 1);
-	Rf_asCharMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_asChar", "(Ljava/lang/Object;)Ljava/lang/String;", 1);
+	Rf_asCharMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_asChar", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
+	Rf_mkCharLenCEMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_mkCharLenCE", "([BI)Ljava/lang/Object;", 1);
 	Rf_asLogicalMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_asLogical", "(Ljava/lang/Object;)I", 1);
 	Rf_PairToVectorListMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_PairToVectorList", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
-	SEXPTYPEClass = checkFindClass(env, "com/oracle/truffle/r/runtime/gnur/SEXPTYPE");
-	gnuRCodeForObjectMethodID = checkGetMethodID(env, SEXPTYPEClass, "gnuRCodeForObject", "(Ljava/lang/Object;)I", 1);
 	NAMED_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "NAMED", "(Ljava/lang/Object;)I", 1);
+	TYPEOF_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "TYPEOF", "(Ljava/lang/Object;)I", 1);
 	DUPLICATE_ATTRIB_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "DUPLICATE_ATTRIB", "(Ljava/lang/Object;Ljava/lang/Object;)V", 1);
 	iS4ObjectMethodID = checkGetMethodID(env, CallRFFIHelperClass, "isS4Object", "(Ljava/lang/Object;)I", 1);
+	logObject_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "logObject", "(Ljava/lang/Object;)V", 1);
+
 	RExternalPtrClass = checkFindClass(env, "com/oracle/truffle/r/runtime/data/RExternalPtr");
 	createExternalPtrMethodID = checkGetMethodID(env, RDataFactoryClass, "createExternalPtr", "(JLjava/lang/Object;Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/data/RExternalPtr;", 1);
 	externalPtrGetAddrMethodID = checkGetMethodID(env, RExternalPtrClass, "getAddr", "()J", 0);
@@ -157,6 +165,21 @@ void init_internals(JNIEnv *env) {
 	externalPtrSetAddrMethodID = checkGetMethodID(env, RExternalPtrClass, "setAddr", "(J)V", 0);
 	externalPtrSetTagMethodID = checkGetMethodID(env, RExternalPtrClass, "setTag", "(Ljava/lang/Object;)V", 0);
 	externalPtrSetProtMethodID = checkGetMethodID(env, RExternalPtrClass, "setProt", "(Ljava/lang/Object;)V", 0);
+
+	CharSXPWrapperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper$CharSXPWrapper");
+	CharXSPWrapperContentsFieldID = checkGetFieldID(env, CharSXPWrapperClass, "contents", "Ljava/lang/String;", 0);
+}
+
+static jstring stringFromCharSXP(JNIEnv *thisenv, SEXP charsxp) {
+#if VALIDATE_REFS
+	validateRef(thisenv, charsxp, "stringFromCharSXP");
+	if (!(*thisenv)->IsInstanceOf(thisenv, charsxp, CharSXPWrapperClass)) {
+
+	    (*thisenv)->CallStaticVoidMethod(thisenv, CallRFFIHelperClass, logObject_MethodID, charsxp);
+	    fatalError("only CharSXPWrapper expected in stringFromCharSXP");
+	}
+#endif
+	return (*thisenv)->GetObjectField(thisenv, charsxp, CharXSPWrapperContentsFieldID);
 }
 
 SEXP Rf_ScalarInteger(int value) {
@@ -357,9 +380,10 @@ SEXP Rf_install(const char *name) {
 	return checkRef(thisenv, result);
 }
 
-SEXP Rf_installChar(SEXP name) {
+SEXP Rf_installChar(SEXP charsxp) {
 	JNIEnv *thisenv = getEnv();
-	SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, RDataFactoryClass, createSymbolMethodID, name);
+	jstring string = stringFromCharSXP(thisenv, charsxp);
+	SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, RDataFactoryClass, createSymbolMethodID, string);
 	return checkRef(thisenv, result);
 }
 
@@ -398,11 +422,9 @@ SEXP Rf_mkCharLen(const char *x, int y) {
 
 SEXP Rf_mkCharLenCE(const char *x, int len, cetype_t enc) {
 	JNIEnv *thisenv = getEnv();
-	char buf[len + 1];
-	memcpy(buf, x, len);
-	buf[len] = 0;
-	// TODO encoding, assume UTF for now, zero terminated
-	SEXP result = (*thisenv)->NewStringUTF(thisenv, buf);
+	jbyteArray bytes = (*thisenv)->NewByteArray(thisenv, len);
+	(*thisenv)->SetByteArrayRegion(thisenv, bytes, 0, len, x);
+	SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_mkCharLenCEMethodID, bytes, (int) enc);
 	return checkRef(thisenv, result);
 }
 
@@ -668,24 +690,28 @@ void Rf_gsetVar(SEXP symbol, SEXP value, SEXP rho)
 }
 
 SEXP TAG(SEXP e) {
+    TRACE(TARG1, e);
     JNIEnv *thisenv = getEnv();
     SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, TAG_MethodID, e);
     return checkRef(thisenv, result);
 }
 
 SEXP PRINTNAME(SEXP e) {
+    TRACE(TARG1, e);
     JNIEnv *thisenv = getEnv();
     SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, PRINTNAME_MethodID, e);
     return checkRef(thisenv, result);
 }
 
 SEXP CAR(SEXP e) {
+    TRACE(TARG1, e);
     JNIEnv *thisenv = getEnv();
     SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, CAR_MethodID, e);
     return checkRef(thisenv, result);
 }
 
 SEXP CDR(SEXP e) {
+    TRACE(TARG1, e);
     JNIEnv *thisenv = getEnv();
     SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, CDR_MethodID, e);
     return checkRef(thisenv, result);
@@ -702,6 +728,7 @@ SEXP CDAR(SEXP e) {
 }
 
 SEXP CADR(SEXP e) {
+    TRACE(TARG1, e);
     JNIEnv *thisenv = getEnv();
     SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, CADR_MethodID, e);
     return checkRef(thisenv, result);
@@ -742,17 +769,20 @@ void SET_MISSING(SEXP x, int v) {
 }
 
 void SET_TAG(SEXP x, SEXP y) {
+    TRACE(TARG2, x, y);
     JNIEnv *thisenv = getEnv();
     (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, SET_TAG_MethodID, x, y);
 }
 
 SEXP SETCAR(SEXP x, SEXP y) {
+    TRACE(TARG2, x, y);
     JNIEnv *thisenv = getEnv();
     SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, SETCAR_MethodID, x, y);
     return checkRef(thisenv, result);
 }
 
 SEXP SETCDR(SEXP x, SEXP y) {
+    TRACE(TARG2, x, y);
     JNIEnv *thisenv = getEnv();
     SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, SETCDR_MethodID, x, y);
     return checkRef(thisenv, result);
@@ -1041,18 +1071,21 @@ SEXP STRING_ELT(SEXP x, R_xlen_t i){
 
 
 SEXP VECTOR_ELT(SEXP x, R_xlen_t i){
+	TRACE(TARG2d, x, i);
 	JNIEnv *thisenv = getEnv();
     SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, VECTOR_ELT_MethodID, x, i);
     return checkRef(thisenv, result);
 }
 
 void SET_STRING_ELT(SEXP x, R_xlen_t i, SEXP v){
+	TRACE("%s(%p, %d, %p)", x, i, v);
 	JNIEnv *thisenv = getEnv();
 	(*thisenv)->CallStaticVoidMethod(thisenv, CallRFFIHelperClass, SET_STRING_ELT_MethodID, x, i, v);
 }
 
 
 SEXP SET_VECTOR_ELT(SEXP x, R_xlen_t i, SEXP v){
+	TRACE("%s(%p, %d, %p)", x, i, v);
 	JNIEnv *thisenv = getEnv();
 	(*thisenv)->CallStaticVoidMethod(thisenv, CallRFFIHelperClass, SET_VECTOR_ELT_MethodID, x, i, v);
 	return v;
@@ -1078,6 +1111,7 @@ SEXP Rf_asChar(SEXP x){
 }
 
 SEXP Rf_PairToVectorList(SEXP x){
+	TRACE(TARG1, x);
 	JNIEnv *thisenv = getEnv();
 	SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_PairToVectorListMethodID, x);
 	return checkRef(thisenv, result);
@@ -1117,8 +1151,9 @@ Rcomplex Rf_asComplex(SEXP x){
 }
 
 int TYPEOF(SEXP x) {
-    JNIEnv *thisenv = getEnv();
-    return (*thisenv)->CallStaticIntMethod(thisenv, SEXPTYPEClass, gnuRCodeForObjectMethodID, x);
+	TRACE(TARG1, x);
+	JNIEnv *thisenv = getEnv();
+	return (*thisenv)->CallStaticIntMethod(thisenv, CallRFFIHelperClass, TYPEOF_MethodID, x);
 }
 
 SEXP ATTRIB(SEXP x){
@@ -1172,15 +1207,13 @@ char *dgettext(const char *domainname, const char *msgid) {
 	return (char*) msgid;
 }
 
-const char *R_CHAR(SEXP string) {
-	TRACE("%s(%p)", string);
+const char *R_CHAR(SEXP charsxp) {
+	TRACE("%s(%p)", charsxp);
+	JNIEnv *thisenv = getEnv();
 	// This is nasty:
 	// 1. the resulting character array has to be copied and zero-terminated.
 	// 2. It causes an (inevitable?) memory leak
-	JNIEnv *thisenv = getEnv();
-#if VALIDATE_REFS
-	validateRef(thisenv, string, "R_CHAR");
-#endif
+	jstring string = stringFromCharSXP(thisenv, charsxp);
 	jsize len = (*thisenv)->GetStringUTFLength(thisenv, string);
 	const char *stringChars = (*thisenv)->GetStringUTFChars(thisenv, string, NULL);
 	char *copyChars = malloc(len + 1);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
index aee0e8150f5fc3623c0e948fda552ac500f00128..e26fc56a969deb22b707ace5f6c5acda2b2aeb29 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -35,6 +35,7 @@
 jclass CallRFFIHelperClass;
 jclass RDataFactoryClass;
 jclass RRuntimeClass;
+jclass CharSXPWrapperClass;
 
 static jclass RInternalErrorClass;
 static jmethodID unimplementedMethodID;
@@ -293,3 +294,19 @@ jmethodID checkGetMethodID(JNIEnv *env, jclass klass, const char *name, const ch
 	}
 	return methodID;
 }
+
+jfieldID checkGetFieldID(JNIEnv *env, jclass klass, const char *name, const char *sig, int isStatic) {
+	jfieldID fieldID = isStatic ? (*env)->GetStaticFieldID(env, klass, name, sig) : (*env)->GetFieldID(env, klass, name, sig);
+	if (fieldID == NULL) {
+		char buf[1024];
+		strcpy(buf, "failed to find ");
+		strcat(buf, isStatic ? "static" : "instance");
+		strcat(buf, " field ");
+		strcat(buf, name);
+		strcat(buf, "(");
+		strcat(buf, sig);
+		strcat(buf, ")");
+		(*env)->FatalError(env, buf);
+	}
+	return fieldID;
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
index a31fd8b65572e53996f2d90409c0951fecf5214f..24e89fee06e97133581fbffc8068055002666ba6 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
@@ -37,6 +37,7 @@ void setEnv(JNIEnv *env);
 
 jclass checkFindClass(JNIEnv *env, const char *name);
 jmethodID checkGetMethodID(JNIEnv *env, jclass klass, const char *name, const char *sig, int isStatic);
+jfieldID checkGetFieldID(JNIEnv *env, jclass klass, const char *name, const char *sig, int isStatic);
 extern jmethodID createSymbolMethodID;
 
 // use for an unimplemented API function
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java
index b1e671b8850640e01de0b1f7755f5e5c38ffac6d..082d05cbbe10dc8e11782fea68312a9a94065e5c 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java
@@ -71,7 +71,7 @@ public class Generic_Tools implements ToolsRFFI {
             SymbolInfo parseRd = ToolsProvider.toolsProvider().getParseRd();
             return RFFIFactory.getRFFI().getCallRFFI().invokeCall(parseRd.address, parseRd.symbol, new Object[]{con, srcfile, verbose, fragment, basename, warningCalls, macros, warndups});
         } catch (Throwable ex) {
-            throw RInternalError.shouldNotReachHere();
+            throw RInternalError.shouldNotReachHere(ex, "error during Rd parsing");
         } finally {
             parseRdCritical.release();
         }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
index 5be652af7b240b8ec0f12f852d636e950d4bd46b..f3dfc4acf13bda69f53cb38e612995e9b1a9a454 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.runtime.ffi.jnr;
 
+import java.nio.charset.StandardCharsets;
+
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RError;
@@ -63,7 +65,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
-import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 /**
  * This class provides methods that match the functionality of the macro/function definitions in the
@@ -72,7 +73,23 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
  * files. These methods should never be called from normal FastR code.
  */
 public class CallRFFIHelper {
-    @SuppressWarnings("unused") private static final NACheck elementNACheck = NACheck.create();
+
+    private static final class CharSXPWrapper {
+        private final String contents;
+
+        CharSXPWrapper(String contents) {
+            this.contents = contents;
+        }
+
+        public String getContents() {
+            return contents;
+        }
+
+        @Override
+        public String toString() {
+            return "CHARSXP(" + contents + ")";
+        }
+    }
 
     private static RuntimeException unimplemented() {
         return unimplemented("");
@@ -112,16 +129,6 @@ public class CallRFFIHelper {
         return clazz.cast(x);
     }
 
-    private static <T> T guaranteeInstanceOfOrNull(Object x, Class<T> clazz) {
-        if (x == null) {
-            return null;
-        }
-        if (!clazz.isInstance(x)) {
-            guarantee(false, "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of " + clazz.getSimpleName());
-        }
-        return clazz.cast(x);
-    }
-
     // Checkstyle: stop method name check
 
     public static RIntVector Rf_ScalarInteger(int value) {
@@ -136,8 +143,9 @@ public class CallRFFIHelper {
         return RDataFactory.createDoubleVectorFromScalar(value);
     }
 
-    public static RStringVector Rf_ScalarString(String value) {
-        return RDataFactory.createStringVectorFromScalar(value);
+    public static RStringVector Rf_ScalarString(Object value) {
+        CharSXPWrapper chars = guaranteeInstanceOf(value, CharSXPWrapper.class);
+        return RDataFactory.createStringVectorFromScalar(chars.getContents());
     }
 
     public static int Rf_asInteger(Object x) {
@@ -173,13 +181,31 @@ public class CallRFFIHelper {
         }
     }
 
-    public static String Rf_asChar(Object x) {
-        if (x instanceof String) {
-            return (String) x;
-        } else {
-            guaranteeInstanceOf(x, RStringVector.class);
-            return ((RStringVector) x).getDataAt(0);
+    public static Object Rf_asChar(Object x) {
+        if (x instanceof CharSXPWrapper) {
+            return x;
+        } else if (x instanceof RSymbol) {
+            return new CharSXPWrapper(((RSymbol) x).getName());
         }
+
+        Object obj = RRuntime.asAbstractVector(x);
+        if (obj instanceof RAbstractVector) {
+            RAbstractVector vector = (RAbstractVector) obj;
+            if (vector.getLength() > 0) {
+                if (vector instanceof RAbstractStringVector) {
+                    return new CharSXPWrapper(((RAbstractStringVector) vector).getDataAt(0));
+                } else {
+                    unimplemented("asChar type " + x.getClass());
+                }
+            }
+        }
+
+        return new CharSXPWrapper(RRuntime.STRING_NA);
+    }
+
+    public static Object Rf_mkCharLenCE(byte[] bytes, @SuppressWarnings("unused") int encoding) {
+        // TODO: handle encoding properly
+        return new CharSXPWrapper(new String(bytes, StandardCharsets.UTF_8));
     }
 
     public static Object Rf_cons(Object car, Object cdr) {
@@ -395,6 +421,8 @@ public class CallRFFIHelper {
             return ((RAbstractContainer) x).getLength();
         } else if (x == RNull.instance) {
             return 0;
+        } else if (x instanceof CharSXPWrapper) {
+            return ((CharSXPWrapper) x).getContents().length();
         } else if (x instanceof Integer || x instanceof Double || x instanceof Byte || x instanceof String) {
             return 1;
         } else {
@@ -403,9 +431,9 @@ public class CallRFFIHelper {
     }
 
     public static void SET_STRING_ELT(Object x, int i, Object v) {
-        // TODO error checks
-        RStringVector xv = (RStringVector) x;
-        xv.setElement(i, v);
+        RStringVector vector = guaranteeInstanceOf(x, RStringVector.class);
+        CharSXPWrapper element = guaranteeInstanceOf(v, CharSXPWrapper.class);
+        vector.setElement(i, element.getContents());
     }
 
     public static void SET_VECTOR_ELT(Object x, int i, Object v) {
@@ -474,15 +502,14 @@ public class CallRFFIHelper {
         }
     }
 
-    public static String STRING_ELT(Object x, int i) {
-        if (x instanceof String) {
-            assert i == 0;
-            return (String) x;
-        } else if (x instanceof RStringVector) {
-            return ((RStringVector) x).getDataAt(i);
-        } else {
-            throw unimplemented();
-        }
+    public static void logObject(Object x) {
+        System.out.println("object " + x);
+        System.out.println("class " + x.getClass());
+    }
+
+    public static Object STRING_ELT(Object x, int i) {
+        RAbstractStringVector vector = guaranteeInstanceOf(RRuntime.asAbstractVector(x), RAbstractStringVector.class);
+        return new CharSXPWrapper(vector.getDataAt(i));
     }
 
     public static Object VECTOR_ELT(Object x, int i) {
@@ -502,6 +529,14 @@ public class CallRFFIHelper {
         }
     }
 
+    public static int TYPEOF(Object x) {
+        if (x instanceof CharSXPWrapper) {
+            return SEXPTYPE.CHARSXP.code;
+        } else {
+            return SEXPTYPE.gnuRCodeForObject(x);
+        }
+    }
+
     public static Object Rf_duplicate(Object x) {
         guaranteeInstanceOf(x, RAbstractVector.class);
         return ((RAbstractVector) x).copy();
@@ -509,7 +544,7 @@ public class CallRFFIHelper {
 
     public static Object PRINTNAME(Object x) {
         guaranteeInstanceOf(x, RSymbol.class);
-        return ((RSymbol) x).getName();
+        return new CharSXPWrapper(((RSymbol) x).getName());
     }
 
     public static Object TAG(Object e) {