diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_variablesindex.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_variablesindex.h
index 9e7702e4e7e87601e15c2179fdf493bbceda6ffc..ddd5559aaf398c8d73947a9468e7a0c1b119d229 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_variablesindex.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_variablesindex.h
@@ -23,58 +23,62 @@
 #ifndef RFFI_VARIABLESINDEX_H
 #define RFFI_VARIABLESINDEX_H
 
+// Generated by RFFIVariables.java:
+
 #define R_Home_x 0
 #define R_TempDir_x 1
 #define R_NilValue_x 2
 #define R_UnboundValue_x 3
 #define R_MissingArg_x 4
-#define R_GlobalEnv_x 5
-#define R_EmptyEnv_x 6
-#define R_BaseEnv_x 7
-#define R_BaseNamespace_x 8
-#define R_NamespaceRegistry_x 9
-#define R_Srcref_x 10
-#define R_Bracket2Symbol_x 11
-#define R_BracketSymbol_x 12
-#define R_BraceSymbol_x 13
-#define R_DoubleColonSymbol_x 14
-#define R_ClassSymbol_x 15
-#define R_DeviceSymbol_x 16
-#define R_DevicesSymbol_x 17
-#define R_DimNamesSymbol_x 18
-#define R_DimSymbol_x 19
-#define R_DollarSymbol_x 20
-#define R_DotsSymbol_x 21
-#define R_DropSymbol_x 22
-#define R_LastvalueSymbol_x 23
-#define R_LevelsSymbol_x 24
-#define R_ModeSymbol_x 25
-#define R_NameSymbol_x 26
-#define R_NamesSymbol_x 27
-#define R_NaRmSymbol_x 28
-#define R_PackageSymbol_x 29
-#define R_QuoteSymbol_x 30
-#define R_RowNamesSymbol_x 31
-#define R_SeedsSymbol_x 32
-#define R_SourceSymbol_x 33
-#define R_TspSymbol_x 34
-#define R_dot_defined_x 35
-#define R_dot_Method_x 36
-#define R_dot_target_x 37
-#define R_SrcrefSymbol_x 38
-#define R_SrcfileSymbol_x 39
-#define R_NaString_x 40
-#define R_NaN_x 41
-#define R_PosInf_x 42
-#define R_NegInf_x 43
-#define R_NaReal_x 44
-#define R_NaInt_x 45
-#define R_BlankString_x 46
-#define R_BlankScalarString_x 47
-#define R_BaseSymbol_x 48
-#define R_NamespaceEnvSymbol_x 49
-#define R_RestartToken_x 50
+#define R_EmptyEnv_x 5
+#define R_Srcref_x 6
+#define R_Bracket2Symbol_x 7
+#define R_BracketSymbol_x 8
+#define R_BraceSymbol_x 9
+#define R_DoubleColonSymbol_x 10
+#define R_ClassSymbol_x 11
+#define R_DeviceSymbol_x 12
+#define R_DevicesSymbol_x 13
+#define R_DimNamesSymbol_x 14
+#define R_DimSymbol_x 15
+#define R_DollarSymbol_x 16
+#define R_DotsSymbol_x 17
+#define R_DropSymbol_x 18
+#define R_LastvalueSymbol_x 19
+#define R_LevelsSymbol_x 20
+#define R_ModeSymbol_x 21
+#define R_NameSymbol_x 22
+#define R_NamesSymbol_x 23
+#define R_NaRmSymbol_x 24
+#define R_PackageSymbol_x 25
+#define R_QuoteSymbol_x 26
+#define R_RowNamesSymbol_x 27
+#define R_SeedsSymbol_x 28
+#define R_SourceSymbol_x 29
+#define R_TspSymbol_x 30
+#define R_dot_defined_x 31
+#define R_dot_Method_x 32
+#define R_dot_target_x 33
+#define R_dot_packageName_x 34
+#define R_dot_Generic_x 35
+#define R_SrcrefSymbol_x 36
+#define R_SrcfileSymbol_x 37
+#define R_NaString_x 38
+#define R_NaN_x 39
+#define R_PosInf_x 40
+#define R_NegInf_x 41
+#define R_NaReal_x 42
+#define R_NaInt_x 43
+#define R_BlankString_x 44
+#define R_BlankScalarString_x 45
+#define R_BaseSymbol_x 46
+#define R_NamespaceEnvSymbol_x 47
+#define R_RestartToken_x 48
+#define R_SortListSymbol_x 49
+#define R_SpecSymbol_x 50
+#define R_TripleColonSymbol_x 51
+#define R_PreviousSymbol_x 52
 
-#define VARIABLES_TABLE_SIZE 50
+#define VARIABLES_TABLE_SIZE 53
 
 #endif // RFFI_VARIABLESINDEX_H
diff --git a/com.oracle.truffle.r.native/fficall/src/include/Defn.h b/com.oracle.truffle.r.native/fficall/src/include/Defn.h
index b401a7c0b7a2efedd0b9f55e0aed231895e92754..3ad79cc188d40d9060f5062381132e8899ea872a 100644
--- a/com.oracle.truffle.r.native/fficall/src/include/Defn.h
+++ b/com.oracle.truffle.r.native/fficall/src/include/Defn.h
@@ -46,18 +46,14 @@ void Rf_checkArityCall(SEXP, SEXP, SEXP);
 /* ../main/devices.c, used in memory.c, gnuwin32/extra.c */
 #define R_MaxDevices 64
 
-extern SEXP FASTR_R_DevicesSymbol();
-#define R_DevicesSymbol FASTR_R_DevicesSymbol()
-extern SEXP FASTR_R_DeviceSymbol();
-#define R_DeviceSymbol FASTR_R_DeviceSymbol()
+extern SEXP R_DevicesSymbol;
+extern SEXP R_DeviceSymbol;
 extern Rboolean FASTR_R_Interactive();
 #define R_Interactive FASTR_R_Interactive()
 extern Rboolean R_Visible;
 int	R_ReadConsole(const char *, unsigned char *, int, int);
-extern const char *FASTR_R_Home();
-#define R_Home FASTR_R_Home()
-extern const char *FASTR_R_TempDir();
-#define R_TempDir FASTR_R_TempDir()
+extern const char *R_Home;
+extern const char *R_TempDir;
 
 //#define HAVE_MBSTATE_T 1 // actually from config.h
 
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
index 858688a9b2efff1487e550ba97461d293cf0e5b9..6a68f5cb209d12e41c50bdc2c8e853b93025d575 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
@@ -26,61 +26,6 @@
 #include <rffiutils.h>
 #include "../common/rffi_variablesindex.h"
 
-
-static const char *R_Home_static;
-static const char *R_TempDir_static;
-static SEXP R_EmptyEnv_static;
-static SEXP R_Srcref_static;
-static SEXP R_NilValue_static;
-static SEXP R_NilValue_static2;
-static SEXP R_UnboundValue_static;
-static SEXP R_MissingArg_static;
-static SEXP R_BaseSymbol_static;
-static SEXP R_Bracket2Symbol_static;   /* "[[" */
-static SEXP R_BracketSymbol_static;    /* "[" */
-static SEXP R_BraceSymbol_static;      /* "{" */
-static SEXP R_DoubleColonSymbol_static;/* "::" */
-static SEXP R_ClassSymbol_static;     /* "class" */
-static SEXP R_DeviceSymbol_static;     /* ".Device" */
-static SEXP R_DevicesSymbol_static;     /* ".Devices" */
-static SEXP R_DimNamesSymbol_static;   /* "dimnames" */
-static SEXP R_DimSymbol_static;     /* "dim" */
-static SEXP R_DollarSymbol_static;     /* "$" */
-static SEXP R_DotsSymbol_static;     /* "..." */
-static SEXP R_DropSymbol_static;     /* "drop" */
-static SEXP R_LastvalueSymbol_static;  /* ".Last.value" */
-static SEXP R_LevelsSymbol_static;     /* "levels" */
-static SEXP R_ModeSymbol_static;     /* "mode" */
-static SEXP R_NameSymbol_static;     /* "name" */
-static SEXP R_NamesSymbol_static;     /* "names" */
-static SEXP R_NaRmSymbol_static;     /* "na.rm" */
-static SEXP R_PackageSymbol_static;    /* "package" */
-static SEXP R_QuoteSymbol_static;     /* "quote" */
-static SEXP R_RowNamesSymbol_static;   /* "row.names" */
-static SEXP R_SeedsSymbol_static;     /* ".Random.seed" */
-static SEXP R_SourceSymbol_static;     /* "source" */
-static SEXP R_TspSymbol_static;     /* "tsp" */
-static SEXP R_dot_defined_static;      /* ".defined" */
-static SEXP R_dot_Method_static;       /* ".Method" */
-static SEXP R_dot_target_static;       /* ".target" */
-static SEXP R_NaString_static;	    /* NA_STRING as a CHARSXP */
-static SEXP R_BlankString_static;	    /* "" as a CHARSXP */
-static SEXP R_BlankScalarString_static;	    /* "" as a STRSXP */
-static SEXP R_BaseSymbol_static;	    /* "base" as a SYMSXP */
-static SEXP	R_NamespaceEnvSymbol_static;   // ".__NAMESPACE__."
-
-// Symbols not part of public API but used in FastR tools implementation
-static SEXP R_SrcrefSymbol_static;
-static SEXP R_SrcfileSymbol_static;
-static SEXP R_RestartToken_static;
-
-// Arith.h
-double R_NaN;		/* IEEE NaN */
-double R_PosInf;	/* IEEE Inf */
-double R_NegInf;	/* IEEE -Inf */
-double R_NaReal;	/* NA_REAL: IEEE */
-int R_NaInt;	/* NA_INTEGER:= INT_MIN currently */
-
 // various ignored flags and variables nevertheless needed to resolve symbols
 Rboolean R_Visible;
 Rboolean R_interrupts_suspended;
@@ -97,263 +42,154 @@ int max_contour_segments = 25000;
 // from sys-std.c
 #include <R_ext/eventloop.h>
 
-static InputHandler BasicInputHandler = {2, -1, NULL};
+InputHandler BasicInputHandler = {2, -1, NULL};
 InputHandler *R_InputHandlers = &BasicInputHandler;
 
-char *FASTR_R_Home() {
-	return (char *) R_Home_static;
-}
-
-char *FASTR_R_TempDir() {
-	return (char *) R_TempDir_static;
-}
-
-SEXP FASTR_R_EmptyEnv() {
-    return R_EmptyEnv_static;
-}
-
-SEXP FASTR_R_Srcref() {
-    return R_Srcref_static;
-}
-
-SEXP FASTR_R_NilValue() {
-    return R_NilValue_static;
-}
-
-SEXP FASTR_R_UnboundValue() {
-    return R_UnboundValue_static;
-}
-
-SEXP FASTR_R_MissingArg() {
-    return R_MissingArg_static;
-}
-
-SEXP FASTR_R_BaseSymbol() {
-    return R_BaseSymbol_static;
-}
-
-
-SEXP FASTR_R_BraceSymbol() {
-    return R_BraceSymbol_static;
-}
-
-SEXP FASTR_R_DoubleColonSymbol() {
-    return R_DoubleColonSymbol_static;
-}
-
-SEXP FASTR_R_Bracket2Symbol() {
-    return R_Bracket2Symbol_static;
-}
-
-SEXP FASTR_R_BracketSymbol() {
-    return R_BracketSymbol_static;
-}
-
-SEXP FASTR_R_ClassSymbol() {
-    return R_ClassSymbol_static;
-}
-
-SEXP FASTR_R_DimNamesSymbol() {
-    return R_DimNamesSymbol_static;
-}
-
-SEXP FASTR_R_DimSymbol() {
-    return R_DimSymbol_static;
-}
-
-
-SEXP FASTR_R_DollarSymbol() {
-    return R_DollarSymbol_static;
-}
-
-SEXP FASTR_R_DotsSymbol() {
-    return R_DotsSymbol_static;
-}
-
-
-SEXP FASTR_R_DropSymbol() {
-    return R_DropSymbol_static;
-}
-
-SEXP FASTR_R_LastvalueSymbol() {
-    return R_LastvalueSymbol_static;
-}
-
-
-SEXP FASTR_R_LevelsSymbol() {
-    return R_LevelsSymbol_static;
-}
-
-SEXP FASTR_R_ModeSymbol() {
-    return R_ModeSymbol_static;
-}
-
-SEXP FASTR_R_NaRmSymbol() {
-    return R_NaRmSymbol_static;
-}
-
-
-SEXP FASTR_R_NameSymbol() {
-    return R_NameSymbol_static;
-}
-
-SEXP FASTR_R_NamesSymbol() {
-    return R_NamesSymbol_static;
-}
-
-
-SEXP FASTR_R_NamespaceEnvSymbol() {
-    return R_NamespaceEnvSymbol_static;
-}
-
-SEXP FASTR_R_PackageSymbol() {
-    return R_PackageSymbol_static;
-}
-
-SEXP FASTR_R_QuoteSymbol() {
-    return R_QuoteSymbol_static;
-}
-
-SEXP FASTR_R_RowNamesSymbol() {
-    return R_RowNamesSymbol_static;
-}
-
-SEXP FASTR_R_SeedsSymbol() {
-    return R_SeedsSymbol_static;
-}
-
-SEXP FASTR_R_SourceSymbol() {
-    return R_SourceSymbol_static;
-}
-
-SEXP FASTR_R_TspSymbol() {
-    return R_TspSymbol_static;
-}
-
-SEXP FASTR_R_dot_defined() {
-    return R_dot_defined_static;
-}
-
-SEXP FASTR_R_dot_Method() {
-    return R_dot_Method_static;
-}
-
-SEXP FASTR_R_dot_target() {
-    return R_dot_target_static;
-}
-
-SEXP FASTR_R_NaString() {
-    return R_NaString_static;
-}
-
-
-SEXP FASTR_R_BlankString() {
-    return R_BlankString_static;
-}
-
-SEXP FASTR_R_BlankScalarString() {
-    return R_BlankScalarString_static;
-}
-
-SEXP FASTR_R_DevicesSymbol() {
-    return R_DevicesSymbol_static;
-}
-
-SEXP FASTR_R_DeviceSymbol() {
-    return R_DeviceSymbol_static;
-}
-
-SEXP FASTR_R_SrcrefSymbol() {
-    return R_SrcrefSymbol_static;
+char *copystring(char *value) {
+	char *result = malloc(strlen(value) + 1);
+	strcpy(result, value);
+	return result;
 }
 
-SEXP FASTR_R_SrcfileSymbol() {
-    return R_SrcfileSymbol_static;
-}
+// ---------------------------------------------------
+// Generated by RFFIVariables.java:
+
+char* R_Home;
+char* R_TempDir;
+SEXP R_NilValue;
+SEXP R_UnboundValue;
+SEXP R_MissingArg;
+SEXP R_EmptyEnv;
+SEXP R_Srcref;
+SEXP R_Bracket2Symbol; /* "[[" */
+SEXP R_BracketSymbol; /* "[" */
+SEXP R_BraceSymbol; /* "{" */
+SEXP R_DoubleColonSymbol; /* "::" */
+SEXP R_ClassSymbol; /* "class" */
+SEXP R_DeviceSymbol; /* ".Device" */
+SEXP R_DevicesSymbol; /* ".Devices" */
+SEXP R_DimNamesSymbol; /* "dimnames" */
+SEXP R_DimSymbol; /* "dim" */
+SEXP R_DollarSymbol; /* "$" */
+SEXP R_DotsSymbol; /* "..." */
+SEXP R_DropSymbol; /* "drop" */
+SEXP R_LastvalueSymbol; /* ".Last.value" */
+SEXP R_LevelsSymbol; /* "levels" */
+SEXP R_ModeSymbol; /* "mode" */
+SEXP R_NameSymbol; /* "name" */
+SEXP R_NamesSymbol; /* "names" */
+SEXP R_NaRmSymbol; /* "na.rm" */
+SEXP R_PackageSymbol; /* "package" */
+SEXP R_QuoteSymbol; /* "quote" */
+SEXP R_RowNamesSymbol; /* "row.names" */
+SEXP R_SeedsSymbol; /* ".Random.seed" */
+SEXP R_SourceSymbol; /* "source" */
+SEXP R_TspSymbol; /* "tsp" */
+SEXP R_dot_defined; /* ".defined" */
+SEXP R_dot_Method; /* ".Method" */
+SEXP R_dot_target; /* ".target" */
+SEXP R_dot_packageName; /* ".packageName" */
+SEXP R_dot_Generic; /* ".Generic" */
+SEXP R_SrcrefSymbol; /* "srcref" */
+SEXP R_SrcfileSymbol; /* "srcfile" */
+SEXP R_NaString;
+double R_NaN;
+double R_PosInf;
+double R_NegInf;
+double R_NaReal;
+int R_NaInt;
+SEXP R_BlankString;
+SEXP R_BlankScalarString;
+SEXP R_BaseSymbol; /* "base" */
+SEXP R_NamespaceEnvSymbol; /* ".__NAMESPACE__." */
+SEXP R_RestartToken;
+SEXP R_SortListSymbol; /* "sort.list" */
+SEXP R_SpecSymbol; /* "spec" */
+SEXP R_TripleColonSymbol; /* ":::" */
+SEXP R_PreviousSymbol; /* "previous" */
 
 void Call_initvar_double(int index, double value) {
-	switch (index) {
-    case R_NaN_x: R_NaN = value; break;
-    case R_PosInf_x: R_PosInf = value; break;
-    case R_NegInf_x: R_NegInf = value; break;
-    case R_NaReal_x: R_NaReal = value; break;
-    default:
-        printf("Call_initvar_double: unimplemented index %d\n", index);
-        exit(1);
-	}
+    switch (index) {
+        case R_NaN_x: R_NaN = value; break;
+        case R_PosInf_x: R_PosInf = value; break;
+        case R_NegInf_x: R_NegInf = value; break;
+        case R_NaReal_x: R_NaReal = value; break;
+        default:
+            printf("Call_initvar_double: unimplemented index %d\n", index);
+            exit(1);
+    }
 }
 
 void Call_initvar_int(int index, int value) {
-	switch (index) {
-    case R_NaInt_x: R_NaInt = value; break;
-    default:
-        printf("Call_initvar_int: unimplemented index %d\n", index);
-        exit(1);
-	}
-}
-
-char *copystring(char *value) {
-	char *result = malloc(strlen(value) + 1);
-	strcpy(result, value);
-	return result;
+    switch (index) {
+        case R_NaInt_x: R_NaInt = value; break;
+        default:
+            printf("Call_initvar_int: unimplemented index %d\n", index);
+            exit(1);
+    }
 }
 
-// value must be copied
-void Call_initvar_string(int index, char *value) {
-	switch (index) {
-    case R_Home_x: R_Home_static = copystring(value); break;
-    case R_TempDir_x: R_TempDir_static = copystring(value); break;
-    default:
-        printf("Call_initvar_string: unimplemented index %d\n", index);
-        exit(1);
-	}
+void Call_initvar_string(int index, char* value) {
+    switch (index) {
+        case R_Home_x: R_Home = copystring(value); break;
+        case R_TempDir_x: R_TempDir = copystring(value); break;
+        default:
+            printf("Call_initvar_string: unimplemented index %d\n", index);
+            exit(1);
+    }
 }
 
 void Call_initvar_obj(TruffleEnv* env, int index, void* value) {
-	init_utils(env);
-	switch (index) {
-    case R_NilValue_x: R_NilValue_static = value; break;
-    case R_UnboundValue_x: R_UnboundValue_static = value; break;
-    case R_MissingArg_x: R_MissingArg_static = value; break;
-    case R_Srcref_x: R_Srcref_static = value; break;
-    case R_EmptyEnv_x: R_EmptyEnv_static = value; break;
-    case R_Bracket2Symbol_x: R_Bracket2Symbol_static = value; break;
-    case R_BracketSymbol_x: R_BracketSymbol_static = value; break;
-    case R_BraceSymbol_x: R_BraceSymbol_static = value; break;
-    case R_DoubleColonSymbol_x: R_DoubleColonSymbol_static = value; break;
-    case R_ClassSymbol_x: R_ClassSymbol_static = value; break;
-    case R_DeviceSymbol_x: R_DeviceSymbol_static = value; break;
-    case R_DevicesSymbol_x: R_DevicesSymbol_static = value; break;
-    case R_DimNamesSymbol_x: R_DimNamesSymbol_static = value; break;
-    case R_DimSymbol_x: R_DimSymbol_static = value; break;
-    case R_DollarSymbol_x: R_DollarSymbol_static = value; break;
-    case R_DotsSymbol_x: R_DotsSymbol_static = value; break;
-    case R_DropSymbol_x: R_DropSymbol_static = value; break;
-    case R_LastvalueSymbol_x: R_LastvalueSymbol_static = value; break;
-    case R_LevelsSymbol_x: R_LevelsSymbol_static = value; break;
-    case R_ModeSymbol_x: R_ModeSymbol_static = value; break;
-    case R_NameSymbol_x: R_NameSymbol_static = value; break;
-    case R_NamesSymbol_x: R_NamesSymbol_static = value; break;
-    case R_NaRmSymbol_x: R_NaRmSymbol_static = value; break;
-    case R_PackageSymbol_x: R_PackageSymbol_static = value; break;
-    case R_QuoteSymbol_x: R_QuoteSymbol_static = value; break;
-    case R_RowNamesSymbol_x: R_RowNamesSymbol_static = value; break;
-    case R_SeedsSymbol_x: R_SeedsSymbol_static = value; break;
-    case R_SourceSymbol_x: R_SourceSymbol_static = value; break;
-    case R_TspSymbol_x: R_TspSymbol_static = value; break;
-    case R_dot_defined_x: R_dot_defined_static = value; break;
-    case R_dot_Method_x: R_dot_Method_static = value; break;
-    case R_dot_target_x: R_dot_target_static = value; break;
-    case R_SrcrefSymbol_x: R_SrcrefSymbol_static = value; break;
-    case R_SrcfileSymbol_x: R_SrcfileSymbol_static = value; break;
-    case R_NaString_x: R_NaString_static = value; break;
-    case R_BlankString_x: R_BlankString_static = value; break;
-    case R_BlankScalarString_x: R_BlankString_static = value; break;
-    case R_BaseSymbol_x: R_BaseSymbol_static = value; break;
-    case R_NamespaceEnvSymbol_x: R_NamespaceEnvSymbol_static = value; break;
-    // case R_RestartToken_x: R_RestartToken_static = value; break;
-    default:
-    	printf("Call_initvar_obj: unimplemented index %d\n", index);
-    	exit(1);
-	}
+    init_utils(env);
+    switch (index) {
+        case R_NilValue_x: R_NilValue = value; break;
+        case R_UnboundValue_x: R_UnboundValue = value; break;
+        case R_MissingArg_x: R_MissingArg = value; break;
+        case R_EmptyEnv_x: R_EmptyEnv = value; break;
+        case R_Srcref_x: R_Srcref = value; break;
+        case R_Bracket2Symbol_x: R_Bracket2Symbol = value; break;
+        case R_BracketSymbol_x: R_BracketSymbol = value; break;
+        case R_BraceSymbol_x: R_BraceSymbol = value; break;
+        case R_DoubleColonSymbol_x: R_DoubleColonSymbol = value; break;
+        case R_ClassSymbol_x: R_ClassSymbol = value; break;
+        case R_DeviceSymbol_x: R_DeviceSymbol = value; break;
+        case R_DevicesSymbol_x: R_DevicesSymbol = value; break;
+        case R_DimNamesSymbol_x: R_DimNamesSymbol = value; break;
+        case R_DimSymbol_x: R_DimSymbol = value; break;
+        case R_DollarSymbol_x: R_DollarSymbol = value; break;
+        case R_DotsSymbol_x: R_DotsSymbol = value; break;
+        case R_DropSymbol_x: R_DropSymbol = value; break;
+        case R_LastvalueSymbol_x: R_LastvalueSymbol = value; break;
+        case R_LevelsSymbol_x: R_LevelsSymbol = value; break;
+        case R_ModeSymbol_x: R_ModeSymbol = value; break;
+        case R_NameSymbol_x: R_NameSymbol = value; break;
+        case R_NamesSymbol_x: R_NamesSymbol = value; break;
+        case R_NaRmSymbol_x: R_NaRmSymbol = value; break;
+        case R_PackageSymbol_x: R_PackageSymbol = value; break;
+        case R_QuoteSymbol_x: R_QuoteSymbol = value; break;
+        case R_RowNamesSymbol_x: R_RowNamesSymbol = value; break;
+        case R_SeedsSymbol_x: R_SeedsSymbol = value; break;
+        case R_SourceSymbol_x: R_SourceSymbol = value; break;
+        case R_TspSymbol_x: R_TspSymbol = value; break;
+        case R_dot_defined_x: R_dot_defined = value; break;
+        case R_dot_Method_x: R_dot_Method = value; break;
+        case R_dot_target_x: R_dot_target = value; break;
+        case R_dot_packageName_x: R_dot_packageName = value; break;
+        case R_dot_Generic_x: R_dot_Generic = value; break;
+        case R_SrcrefSymbol_x: R_SrcrefSymbol = value; break;
+        case R_SrcfileSymbol_x: R_SrcfileSymbol = value; break;
+        case R_NaString_x: R_NaString = value; break;
+        case R_BlankString_x: R_BlankString = value; break;
+        case R_BlankScalarString_x: R_BlankScalarString = value; break;
+        case R_BaseSymbol_x: R_BaseSymbol = value; break;
+        case R_NamespaceEnvSymbol_x: R_NamespaceEnvSymbol = value; break;
+        case R_RestartToken_x: R_RestartToken = value; break;
+        case R_SortListSymbol_x: R_SortListSymbol = value; break;
+        case R_SpecSymbol_x: R_SpecSymbol = value; break;
+        case R_TripleColonSymbol_x: R_TripleColonSymbol = value; break;
+        case R_PreviousSymbol_x: R_PreviousSymbol = value; break;
+        default:
+            printf("Call_initvar_obj: unimplemented index %d\n", index);
+            exit(1);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
index fcadf58d328e1fd882f6721e5453e36135a1b4b0..0aa1c986c3a7f8c2b6c130c96458da60ea6e976e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -31,11 +32,14 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -49,13 +53,19 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 public abstract class Sprintf extends RBuiltinNode.Arg2 {
 
     static {
-        Casts.noCasts(Sprintf.class);
+        Casts casts = new Casts(Sprintf.class);
+        casts.arg("fmt").mustBe(stringValue()).asStringVector();
     }
 
     public abstract Object executeObject(String fmt, Object args);
 
     @Child private Sprintf sprintfRecursive;
 
+    @Specialization
+    protected RStringVector sprintf(RAbstractStringVector fmt, RList values) {
+        return sprintf(fmt, new RArgsValuesAndNames(values.getReadonlyData(), ArgumentsSignature.empty(values.getLength())));
+    }
+
     @Specialization
     protected RStringVector sprintf(@SuppressWarnings("unused") RAbstractStringVector fmt, @SuppressWarnings("unused") RNull x) {
         return RDataFactory.createEmptyStringVector();
@@ -272,7 +282,10 @@ public abstract class Sprintf extends RBuiltinNode.Arg2 {
                     data[i] = (String) formattedObj;
                 } else {
                     RStringVector formatted = (RStringVector) formattedObj;
-                    assert formatted.getLength() > 0;
+                    if (formatted.getLength() == 0) {
+                        // Any NULL inside args causes the whole result to be empty vector
+                        return formatted;
+                    }
                     data[i] = formatted.getDataAt(i % formatted.getLength());
                 }
             }
@@ -494,7 +507,11 @@ public abstract class Sprintf extends RBuiltinNode.Arg2 {
                             widthAndPrecision(cs, j, fi);
                             j = fi.nextChar;
                         } else if (c == '.') {
-                            // apparently precision can be specified without width as well
+                            // apparently precision can be specified without width as well, but in
+                            // such case the '0' prefix if any should be interpreted as width...
+                            if (fi.padZero) {
+                                fi.padZero = false;
+                            }
                             oneWidth(cs, j + 1, fi, false);
                             j = fi.nextChar;
                         } else {
@@ -532,7 +549,7 @@ public abstract class Sprintf extends RBuiltinNode.Arg2 {
         if (isNumeric(cs[j])) {
             n = number(cs, j, fi);
             j = fi.nextChar;
-        } else {
+        } else if (cs[j] == '*') {
             assert cs[j] == '*';
             if (width) {
                 fi.widthIsArg = true;
@@ -548,6 +565,11 @@ public abstract class Sprintf extends RBuiltinNode.Arg2 {
             } else {
                 n = fi.argc++;
             }
+        } else {
+            if (!isConversion(cs[j])) {
+                throw RError.error(RError.NO_CALLER, Message.UNRECOGNIZED_FORMAT, new String(cs));
+            }
+            n = 0;
         }
         if (width) {
             fi.width = n;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
index 1139df347c88ba98ffad02fb0074ffca2aa536b4..fdb7c6ef17ab8df7029d64ab24eb218d71d091c0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
@@ -298,13 +298,18 @@ public abstract class InternalNode extends OperatorNode {
         @Override
         @ExplodeLoop
         protected Object[] prepareArgs(VirtualFrame frame) {
-            Object[] args = new Object[factory.getSignature().getLength()];
+            int argsLength = factory.getSignature().getLength();
+            if (arguments.length < argsLength - 1) {
+                // Note: GnuR seems to be OK with this and makes up some random values
+                throw error(Message.ARGUMENT_LENGTHS_DIFFER);
+            }
+            Object[] args = new Object[argsLength];
 
             for (int i = 0; i < args.length - 1; i++) {
                 Object arg = arguments[i].execute(frame);
                 args[i] = arg;
             }
-            Object[] varArgs = new Object[arguments.length - (factory.getSignature().getLength() - 1)];
+            Object[] varArgs = new Object[arguments.length - (argsLength - 1)];
             for (int i = 0; i < varArgs.length; i++) {
                 Object arg = arguments[args.length - 1 + i].execute(frame);
                 varArgs[i] = arg;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
index 8defc8bd28a60914b203f7e5221086d8f380fdaa..11315ae9979fbad45ae0f72a77a21b590fadbe42 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.builtin;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.GeneratedBy;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
@@ -107,6 +108,7 @@ public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithA
     }
 
     @Override
+    @TruffleBoundary
     public RBaseNode getErrorContext() {
         ErrorContext context = RError.contextForBuiltin(getRBuiltin());
         return context == null ? this : context;
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/rj.R b/com.oracle.truffle.r.pkgs/rJava/R/rj.R
index bef0b2281f1b0ef5101509cda934d8e2917e6452..5d6727448efcf66cab4845774d2187b3ad192a41 100644
--- a/com.oracle.truffle.r.pkgs/rJava/R/rj.R
+++ b/com.oracle.truffle.r.pkgs/rJava/R/rj.R
@@ -154,7 +154,7 @@ J <- function (class, method, ...)
 #
 
 #' @export
-.jinit <- function ()
+.jinit <- function (...)
 {    
     # do nothing
 }
@@ -186,4 +186,4 @@ J <- function (class, method, ...)
            "*** ", path, "\n",
            "*** are set on LD_LIBRARY_PATH or java.library.path\n",
            "********************************************************\n"))
-}
\ No newline at end of file
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java
index 85c44026426c8740cc9155fb4b5212df37939219..bab299694f7bda289d97a568ed56cfddd44c9729 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java
@@ -34,6 +34,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
@@ -123,10 +124,14 @@ public class AgentObjectSizeFactory extends ObjectSizeFactory {
 
     @Override
     public long getObjectSize(Object obj, IgnoreObjectHandler ignoreObjectHandler) {
-        return getObjectSize(obj, obj, ignoreObjectHandler);
+        return getObjectSize(obj, obj, ignoreObjectHandler, new HashSet<>());
     }
 
-    private long getObjectSize(Object rootObj, Object obj, IgnoreObjectHandler ignoreObjectHandler) {
+    private long getObjectSize(Object rootObj, Object obj, IgnoreObjectHandler ignoreObjectHandler, HashSet<Object> visited) {
+        if (visited.contains(obj)) {
+            return 0;
+        }
+        visited.add(obj);
         try {
             long basicSize = ObjSizeAgent.objectSize(obj);
             long size = basicSize;
@@ -137,7 +142,7 @@ public class AgentObjectSizeFactory extends ObjectSizeFactory {
                     if (elem == null || isNa(elem)) {
                         continue;
                     } else {
-                        size += getObjectSize(rootObj, elem, ignoreObjectHandler);
+                        size += getObjectSize(rootObj, elem, ignoreObjectHandler, visited);
                     }
                 }
             } else {
@@ -154,7 +159,7 @@ public class AgentObjectSizeFactory extends ObjectSizeFactory {
                     } else {
                         TypeCustomizer typeCustomizer = getCustomizer(fieldObj.getClass());
                         if (typeCustomizer == null) {
-                            size += getObjectSize(rootObj, fieldObj, ignoreObjectHandler);
+                            size += getObjectSize(rootObj, fieldObj, ignoreObjectHandler, visited);
                         } else {
                             size += typeCustomizer.getObjectSize(fieldObj);
                         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
index aea39489db98957faa8048ecfe9e8687fddfd185..f20be7018e35f78907005a487464c90e798b5c34 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
@@ -55,6 +55,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.UpdateShareableChildValue;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
@@ -888,6 +889,14 @@ public abstract class REnvironment extends RAttributeStorage {
                 throw new PutException(RError.Message.ENV_ADD_BINDINGS);
             }
         }
+        if (value instanceof RSharingAttributeStorage) {
+            RSharingAttributeStorage shareable = (RSharingAttributeStorage) value;
+            if (!shareable.isShared()) {
+                shareable.incRefCount();
+            }
+        } else {
+            RSharingAttributeStorage.verify(value);
+        }
         frameAccess.put(key, value);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
index 6eba171b149ef4343653812ae289948e71cc6311..897acb3dbc8375c2920d94ff11e09b188877c0dd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
@@ -22,6 +22,9 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
+import java.util.Arrays;
+import java.util.stream.Stream;
+
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.TempPathName;
@@ -29,20 +32,20 @@ import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RUnboundValue;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
+/**
+ * Note: regenerate the C glue code upon any change in this enum, use {@link #main(String[])}.
+ */
 public enum RFFIVariables {
     R_Home(REnvVars.rHome()),
     R_TempDir(null), // Set later
     R_NilValue(RNull.instance),
     R_UnboundValue(RUnboundValue.instance),
     R_MissingArg(RMissing.instance),
-    R_GlobalEnv(null, true),
     R_EmptyEnv(REnvironment.emptyEnv()),
-    R_BaseEnv(null, true),
-    R_BaseNamespace(null, true),
-    R_NamespaceRegistry(null, true),
     R_Srcref(null),
     R_Bracket2Symbol(RDataFactory.createSymbol("[[")),
     R_BracketSymbol(RDataFactory.createSymbol("[")),
@@ -71,6 +74,8 @@ public enum RFFIVariables {
     R_dot_defined(RDataFactory.createSymbol(".defined")),
     R_dot_Method(RDataFactory.createSymbol(".Method")),
     R_dot_target(RDataFactory.createSymbol(".target")),
+    R_dot_packageName(RDataFactory.createSymbol(".packageName")),
+    R_dot_Generic(RDataFactory.createSymbol(".Generic")),
     R_SrcrefSymbol(RDataFactory.createSymbol("srcref")),
     R_SrcfileSymbol(RDataFactory.createSymbol("srcfile")),
     R_NaString(CharSXPWrapper.create(RRuntime.STRING_NA)),
@@ -83,7 +88,11 @@ public enum RFFIVariables {
     R_BlankScalarString(RDataFactory.createStringVectorFromScalar("")),
     R_BaseSymbol(RDataFactory.createSymbol("base")),
     R_NamespaceEnvSymbol(RDataFactory.createSymbol(".__NAMESPACE__.")),
-    R_RestartToken(null);
+    R_RestartToken(null),
+    R_SortListSymbol(RDataFactory.createSymbol("sort.list")),
+    R_SpecSymbol(RDataFactory.createSymbol("spec")),
+    R_TripleColonSymbol(RDataFactory.createSymbol(":::")),
+    R_PreviousSymbol(RDataFactory.createSymbol("previous"));
 
     private Object value;
     public final boolean alwaysUpCall;
@@ -109,9 +118,66 @@ public enum RFFIVariables {
         return values();
     }
 
+    /**
+     * Generates C code necessary to glue the Java and C part together. To run this, run
+     * {@code mx -v r} to get full command line that runs R and replace the main class with this
+     * class.
+     */
     public static void main(String[] args) {
+        R_TempDir.value = "dummy string";
+        System.out.println("// Update com.oracle.truffle.r.native/fficall/src/common/rffi_variablesindex.h with the following: \n");
+        System.out.println("// Generated by RFFIVariables.java:\n");
         for (RFFIVariables var : RFFIVariables.values()) {
             System.out.printf("#define %s_x %d\n", var.name(), var.ordinal());
         }
+        System.out.printf("\n#define VARIABLES_TABLE_SIZE %d", values().length);
+
+        System.out.println("\n\n// Update com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c with the following: \n");
+
+        System.out.println("// Generated by RFFIVariables.java:\n");
+
+        for (RFFIVariables val : values()) {
+            if (val.value instanceof Double) {
+                System.out.printf("double %s;\n", val.name());
+            } else if (val.value instanceof Integer) {
+                System.out.printf("int %s;\n", val.name());
+            } else if (val.value instanceof String) {
+                System.out.printf("char* %s;\n", val.name());
+            } else if (val.value instanceof RSymbol) {
+                System.out.printf("SEXP %s; /* \"%s\" */\n", val.name(), ((RSymbol) val.value).getName());
+            } else {
+                System.out.printf("SEXP %s;\n", val.name());
+            }
+        }
+
+        System.out.println("\nvoid Call_initvar_double(int index, double value) {");
+        printInitVarFor(Arrays.stream(RFFIVariables.values()).filter(x -> x.value instanceof Double), "Call_initvar_double");
+        System.out.println("}\n");
+
+        System.out.println("void Call_initvar_int(int index, int value) {");
+        printInitVarFor(Arrays.stream(RFFIVariables.values()).filter(x -> x.value instanceof Integer), "Call_initvar_int");
+        System.out.println("}\n");
+
+        System.out.println("void Call_initvar_string(int index, char* value) {");
+        printInitVarFor(Arrays.stream(RFFIVariables.values()).filter(x -> x.value instanceof String), "copystring(value)", "Call_initvar_string");
+        System.out.println("}\n");
+
+        System.out.println("void Call_initvar_obj(TruffleEnv* env, int index, void* value) {");
+        System.out.println("    init_utils(env);");
+        printInitVarFor(Arrays.stream(RFFIVariables.values()).filter(x -> !(x.value instanceof Number || x.value instanceof String)), "Call_initvar_obj");
+        System.out.println("}\n");
+    }
+
+    private static void printInitVarFor(Stream<RFFIVariables> vars, String callName) {
+        printInitVarFor(vars, "value", callName);
+    }
+
+    private static void printInitVarFor(Stream<RFFIVariables> vars, String value, String callName) {
+        System.out.println("    switch (index) {");
+        vars.forEachOrdered(x -> System.out.printf("        case %s_x: %s = %s; break;\n", x.name(), x.name(), value));
+        System.out.println("        default:");
+        System.out.printf("            printf(\"%s: unimplemented index %%d\\n\", index);\n", callName);
+        System.out.println("            exit(1);");
+        System.out.println("    }");
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java
index fa3254ef13d6cbded74e37747af70715980050ed..6f05ebf3cacc34bac8b3fd74f1483ecba822d6c3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java
@@ -106,7 +106,9 @@ public final class EvaluatedArgumentsVisitor extends RSyntaxVisitor<Info> {
                         } else {
                             assert signature.getVarArgCount() == 1 : signature;
                             assert innerArguments.length == signature.getLength() || signature.getVarArgIndex() == signature.getLength() - 1 : signature;
-                            assert innerArguments.length >= signature.getLength() - 1 : signature + " " + innerArguments.length;
+                            // holds only for well-formed code, so we cannot rely on it:
+                            // assert innerArguments.length >= signature.getLength() - 1 : signature
+                            // + " " + innerArguments.length;
                         }
                         Info info = Info.createNew();
                         for (int i = innerArguments.length - 1; i >= 0; i--) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 4231476011c26ece8a58fcf9761ecac6eda2daf6..d1e096ec5a2319b4bdf224d05ed423358f5bc4b4 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -67588,6 +67588,33 @@ $`2`
 [1] NA
 
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testCornerCases#Ignored.ImplementationError#
+#{ sprintf(c('hello %d %s', 'world %d %s'), list(2, 'x')) }
+Error in sprintf(c("hello %d %s", "world %d %s"), list(2, "x")) :
+  unsupported type
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testGenericDispatch#Ignored.Unimplemented#
+#{ as.character.myclass65231 <- function(x) '42'; y <- 2; class(y) <- 'myclass65231'; sprintf('%s', y); }
+[1] "42"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testGenericDispatch#Ignored.Unimplemented#
+#{ as.double.myclass65321 <- function(x) 3.14; y <- 'str'; class(y) <- 'myclass65321'; sprintf('%g', y); }
+Error in sprintf("%g", y) :
+  invalid format '%g'; use format %s for character objects
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testGenericDispatch#Ignored.Unimplemented#
+#{ as.double.myclass65321 <- function(x) 3.14; y <- 3L; class(y) <- 'myclass65321'; sprintf('%g', y); }
+[1] "3.14"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
+#{ asdfgerta <- sprintf('%.0f', 1); }
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
+#{ asdfgerta <- sprintf('%0.0f', 1); }
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
+#{ asdfgerta <- sprintf('%0.f', 1); }
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
 #{ sprintf("%.3g", 1.234) }
 [1] "1.23"
@@ -67672,6 +67699,10 @@ character(0)
 #{ sprintf("foo") }
 [1] "foo"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
+#{ sprintf('%s', list('hello world')) }
+[1] "hello world"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
 #{ sprintf('plot_%02g', 3L) }
 [1] "plot_03"
@@ -67692,6 +67723,10 @@ character(0)
 #{ sprintf(c("foo", "bar")) }
 [1] "foo" "bar"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testSprintf#
+#{ sprintf(c('hello', 'world'), NULL) }
+character(0)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testsprintf1#
 #argv <- list('%s is not TRUE', 'identical(fxy, c(1, 2, 3))'); .Internal(sprintf(argv[[1]], argv[[2]]))
 [1] "identical(fxy, c(1, 2, 3)) is not TRUE"
@@ -81895,6 +81930,19 @@ Error in get("x") : object 'x' not found
 #{ x <- function(){3} ; gg <- function() { assign("x", 4) ; g <- function() { if (FALSE) { x <- 2 } ; f <- function() { h <- function() { x() } ; h() } ; f() } ; g() } ; gg() }
 [1] 3
 
+##com.oracle.truffle.r.test.library.base.TestEnvironments.testSharing#
+#{ e <- new.env(); e$vec <- c(1,2,3); vv <- e$vec; vv[[1]] <- 42; e$vec; }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.base.TestEnvironments.testSharing#
+#{ e <- new.env(); f <- new.env(); e$vec <- c(1,2,3); f$vec <- e$vec; e$vec[[1]] <- 42; list(f = f$vec, e = e$vec); }
+$f
+[1] 1 2 3
+
+$e
+[1] 42  2  3
+
+
 ##com.oracle.truffle.r.test.library.base.TestIsElement.testIsElement#
 #{ is.element('b', c('a', 'b', 'b')) }
 [1] TRUE
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sprintf.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sprintf.java
index 4fee95e62edcbd039e3d07d33089fb58368b249e..de38c81297d0623969abaa6c5f35a5d8a162a612 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sprintf.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sprintf.java
@@ -151,5 +151,28 @@ public class TestBuiltin_sprintf extends TestBase {
         assertEval("{ sprintf(c(\"foo %f %d\", \"bar %f %d\"), c(7,1), c(42L, 2L)) }");
         assertEval("{ sprintf(\"%.3g\", 1.234) }");
         assertEval("{ sprintf('plot_%02g', 3L) }");
+        assertEval("{ sprintf(c('hello', 'world'), NULL) }");
+        assertEval("{ sprintf('%s', list('hello world')) }");
+        // Note: we save the result to variable to avoid diff because of different formatting,
+        // however, at least we test that the format expression is not causing any problems to
+        // FastR.
+        assertEval("{ asdfgerta <- sprintf('%0.f', 1); }");
+        assertEval("{ asdfgerta <- sprintf('%0.0f', 1); }");
+        assertEval("{ asdfgerta <- sprintf('%.0f', 1); }");
+    }
+
+    @Test
+    public void testGenericDispatch() {
+        // from the doc: sprintf uses as.character for %s arguments, and as.double for %f, %E, ...
+        assertEval(Ignored.Unimplemented, "{ as.character.myclass65231 <- function(x) '42'; y <- 2; class(y) <- 'myclass65231'; sprintf('%s', y); }");
+        assertEval(Ignored.Unimplemented, "{ as.double.myclass65321 <- function(x) 3.14; y <- 3L; class(y) <- 'myclass65321'; sprintf('%g', y); }");
+        // catch: probably before calling as.double there is numeric validation? Strings are not OK
+        // even, when they have as.double function
+        assertEval(Ignored.Unimplemented, "{ as.double.myclass65321 <- function(x) 3.14; y <- 'str'; class(y) <- 'myclass65321'; sprintf('%g', y); }");
+    }
+
+    @Test
+    public void testCornerCases() {
+        assertEval(Ignored.ImplementationError, "{ sprintf(c('hello %d %s', 'world %d %s'), list(2, 'x')) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java
index 1f2f9713d5eda8af8729943f9336c0f680c3aa87..6afdff5532990a62d8d2a4cf4632d6cd39fc34b5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java
@@ -294,4 +294,10 @@ public class TestEnvironments extends TestBase {
         // Turning frame into an environment should not evaluate all the promises:
         assertEval("{ makefun <- function(f,s) function(a) f(a); s <- function() cat('side effect'); .Internal(islistfactor(environment(makefun(function(b) 2*b, s()))$f, F)); }");
     }
+
+    @Test
+    public void testSharing() {
+        assertEval("{ e <- new.env(); e$vec <- c(1,2,3); vv <- e$vec; vv[[1]] <- 42; e$vec; }");
+        assertEval("{ e <- new.env(); f <- new.env(); e$vec <- c(1,2,3); f$vec <- e$vec; e$vec[[1]] <- 42; list(f = f$vec, e = e$vec); }");
+    }
 }
diff --git a/mx.fastr/mx_fastr_edinclude.py b/mx.fastr/mx_fastr_edinclude.py
index 656ecaa88cbacf2437410d07dc3a1888041853ee..8cfc59d183694ba9d77af39e862e1f28e5caa50f 100644
--- a/mx.fastr/mx_fastr_edinclude.py
+++ b/mx.fastr/mx_fastr_edinclude.py
@@ -27,17 +27,7 @@ Handles all the editing of R FFI header files from the GNUR include directory to
 FastR include directory.
 '''
 # variables in Rinternals.h that are Java Objects and so remapped to functions
-r_internals_vars = ['R_NilValue', 'R_UnboundValue', 'R_MissingArg', 'R_GlobalEnv',
-    'R_EmptyEnv', 'R_BaseEnv', 'R_BaseNamespace', 'R_NamespaceRegistry', 'R_Srcref', 'R_Bracket2Symbol',
-    'R_BracketSymbol', 'R_BraceSymbol', 'R_ClassSymbol', 'R_DeviceSymbol', 'R_DevicesSymbol',
-    'R_DimNamesSymbol', 'R_DimSymbol', 'R_DollarSymbol', 'R_DotsSymbol', 'R_DropSymbol', 'R_LastvalueSymbol',
-    'R_LevelsSymbol', 'R_ModeSymbol', 'R_NameSymbol', 'R_NamesSymbol', 'R_NaRmSymbol', 'R_PackageSymbol',
-    'R_QuoteSymbol', 'R_RowNamesSymbol', 'R_SeedsSymbol', 'R_SourceSymbol', 'R_TspSymbol', 'R_dot_defined',
-    'R_dot_Method', 'R_dot_target', 'R_SrcrefSymbol', 'R_SrcfileSymbol', 'R_NaString', 'R_BlankString',
-    'R_DoubleColonSymbol', 'R_BlankScalarString', 'R_BaseSymbol', 'R_baseSymbol', 'R_NamespaceEnvSymbol']
-
-interface_vars = ['R_Home', 'R_TempDir',]
-
+r_internals_vars = ['R_GlobalEnv', 'R_BaseEnv', 'R_BaseNamespace', 'R_NamespaceRegistry']
 
 def edinclude(args):
     '''
@@ -127,21 +117,10 @@ def ed_r_internals(gnu_dir):
 def rewrite_var(f, var, line):
     f.write('#ifdef FASTR\n')
     f.write('LibExtern SEXP FASTR_{0}();\n'.format(var))
-    if var == 'R_baseSymbol': # alias
-        f.write('#define {0} FASTR_R_BaseSymbol()\n'.format(var))
-    else:
-        f.write('#define {0} FASTR_{0}()\n'.format(var))
+    f.write('#define {0} FASTR_{0}()\n'.format(var))
     f.write('#else\n')
-    # Ugly special case, comment split on two lines, just
-    if var == 'R_EmptyEnv':
-        split = line.split(';')
-        f.write(split[0])
-        f.write(';\n')
-        f.write('#endif\n')
-        f.write(split[1])
-    else:
-        f.write(line)
-        f.write('#endif\n')
+    f.write(line)
+    f.write('#endif\n')
 
 def is_internal_var(line):
     for var in r_internals_vars:
@@ -173,12 +152,6 @@ extern Rboolean FASTR_R_Interactive();
 #else
 '''
 
-rhome_rewrite = '''#ifdef FASTR
-extern char* FASTR_R_Home();
-#define R_Home FASTR_R_Home()
-#else
-'''
-
 def ed_r_interface(gnu_dir):
     r_interface_h = join(gnu_dir, 'Rinterface.h')
     with open(r_interface_h) as f:
@@ -194,10 +167,6 @@ def ed_r_interface(gnu_dir):
                 f.write(interactive_rewrite)
                 f.write(line)
                 f.write('#endif\n')
-            elif 'R_Home;' in line:
-                f.write(rhome_rewrite)
-                f.write(line)
-                f.write('#endif\n')
             else:
                 f.write(line)
 
diff --git a/mx.fastr/mx_fastr_mkgramrd.py b/mx.fastr/mx_fastr_mkgramrd.py
index 5481589664725b5f9c513bc15a7c2c56db1c8349..244c3b4a62b7bbe25408fd143f8e0d928f1d8ed4 100644
--- a/mx.fastr/mx_fastr_mkgramrd.py
+++ b/mx.fastr/mx_fastr_mkgramrd.py
@@ -26,10 +26,8 @@ def mkgramrd(args):
     converts GNU R gramRd.c into one suitable for invoking via FastR
     '''
     parse_defs = '''
-extern SEXP FASTR_R_SrcrefSymbol();
-#define R_SrcrefSymbol FASTR_R_SrcrefSymbol()
-extern SEXP FASTR_R_SrcfileSymbol();
-#define R_SrcfileSymbol FASTR_R_SrcfileSymbol()
+extern SEXP R_SrcrefSymbol;
+extern SEXP R_SrcfileSymbol;
 extern int R_ParseContextLast;
 #define R_EOF -1
 #define PARSE_ERROR_SIZE 256
@@ -39,8 +37,7 @@ static char    R_ParseContext[PARSE_CONTEXT_SIZE];
 int    R_ParseContextLast;
 int    R_ParseContextLine;
 int R_ParseError;
-extern SEXP FASTR_R_EmptyEnv();
-#define R_EmptyEnv FASTR_R_EmptyEnv()
+extern SEXP R_EmptyEnv;
 extern SEXP R_NewHashedEnv(SEXP a, SEXP b);
 
 char *dgettext(const char *p, const char *msgid) {