diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/TruffleCallHelper.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/TruffleCallHelper.java
index 420b4218e7b55c868b73c880a4fd5a45476be0e4..64126ff2c7de51b08f2db0ef561c15ee636b5510 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/TruffleCallHelper.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/TruffleCallHelper.java
@@ -31,6 +31,8 @@ import com.oracle.truffle.r.engine.interop.NativeDoubleArray;
 import com.oracle.truffle.r.engine.interop.NativeIntegerArray;
 import com.oracle.truffle.r.engine.interop.NativeLogicalArray;
 import com.oracle.truffle.r.engine.interop.NativeRawArray;
+import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
+import com.oracle.truffle.r.nodes.ffi.UpCallsRFFIImpl;
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -42,14 +44,13 @@ import com.oracle.truffle.r.runtime.data.RScalar;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.RUnboundValue;
 import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
-import com.oracle.truffle.r.runtime.ffi.JavaUpCallsRFFI;
 
 /**
  * A wrapper class that can be instantiated and export for method lookup. For now just delegates to
- * {@link JavaUpCallsRFFI}.
+ * {@link UpCallsRFFIImpl}.
  *
  */
-public class TruffleCallHelper extends JavaUpCallsRFFI {
+public class TruffleCallHelper extends UpCallsRFFIImpl {
     private static TruffleCallHelper singleton;
     private static TruffleObject singletonTruffleObject;
 
@@ -62,7 +63,7 @@ public class TruffleCallHelper extends JavaUpCallsRFFI {
     }
 
     public Object charSXPToNativeCharArray(Object x) {
-        CharSXPWrapper chars = guaranteeInstanceOf(x, CharSXPWrapper.class);
+        CharSXPWrapper chars = RFFIUtils.guaranteeInstanceOf(x, CharSXPWrapper.class);
         return new NativeCharArray(chars.getContents().getBytes());
     }
 
diff --git a/com.oracle.truffle.r.native/fficall/src/common/coerce_fastr.c b/com.oracle.truffle.r.native/fficall/src/common/coerce_fastr.c
index a49307a11779bc2093e0410ad88ebc71d4a5f449..2e0b2fe4c58d3d1fc3eb9390f065138dd297030a 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/coerce_fastr.c
+++ b/com.oracle.truffle.r.native/fficall/src/common/coerce_fastr.c
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -425,38 +425,3 @@ SEXP Rf_coerceVector(SEXP v, SEXPTYPE type)
 #undef COERCE_ERROR
 
 
-double Rf_asReal(SEXP x)
-{
-    int warn = 0;
-    double res;
-
-    if (isVectorAtomic(x) && XLENGTH(x) >= 1) {
-	switch (TYPEOF(x)) {
-	case LGLSXP:
-	    res = RealFromLogical(LOGICAL(x)[0], &warn);
-	    CoercionWarning(warn);
-	    return res;
-	case INTSXP:
-	    res = RealFromInteger(INTEGER(x)[0], &warn);
-	    CoercionWarning(warn);
-	    return res;
-	case REALSXP:
-	    return REAL(x)[0];
-	case CPLXSXP:
-	    res = RealFromComplex(COMPLEX(x)[0], &warn);
-	    CoercionWarning(warn);
-	    return res;
-	case STRSXP:
-	    res = RealFromString(STRING_ELT(x, 0), &warn);
-	    CoercionWarning(warn);
-	    return res;
-	default:
-	    UNIMPLEMENTED_TYPE("asReal", x);
-	}
-    } else if(TYPEOF(x) == CHARSXP) {
-	res = RealFromString(x, &warn);
-	CoercionWarning(warn);
-	return res;
-    }
-    return NA_REAL;
-}
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
index 233a58dbc129066a73b9a1cb364bc7cffde33b1a..723290cfea319d97cce90c45762f13087bd4ed28 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@ static jfieldID parseExprFieldID;
 
 void init_parse(JNIEnv *env) {
 	parseMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ParseVector", "(Ljava/lang/Object;ILjava/lang/Object;)Ljava/lang/Object;", 0);
-	parseResultClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/ParseResult");
+	parseResultClass = checkFindClass(env, "com/oracle/truffle/r/nodes/ffi/ParseResult");
 	parseStatusFieldID = checkGetFieldID(env, parseResultClass, "parseStatus", "I", 0);
 	parseExprFieldID = checkGetFieldID(env, parseResultClass, "expr", "Ljava/lang/Object;", 0);
 }
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 540621ad1600f0694ab8c21c598f3fbe7efd6dcf..bfa6afc5257d824d9321e3269b5779d99cebf2d4 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -90,7 +90,7 @@ static jmethodID STRING_ELT_MethodID;
 static jmethodID VECTOR_ELT_MethodID;
 static jmethodID LENGTH_MethodID;
 static jmethodID Rf_asIntegerMethodID;
-//static jmethodID Rf_asRealMethodID;
+static jmethodID Rf_asRealMethodID;
 static jmethodID Rf_asCharMethodID;
 static jmethodID Rf_mkCharLenCEMethodID;
 static jmethodID Rf_asLogicalMethodID;
@@ -195,7 +195,7 @@ void init_internals(JNIEnv *env) {
 	VECTOR_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "VECTOR_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0);
 	LENGTH_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "LENGTH", "(Ljava/lang/Object;)I", 0);
 	Rf_asIntegerMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asInteger", "(Ljava/lang/Object;)I", 0);
-//	Rf_asRealMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asReal", "(Ljava/lang/Object;)D", 0);
+	Rf_asRealMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asReal", "(Ljava/lang/Object;)D", 0);
 	Rf_asCharMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asChar", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_mkCharLenCEMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_mkCharLenCE", "([BI)Ljava/lang/Object;", 0);
 	Rf_asLogicalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asLogical", "(Ljava/lang/Object;)I", 0);
@@ -1246,11 +1246,11 @@ int Rf_asInteger(SEXP x) {
 	return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_asIntegerMethodID, x);
 }
 
-//double Rf_asReal(SEXP x) {
-//	TRACE(TARGp, x);
-//	JNIEnv *thisenv = getEnv();
-//	return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_asRealMethodID, x);
-//}
+double Rf_asReal(SEXP x) {
+	TRACE(TARGp, x);
+	JNIEnv *thisenv = getEnv();
+	return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_asRealMethodID, x);
+}
 
 Rcomplex Rf_asComplex(SEXP x){
 	unimplemented("Rf_asLogical");
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..95b124519c139f21b75544d9bd0ed43123c65a5b
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.ffi;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.r.nodes.unary.CastStringNode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
+
+@TypeSystemReference(RTypesFlatLayout.class)
+public abstract class AsCharNode extends FFIUpCallNode.Arg1 {
+    private static final CharSXPWrapper CharSXPWrapper_NA = CharSXPWrapper.create(RRuntime.STRING_NA);
+
+    @Specialization
+    protected CharSXPWrapper asChar(CharSXPWrapper obj) {
+        return obj;
+    }
+
+    @Specialization
+    protected CharSXPWrapper asChar(RAbstractStringVector obj) {
+        if (obj.getLength() == 0) {
+            return CharSXPWrapper_NA;
+        } else {
+            return CharSXPWrapper.create(obj.getDataAt(0));
+        }
+    }
+
+    @Specialization
+    protected CharSXPWrapper asChar(RSymbol obj) {
+        return CharSXPWrapper.create(obj.getName());
+    }
+
+    @Specialization(guards = "isVectorAtomicNodeLG0.execute(obj)")
+    protected CharSXPWrapper asChar(Object obj,
+                    @Cached("createNonPreserving()") CastStringNode castStringNode,
+                    @SuppressWarnings("unused") @Cached("create()") IsVectorAtomicNodeLG0 isVectorAtomicNodeLG0) {
+        Object castObj = castStringNode.executeString(obj);
+        if (castObj instanceof String) {
+            return CharSXPWrapper.create((String) castObj);
+        } else if (castObj instanceof RAbstractStringVector) {
+            return CharSXPWrapper.create(((RAbstractStringVector) castObj).getDataAt(0));
+        } else {
+            throw RInternalError.shouldNotReachHere();
+        }
+    }
+
+    @Fallback
+    protected CharSXPWrapper asCharFallback(@SuppressWarnings("unused") Object obj) {
+        return CharSXPWrapper_NA;
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2cb77d981e2e68b5664679817b3c804eac5cd43
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.ffi;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+
+/**
+ * Implements the {@code Rf_asInteger} GNU R function . The behavior is subtly different (more
+ * permissive error-wise) that {@link CastIntegerNode}. Non-castable values return {@code NA}.
+ */
+@TypeSystemReference(RTypesFlatLayout.class)
+public abstract class AsIntegerNode extends FFIUpCallNode.Arg1 {
+
+    @Specialization
+    protected int asInteger(int obj) {
+        return obj;
+    }
+
+    @Specialization
+    protected int asInteger(double obj) {
+        return (int) obj;
+    }
+
+    @Specialization
+    protected int asReal(RAbstractDoubleVector obj) {
+        if (obj.getLength() == 0) {
+            return RRuntime.INT_NA;
+        }
+        return (int) obj.getDataAt(0);
+    }
+
+    @Specialization
+    protected int asReal(RAbstractIntVector obj) {
+        if (obj.getLength() == 0) {
+            return RRuntime.INT_NA;
+        }
+        return obj.getDataAt(0);
+    }
+
+    @Specialization(guards = "isVectorAtomicNodeLG0.execute(obj)")
+    protected int asReal(Object obj,
+                    @Cached("createNonPreserving()") CastIntegerNode castIntegerNode,
+                    @SuppressWarnings("unused") @Cached("create()") IsVectorAtomicNodeLG0 isVectorAtomicNodeLG0) {
+        Object castObj = castIntegerNode.executeInt(obj);
+        if (castObj instanceof Integer) {
+            return (Integer) castObj;
+        } else if (castObj instanceof RAbstractIntVector) {
+            return ((RAbstractIntVector) castObj).getDataAt(0);
+        } else {
+            throw RInternalError.shouldNotReachHere();
+        }
+    }
+
+    @Fallback
+    protected int asRealFallback(@SuppressWarnings("unused") Object obj) {
+        return RRuntime.INT_NA;
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..bb67a13e0314bfc8957312e46778c31d9d2f2ffd
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.ffi;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.r.nodes.unary.CastLogicalNode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+
+@TypeSystemReference(RTypesFlatLayout.class)
+@ImportStatic(IsVectorAtomicNodeLG0.class)
+public abstract class AsLogicalNode extends FFIUpCallNode.Arg1 {
+
+    @Specialization
+    protected int asLogical(byte b) {
+        return b;
+    }
+
+    @Specialization
+    protected int asLogical(RAbstractLogicalVector obj) {
+        if (obj.getLength() == 0) {
+            return RRuntime.INT_NA;
+        }
+        return obj.getDataAt(0);
+    }
+
+    @Specialization(guards = "isVectorAtomicNodeLG0.execute(obj)")
+    protected int asLogical(Object obj,
+                    @Cached("createNonPreserving()") CastLogicalNode castLogicalNode,
+                    @SuppressWarnings("unused") @Cached("create()") IsVectorAtomicNodeLG0 isVectorAtomicNodeLG0) {
+        Object castObj = castLogicalNode.execute(obj);
+        if (castObj instanceof Byte) {
+            return (byte) castObj;
+        } else if (castObj instanceof RAbstractLogicalVector) {
+            return ((RAbstractLogicalVector) castObj).getDataAt(0);
+        } else {
+            throw RInternalError.shouldNotReachHere();
+        }
+    }
+
+    @Fallback
+    protected int asLogicalFallback(@SuppressWarnings("unused") Object obj) {
+        return RRuntime.INT_NA;
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java
index cfca08ce67c7e0a3170bbd9f667709baf99665ab..27502aea2ca1bb55f6840e94bb4fec5604f4ca46 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java
@@ -12,37 +12,36 @@
  */
 package com.oracle.truffle.r.nodes.ffi;
 
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
+import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 /**
  * Implements the {@code Rf_asReal} GNU R function (which is also used internally). The behavior is
  * subtly different (more permissive error-wise) that {@link CastDoubleNode}. Non-castable values
  * return {@code NA}.
  */
-public abstract class AsRealNode extends Node {
-    @Child private CastDoubleNode castDoubleNode = CastDoubleNode.createNonPreserving();
+@TypeSystemReference(RTypesFlatLayout.class)
+@ImportStatic(IsVectorAtomicNodeLG0.class)
+public abstract class AsRealNode extends FFIUpCallNode.Arg1 {
 
     public abstract double execute(Object obj);
 
     @Specialization
-    protected double asReal(Double obj) {
+    protected double asReal(double obj) {
         return obj;
     }
 
     @Specialization
-    protected double asReal(Integer obj) {
+    protected double asReal(int obj) {
         return obj;
     }
 
@@ -62,13 +61,15 @@ public abstract class AsRealNode extends Node {
         return obj.getDataAt(0);
     }
 
-    @Specialization(guards = "isVectorAtomic(obj)")
-    protected double asReal(Object obj) {
+    @Specialization(guards = "isVectorAtomicNodeLG0.execute(obj)")
+    protected double asReal(Object obj,
+                    @Cached("createNonPreserving()") CastDoubleNode castDoubleNode,
+                    @SuppressWarnings("unused") @Cached("create()") IsVectorAtomicNodeLG0 isVectorAtomicNodeLG0) {
         Object castObj = castDoubleNode.executeDouble(obj);
         if (castObj instanceof Double) {
             return (double) castObj;
-        } else if (castObj instanceof RDoubleVector) {
-            return ((RDoubleVector) castObj).getDataAt(0);
+        } else if (castObj instanceof RAbstractDoubleVector) {
+            return ((RAbstractDoubleVector) castObj).getDataAt(0);
         } else {
             throw RInternalError.shouldNotReachHere();
         }
@@ -79,16 +80,4 @@ public abstract class AsRealNode extends Node {
         return RRuntime.DOUBLE_NA;
     }
 
-    public static boolean isVectorAtomic(Object obj) {
-        return obj instanceof Byte || obj instanceof String || isNonScalarVectorAtomic(obj);
-    }
-
-    private static boolean isNonScalarVectorAtomic(Object obj) {
-        if (obj instanceof RAbstractLogicalVector || obj instanceof RAbstractStringVector || obj instanceof RAbstractComplexVector) {
-            RAbstractVector avec = (RAbstractVector) obj;
-            return avec.getLength() >= 1;
-        } else {
-            return false;
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFIFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallNode.java
similarity index 50%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFIFactory.java
rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallNode.java
index 6bf0183d8e85302127526f6631c99f81662030f6..7cf4549706518f3fc9c496a10f11bcc125c9d9c2 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFIFactory.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallNode.java
@@ -20,12 +20,48 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi;
+package com.oracle.truffle.r.nodes.ffi;
 
-public class JavaUpCallsRFFIFactory extends UpCallsRFFIFactory {
+import com.oracle.truffle.api.nodes.Node;
+
+public abstract class FFIUpCallNode extends Node {
+    protected abstract int numArgs();
+
+    public abstract static class Arg0 extends FFIUpCallNode {
+        public abstract Object executeObject();
+
+        @Override
+        protected int numArgs() {
+            return 0;
+        }
 
-    @Override
-    public UpCallsRFFI getUpcallsRFFI() {
-        return new JavaUpCallsRFFI();
     }
+
+    public abstract static class Arg1 extends FFIUpCallNode {
+        public abstract Object executeObject(Object arg0);
+
+        @Override
+        protected int numArgs() {
+            return 1;
+        }
+    }
+
+    public abstract static class Arg2 extends FFIUpCallNode {
+        public abstract Object executeObject(Object arg0, Object arg1);
+
+        @Override
+        protected int numArgs() {
+            return 2;
+        }
+    }
+
+    public abstract static class Arg3 extends FFIUpCallNode {
+        public abstract Object executeObject(Object arg0, Object arg1, Object arg2);
+
+        @Override
+        protected int numArgs() {
+            return 3;
+        }
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c159c108c494f4d645280b917ea9c78937a6934
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.ffi;
+
+import java.util.function.Supplier;
+
+import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.frame.FrameDescriptor;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
+
+public final class FFIUpCallRootNode extends RootNode {
+    private static RootCallTarget[] rootCallTargets = new RootCallTarget[UpCallsIndex.TABLE_LENGTH];
+
+    @Child private FFIUpCallNode theFFIUpCallNode;
+    private final int numArgs;
+
+    private FFIUpCallRootNode(FFIUpCallNode child) {
+        super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor());
+        theFFIUpCallNode = child;
+        this.numArgs = child.numArgs();
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        Object[] args = frame.getArguments();
+        switch (numArgs) {
+            case 0:
+                return ((FFIUpCallNode.Arg0) theFFIUpCallNode).executeObject();
+            case 1:
+                return ((FFIUpCallNode.Arg1) theFFIUpCallNode).executeObject(args[0]);
+            case 2:
+                return ((FFIUpCallNode.Arg2) theFFIUpCallNode).executeObject(args[0], args[1]);
+            case 3:
+                return ((FFIUpCallNode.Arg3) theFFIUpCallNode).executeObject(args[0], args[1], args[2]);
+            default:
+                throw RInternalError.shouldNotReachHere();
+        }
+    }
+
+    static void add(int index, Supplier<FFIUpCallNode> constructor) {
+        FFIUpCallRootNode rootNode = new FFIUpCallRootNode(constructor.get());
+        rootCallTargets[index] = Truffle.getRuntime().createCallTarget(rootNode);
+    }
+
+    public static RootCallTarget getCallTarget(int index) {
+        RootCallTarget target = rootCallTargets[index];
+        assert target != null;
+        return target;
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/IsVectorAtomicNodeLG0.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/IsVectorAtomicNodeLG0.java
new file mode 100644
index 0000000000000000000000000000000000000000..337982d1e8c35e832edda26f419bd53d31cf03d6
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/IsVectorAtomicNodeLG0.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.ffi;
+
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+/**
+ * Implements the GNU R function {@code isVectorAtomic} and checks whether length is > 0.
+ */
+@TypeSystemReference(RTypesFlatLayout.class)
+public abstract class IsVectorAtomicNodeLG0 extends Node {
+    public abstract boolean execute(Object obj);
+
+    @Specialization
+    protected boolean isVectorAtomicNode(@SuppressWarnings("unused") Byte obj) {
+        return true;
+    }
+
+    @Specialization
+    protected boolean isVectorAtomicNode(@SuppressWarnings("unused") String obj) {
+        return true;
+    }
+
+    @Specialization
+    protected boolean isVectorAtomicNode(RAbstractLogicalVector obj) {
+        return obj.getLength() > 0;
+    }
+
+    @Specialization
+    protected boolean isVectorAtomicNode(RAbstractIntVector obj) {
+        return obj.getLength() > 0;
+    }
+
+    @Specialization
+    protected boolean isVectorAtomicNode(RAbstractDoubleVector obj) {
+        return obj.getLength() > 0;
+    }
+
+    @Specialization
+    protected boolean isVectorAtomicNode(RAbstractStringVector obj) {
+        return obj.getLength() > 0;
+    }
+
+    @Specialization
+    protected boolean isVectorAtomicNode(RAbstractComplexVector obj) {
+        return obj.getLength() > 0;
+    }
+
+    @Fallback
+    protected boolean isVectorAtomicNode(@SuppressWarnings("unused") Object obj) {
+        return false;
+    }
+
+    public static IsVectorAtomicNodeLG0 create() {
+        return IsVectorAtomicNodeLG0NodeGen.create();
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b443987e44dea159fc884aef156d3318affecdc
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.ffi;
+
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.unimplemented;
+
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+
+/**
+ * Nodes that implement {@code CAR}, {@code CDR}, etc. N.B. GNU R does not error check the
+ * arguments; it will crash (segv) if given, say, a numeric arg.
+ */
+public final class ListAccessNodes {
+
+    @TypeSystemReference(RTypesFlatLayout.class)
+    public abstract static class CARNode extends FFIUpCallNode.Arg1 {
+        @Specialization
+        protected Object car(RPairList pl) {
+            return pl.car();
+        }
+
+        @Specialization
+        protected Object car(RLanguage lang) {
+            return lang.getDataAtAsObject(0);
+        }
+
+        @Fallback
+        protected Object car(@SuppressWarnings("unused") Object obj) {
+            throw unimplemented("CAR only works on pair lists and language objects");
+        }
+
+    }
+
+    @TypeSystemReference(RTypesFlatLayout.class)
+    public abstract static class CDRNode extends FFIUpCallNode.Arg1 {
+        @Specialization
+        protected Object cdr(RPairList pl) {
+            return pl.cdr();
+        }
+
+        @Specialization
+        protected Object cdr(RLanguage lang) {
+            RPairList l = lang.getPairList();
+            return l.cdr();
+        }
+
+        @Fallback
+        protected Object cdr(@SuppressWarnings("unused") Object obj) {
+            throw unimplemented("CDR only works on pair lists and language objects");
+
+        }
+    }
+
+    @TypeSystemReference(RTypesFlatLayout.class)
+    public abstract static class CADRNode extends FFIUpCallNode.Arg1 {
+        @Specialization
+        protected Object cadr(RPairList pl) {
+            return pl.cadr();
+        }
+
+        @Specialization
+        protected Object cadr(RLanguage lang) {
+            return lang.getDataAtAsObject(1);
+        }
+
+        @Fallback
+        protected Object cadr(@SuppressWarnings("unused") Object obj) {
+            throw unimplemented("CADR only works on pair lists and language objects");
+        }
+
+    }
+
+    @TypeSystemReference(RTypesFlatLayout.class)
+    public abstract static class CADDRNode extends FFIUpCallNode.Arg1 {
+        @Specialization
+        protected Object caddr(RPairList pl) {
+            return pl.caddr();
+        }
+
+        @Specialization
+        protected Object caddr(RLanguage lang) {
+            return lang.getDataAtAsObject(2);
+        }
+
+        @Fallback
+        protected Object caddr(@SuppressWarnings("unused") Object obj) {
+            throw unimplemented("CADDR only works on pair lists and language objects");
+        }
+
+    }
+
+    @TypeSystemReference(RTypesFlatLayout.class)
+    public abstract static class CDDRNode extends FFIUpCallNode.Arg1 {
+        @Specialization
+        protected Object cddr(RPairList pl) {
+            return pl.cddr();
+        }
+
+        @Specialization
+        protected Object cdr(RLanguage lang) {
+            RPairList l = lang.getPairList();
+            return l.cddr();
+        }
+
+        @Fallback
+        protected Object cddr(@SuppressWarnings("unused") Object obj) {
+            throw unimplemented("CDDR only works on pair lists and language objects");
+
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d833e1641f64b7dc1614d2792ff47265f4cacee
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.ffi;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
+import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
+
+public final class MiscNodes {
+
+    @TypeSystemReference(RTypesFlatLayout.class)
+    public abstract static class LENGTHNode extends FFIUpCallNode.Arg1 {
+
+        @Specialization
+        protected int length(@SuppressWarnings("unused") RNull obj) {
+            return 0;
+        }
+
+        @Specialization
+        protected int length(@SuppressWarnings("unused") int x) {
+            return 1;
+        }
+
+        @Specialization
+        protected int length(@SuppressWarnings("unused") double x) {
+            return 1;
+        }
+
+        @Specialization
+        protected int length(@SuppressWarnings("unused") byte x) {
+            return 1;
+        }
+
+        @Specialization
+        protected int length(@SuppressWarnings("unused") String x) {
+            return 1;
+        }
+
+        @Specialization
+        protected int length(CharSXPWrapper obj) {
+            return obj.getContents().length();
+        }
+
+        @Specialization
+        protected int length(RAbstractContainer obj) {
+            // Should this use RLengthNode?
+            return obj.getLength();
+        }
+
+        @Fallback
+        protected int length(Object obj) {
+            CompilerDirectives.transferToInterpreter();
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.LENGTH_MISAPPLIED, SEXPTYPE.gnuRTypeForObject(obj).name());
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ParseResult.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ParseResult.java
similarity index 90%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ParseResult.java
rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ParseResult.java
index d4c71e01bd9db7b54b821bdeec2afda8ea9589b6..1a5dc11242769558430a273c3f16dc61f598b8bb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ParseResult.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ParseResult.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,7 +20,9 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi;
+package com.oracle.truffle.r.nodes.ffi;
+
+import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 
 /**
  * Used in implementation of {@link UpCallsRFFI#R_ParseVector(Object, int, Object)}.
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java
similarity index 87%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIUtils.java
rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java
index fa21f16be67c76d37887a304de50831c867f8f4d..6cda0147f1d4cb3b3a96c11ac7e8b66924e5072c 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIUtils.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi;
+package com.oracle.truffle.r.nodes.ffi;
 
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
@@ -29,6 +29,7 @@ import java.nio.file.Path;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.FastROptions;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RSymbol;
@@ -181,6 +182,34 @@ public class RFFIUtils {
         }
     }
 
+    // Error handling
+    static RuntimeException unimplemented() {
+        return unimplemented("");
+    }
+
+    static RuntimeException unimplemented(String message) {
+        throw RInternalError.unimplemented(message);
+    }
+
+    static void guarantee(boolean condition) {
+        guarantee(condition, "");
+    }
+
+    static void guarantee(boolean condition, String message) {
+        if (!condition) {
+            unimplemented(message);
+        }
+    }
+
+    public static <T> T guaranteeInstanceOf(Object x, Class<T> clazz) {
+        if (x == null) {
+            guarantee(false, "unexpected type: null instead of " + clazz.getSimpleName());
+        } else if (!clazz.isInstance(x)) {
+            guarantee(false, "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of " + clazz.getSimpleName());
+        }
+        return clazz.cast(x);
+    }
+
     // Miscellaneous support functions
 
     public static byte[] wrapChar(char v) {
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/TraceUpCallsAdapter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TraceUpCallsAdapter.java
similarity index 99%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/TraceUpCallsAdapter.java
rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TraceUpCallsAdapter.java
index 1b6d8aab816bc180e5a361d2e3311c02d40e3749..4dea6ab018ec73cb19f80b0ca3b955733c7237d4 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/TraceUpCallsAdapter.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TraceUpCallsAdapter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.nodes.ffi;
 
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
@@ -28,7 +28,6 @@ import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.ffi.RFFIUtils;
 import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 
 public class TraceUpCallsAdapter implements UpCallsRFFI {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsIndex.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsIndex.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa9f03d430184303fbafa64f71dd0c3e15d96b46
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsIndex.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.ffi;
+
+import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CADDRNodeGen;
+import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CADRNodeGen;
+import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CARNodeGen;
+import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CDDRNodeGen;
+import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CDRNodeGen;
+import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.LENGTHNodeGen;
+import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
+
+/**
+ * Provides indices for indexing into table of {@link RootCallTarget}s for any upcall implemented in
+ * Truffle, and a {@link #register} method to associate exactly those calls which are implemented in
+ * Truffle. The indices were initially generated automatically from {@link UpCallsRFFI}.
+ */
+final class UpCallsIndex {
+    static final int TABLE_LENGTH = 110;
+
+    static final int CADDR = 0;
+    static final int CADR = 1;
+    static final int CAR = 2;
+    static final int CDDR = 3;
+    static final int CDR = 4;
+    static final int DUPLICATE_ATTRIB = 5;
+    static final int ENCLOS = 6;
+    static final int GetRNGstate = 7;
+    static final int INTEGER = 8;
+    static final int LENGTH = 9;
+    static final int LOGICAL = 10;
+    static final int NAMED = 11;
+    static final int OBJECT = 12;
+    static final int PRINTNAME = 13;
+    static final int PRVALUE = 14;
+    static final int PutRNGstate = 15;
+    static final int RAW = 16;
+    static final int RDEBUG = 17;
+    static final int REAL = 18;
+    static final int RSTEP = 19;
+    static final int R_BaseEnv = 20;
+    static final int R_BaseNamespace = 21;
+    static final int R_BindingIsLocked = 22;
+    static final int R_CleanUp = 23;
+    static final int R_ExternalPtrAddr = 24;
+    static final int R_ExternalPtrProt = 25;
+    static final int R_ExternalPtrTag = 26;
+    static final int R_FindNamespace = 27;
+    static final int R_GlobalContext = 28;
+    static final int R_GlobalEnv = 29;
+    static final int R_HomeDir = 30;
+    static final int R_MakeExternalPtr = 31;
+    static final int R_NamespaceRegistry = 32;
+    static final int R_NewHashedEnv = 33;
+    static final int R_ParseVector = 34;
+    static final int R_SetExternalPtrAddr = 35;
+    static final int R_SetExternalPtrProt = 36;
+    static final int R_SetExternalPtrTag = 37;
+    static final int R_ToplevelExec = 38;
+    static final int R_computeIdentical = 39;
+    static final int R_do_MAKE_CLASS = 40;
+    static final int R_getContextCall = 41;
+    static final int R_getContextEnv = 42;
+    static final int R_getContextFun = 43;
+    static final int R_getContextSrcRef = 44;
+    static final int R_getGlobalFunctionContext = 45;
+    static final int R_getParentFunctionContext = 46;
+    static final int R_insideBrowser = 47;
+    static final int R_isEqual = 48;
+    static final int R_isGlobal = 49;
+    static final int R_lsInternal3 = 50;
+    static final int R_tryEval = 51;
+    static final int Rf_GetOption1 = 52;
+    static final int Rf_PairToVectorList = 53;
+    static final int Rf_ScalarDouble = 54;
+    static final int Rf_ScalarInteger = 55;
+    static final int Rf_ScalarLogical = 56;
+    static final int Rf_ScalarString = 57;
+    static final int Rf_allocateArray = 58;
+    static final int Rf_allocateMatrix = 59;
+    static final int Rf_allocateVector = 60;
+    static final int Rf_anyDuplicated = 61;
+    static final int Rf_asChar = 62;
+    static final int Rf_asInteger = 63;
+    static final int Rf_asLogical = 64;
+    static final int Rf_asReal = 65;
+    static final int Rf_classgets = 66;
+    static final int Rf_cons = 67;
+    static final int Rf_copyListMatrix = 68;
+    static final int Rf_copyMatrix = 69;
+    static final int Rf_defineVar = 70;
+    static final int Rf_duplicate = 71;
+    static final int Rf_error = 72;
+    static final int Rf_eval = 73;
+    static final int Rf_findVar = 74;
+    static final int Rf_findVarInFrame = 75;
+    static final int Rf_findVarInFrame3 = 76;
+    static final int Rf_findfun = 77;
+    static final int Rf_getAttrib = 78;
+    static final int Rf_gsetVar = 79;
+    static final int Rf_inherits = 80;
+    static final int Rf_install = 81;
+    static final int Rf_isNull = 82;
+    static final int Rf_isString = 83;
+    static final int Rf_lengthgets = 84;
+    static final int Rf_mkCharLenCE = 85;
+    static final int Rf_ncols = 86;
+    static final int Rf_nrows = 87;
+    static final int Rf_setAttrib = 88;
+    static final int Rf_warning = 89;
+    static final int Rf_warningcall = 90;
+    static final int Rprintf = 91;
+    static final int SETCADR = 92;
+    static final int SETCAR = 93;
+    static final int SETCDR = 94;
+    static final int SET_RDEBUG = 95;
+    static final int SET_RSTEP = 96;
+    static final int SET_STRING_ELT = 97;
+    static final int SET_SYMVALUE = 98;
+    static final int SET_TAG = 99;
+    static final int SET_TYPEOF_FASTR = 100;
+    static final int SET_VECTOR_ELT = 101;
+    static final int STRING_ELT = 102;
+    static final int SYMVALUE = 103;
+    static final int TAG = 104;
+    static final int TYPEOF = 105;
+    static final int VECTOR_ELT = 106;
+    static final int isInteractive = 107;
+    static final int isS4Object = 108;
+    static final int unif_rand = 109;
+
+    static void register() {
+        FFIUpCallRootNode.add(Rf_asReal, AsRealNodeGen::create);
+        FFIUpCallRootNode.add(Rf_asLogical, AsLogicalNodeGen::create);
+        FFIUpCallRootNode.add(Rf_asInteger, AsIntegerNodeGen::create);
+        FFIUpCallRootNode.add(Rf_asChar, AsCharNodeGen::create);
+        FFIUpCallRootNode.add(CAR, CARNodeGen::create);
+        FFIUpCallRootNode.add(CDR, CDRNodeGen::create);
+        FFIUpCallRootNode.add(CADR, CADRNodeGen::create);
+        FFIUpCallRootNode.add(CADDR, CADDRNodeGen::create);
+        FFIUpCallRootNode.add(CDDR, CDDRNodeGen::create);
+        FFIUpCallRootNode.add(LENGTH, LENGTHNodeGen::create);
+    }
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFI.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java
similarity index 90%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFI.java
rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java
index 498519f4837e28824ff4fa6d9fc840e2c3636967..cc0883388ba36345a3582985028ca9e54c2b7b41 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFI.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java
@@ -20,7 +20,9 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi;
+package com.oracle.truffle.r.nodes.ffi;
+
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.*;
 
 import java.nio.charset.StandardCharsets;
 import java.util.function.Function;
@@ -31,6 +33,7 @@ import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.nodes.ffi.ParseResult.ParseStatus;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RCleanUp;
@@ -73,15 +76,14 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RUnboundValue;
 import com.oracle.truffle.r.runtime.data.RVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 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.ffi.CharSXPWrapper;
+import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
-import com.oracle.truffle.r.runtime.ffi.ParseResult.ParseStatus;
-import com.oracle.truffle.r.runtime.ffi.jni.TraceUpCallsAdapter;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 import com.oracle.truffle.r.runtime.nodes.DuplicationHelper;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -98,52 +100,15 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
  * is desirable. In some cases it may be possible to "implement" the functions in R (which is a
  * simple way to achieve the above).
  */
-public class JavaUpCallsRFFI implements UpCallsRFFI {
+public class UpCallsRFFIImpl implements UpCallsRFFI {
 
-    private TraceUpCallsAdapter tracer;
+    protected TraceUpCallsAdapter tracer;
 
-    public JavaUpCallsRFFI() {
+    public UpCallsRFFIImpl() {
         if (RFFIUtils.traceEnabled()) {
             tracer = new TraceUpCallsAdapter();
         }
-    }
-
-    private static RuntimeException unimplemented() {
-        return unimplemented("");
-    }
-
-    private static RuntimeException unimplemented(String message) {
-        System.err.println(message);
-        try {
-            throw RInternalError.unimplemented(message);
-        } catch (Error e) {
-            e.printStackTrace();
-            try {
-                Thread.sleep(100000);
-            } catch (InterruptedException e2) {
-                e2.printStackTrace();
-            }
-            throw e;
-        }
-    }
-
-    private static void guarantee(boolean condition) {
-        guarantee(condition, "");
-    }
-
-    private static void guarantee(boolean condition, String message) {
-        if (!condition) {
-            unimplemented(message);
-        }
-    }
-
-    public static <T> T guaranteeInstanceOf(Object x, Class<T> clazz) {
-        if (x == null) {
-            guarantee(false, "unexpected type: null instead of " + clazz.getSimpleName());
-        } else if (!clazz.isInstance(x)) {
-            guarantee(false, "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of " + clazz.getSimpleName());
-        }
-        return clazz.cast(x);
+        UpCallsIndex.register();
     }
 
     // Checkstyle: stop method name check
@@ -161,7 +126,13 @@ public class JavaUpCallsRFFI implements UpCallsRFFI {
         if (tracer != null) {
             tracer.Rf_ScalarLogical(value);
         }
-        return RDataFactory.createLogicalVectorFromScalar(value != 0);
+        byte byteValue;
+        if (value == RRuntime.INT_NA) {
+            byteValue = RRuntime.LOGICAL_NA;
+        } else {
+            byteValue = (byte) (value & 0xFF);
+        }
+        return RDataFactory.createLogicalVectorFromScalar(byteValue);
     }
 
     @Override
@@ -186,19 +157,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI {
         if (tracer != null) {
             tracer.Rf_asInteger(x);
         }
-        // TODO this is quite incomplete and really should be implemented with CastIntegerNode
-        if (x instanceof Integer) {
-            return ((Integer) x).intValue();
-        } else if (x instanceof Double) {
-            return RRuntime.double2int((Double) x);
-        } else if (x instanceof Byte) {
-            return RRuntime.logical2int((Byte) x);
-        } else if (x instanceof RLogicalVector) {
-            return RRuntime.logical2int(((RLogicalVector) x).getDataAt(0));
-        } else {
-            guaranteeInstanceOf(x, RIntVector.class);
-            return ((RIntVector) x).getDataAt(0);
-        }
+        return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asInteger).call(x);
     }
 
     @Override
@@ -206,14 +165,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI {
         if (tracer != null) {
             tracer.Rf_asReal(x);
         }
-        if (x instanceof Double) {
-            return ((Double) x).doubleValue();
-        } else if (x instanceof Byte) {
-            return RRuntime.logical2double((Byte) x);
-        } else {
-            guaranteeInstanceOf(x, RDoubleVector.class);
-            return ((RDoubleVector) x).getDataAt(0);
-        }
+        return (double) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asReal).call(x);
     }
 
     @Override
@@ -221,12 +173,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI {
         if (tracer != null) {
             tracer.Rf_asLogical(x);
         }
-        if (x instanceof Byte) {
-            return ((Byte) x).intValue();
-        } else {
-            guaranteeInstanceOf(x, RLogicalVector.class);
-            return ((RLogicalVector) x).getDataAt(0);
-        }
+        return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asLogical).call(x);
     }
 
     @Override
@@ -234,25 +181,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI {
         if (tracer != null) {
             tracer.Rf_asChar(x);
         }
-        if (x instanceof CharSXPWrapper) {
-            return x;
-        } else if (x instanceof RSymbol) {
-            return CharSXPWrapper.create(((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 CharSXPWrapper.create(((RAbstractStringVector) vector).getDataAt(0));
-                } else {
-                    unimplemented("asChar type " + x.getClass());
-                }
-            }
-        }
-
-        return CharSXPWrapper.create(RRuntime.STRING_NA);
+        return FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asChar).call(x);
     }
 
     @Override
@@ -607,17 +536,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI {
         if (tracer != null) {
             tracer.LENGTH(x);
         }
-        if (x instanceof RAbstractContainer) {
-            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 {
-            throw unimplemented("unexpected value: " + x);
-        }
+        return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.LENGTH).call(x);
     }
 
     @Override
@@ -836,12 +755,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI {
         if (tracer != null) {
             tracer.CAR(e);
         }
-        guarantee(e != null && (RPairList.class.isInstance(e) || RLanguage.class.isInstance(e)), "CAR only works on pair lists and language objects");
-        if (e instanceof RPairList) {
-            return ((RPairList) e).car();
-        } else {
-            return ((RLanguage) e).getDataAtAsObject(0);
-        }
+        return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CAR).call(e);
     }
 
     @Override
@@ -849,14 +763,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI {
         if (tracer != null) {
             tracer.CDR(e);
         }
-        if (e instanceof RLanguage) {
-            RLanguage lang = (RLanguage) e;
-            RPairList l = lang.getPairList();
-            return l.cdr();
-        } else {
-            guaranteeInstanceOf(e, RPairList.class);
-            return ((RPairList) e).cdr();
-        }
+        return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CDR).call(e);
     }
 
     @Override
@@ -864,12 +771,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI {
         if (tracer != null) {
             tracer.CADR(e);
         }
-        guarantee(e != null && (RPairList.class.isInstance(e) || RLanguage.class.isInstance(e)), "CADR only works on pair lists and language objects");
-        if (e instanceof RPairList) {
-            return ((RPairList) e).cadr();
-        } else {
-            return ((RLanguage) e).getDataAtAsObject(1);
-        }
+        return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CADR).call(e);
     }
 
     @Override
@@ -877,12 +779,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI {
         if (tracer != null) {
             tracer.CADDR(e);
         }
-        guarantee(e != null && (RPairList.class.isInstance(e) || RLanguage.class.isInstance(e)), "CADDR only works on pair lists and language objects");
-        if (e instanceof RPairList) {
-            return ((RPairList) e).caddr();
-        } else {
-            return ((RLanguage) e).getDataAtAsObject(2);
-        }
+        return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CADDR).call(e);
     }
 
     @Override
@@ -890,14 +787,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI {
         if (tracer != null) {
             tracer.CDDR(e);
         }
-        if (e instanceof RLanguage) {
-            RLanguage lang = (RLanguage) e;
-            RPairList l = lang.getPairList();
-            return l.cddr();
-        } else {
-            guaranteeInstanceOf(e, RPairList.class);
-            return ((RPairList) e).cddr();
-        }
+        return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CDDR).call(e);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java
index a4e26e084cb26a2b33636465fd06b613b18346ba..26f233a1fad2f1da4d59a33118043d9f4f9b7a91 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java
@@ -22,8 +22,8 @@
  */
 package com.oracle.truffle.r.runtime.ffi.jni;
 
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCall;
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled;
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall;
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.ffi.CRFFI;
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
index d05fc1e0d965cfde992b255c747d9e22de172062..00ba4c6fa9190f4d91e711de8ebdc0a0510f5d8a 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
@@ -22,21 +22,21 @@
  */
 package com.oracle.truffle.r.runtime.ffi.jni;
 
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCall;
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCallReturn;
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled;
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall;
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCallReturn;
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.nodes.ffi.UpCallsRFFIImpl;
+import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
 import com.oracle.truffle.r.runtime.ffi.LibPaths;
 import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
-import com.oracle.truffle.r.runtime.ffi.RFFIUtils;
 import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
 import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFIFactory;
 
 /**
  * The only variety in the signatures for {@code .Call} is the number of arguments. GnuR supports a
@@ -171,7 +171,7 @@ public class JNI_Call implements CallRFFI {
             traceDownCall("initialize");
         }
         try {
-            initialize(UpCallsRFFIFactory.getInstance().getUpcallsRFFI(), RFFIVariables.values());
+            initialize(new UpCallsRFFIImpl(), RFFIVariables.values());
         } finally {
             if (traceEnabled()) {
                 traceDownCallReturn("initialize", null);
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java
index eb9acfc8566c51815bdb537e07d5a842ddb8bad8..25035bfc14be70f11f84b916ffb519ac8281e4eb 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,9 +22,9 @@
  */
 package com.oracle.truffle.r.runtime.ffi.jni;
 
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCall;
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCallReturn;
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled;
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall;
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCallReturn;
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled;
 
 import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index f0a8433fdbc67f01c81da9b60ed8dcf87b58853a..8f3c3a3a6d95b03e1562a73192828cdfa61f1bf0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -777,11 +777,12 @@ public final class RError extends RuntimeException {
         FIRST_ELEMENT_ONLY("only first element of '%s' argument used"),
         MUST_BE_GE_ONE("'%s' must be of length >= 1"),
         MORE_THAN_ONE_MATCH("there is more than one match in '%s'"),
-        TOO_MANY_ARGS("too many arguments"),
         ARG_MUST_BE_CHARACTER("argument '%s' must be character"),
         INCORRECT_NOF_ARGS("Incorrect number of arguments (%d), expecting %d for '%s'"),
         MACRO_CAN_BE_APPLIED_TO("%s can only be applied to a '%s', not a '%s'"),
-        LOSS_OF_ACCURACY_MOD("probable complete loss of accuracy in modulus");
+        LOSS_OF_ACCURACY_MOD("probable complete loss of accuracy in modulus"),
+        LENGTH_MISAPPLIED("LENGTH or similar applied to %s object"),
+        TOO_MANY_ARGS("too many arguments");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CharSXPWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CharSXPWrapper.java
index 161a93b520a4d41b676bf864830e1df530eb7461..914742898c1751e9a2a333c4070f2a90a87c5575 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CharSXPWrapper.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CharSXPWrapper.java
@@ -48,7 +48,7 @@ public final class CharSXPWrapper {
         return "CHARSXP(" + contents + ")";
     }
 
-    public static Object create(String contents) {
+    public static CharSXPWrapper create(String contents) {
         return new CharSXPWrapper(contents);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UpCallsRFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UpCallsRFFIFactory.java
deleted file mode 100644
index ad90095e5d43c62b89736d67dc05c0a60d035c1a..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UpCallsRFFIFactory.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.ffi;
-
-public abstract class UpCallsRFFIFactory {
-    static {
-        final String prop = System.getProperty("fastr.upcalls.factory.class", "com.oracle.truffle.r.runtime.ffi.JavaUpCallsRFFIFactory");
-        try {
-            theInstance = (UpCallsRFFIFactory) Class.forName(prop).newInstance();
-        } catch (Exception ex) {
-            // CheckStyle: stop system..print check
-            System.err.println("Failed to instantiate class: " + prop);
-        }
-    }
-
-    private static UpCallsRFFIFactory theInstance;
-
-    public static UpCallsRFFIFactory getInstance() {
-        return theInstance;
-    }
-
-    public abstract UpCallsRFFI getUpcallsRFFI();
-
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
index 2735f2873b6f49f1e2e17099f5e8513eebd3d60b..4740bd9bc7c7364e73f758441c9621f7c8a45a30 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -157,8 +157,15 @@ public enum SEXPTYPE {
      * Accessed from FFI layer.
      */
     public static int gnuRCodeForObject(Object obj) {
+        return gnuRTypeForObject(obj).code;
+    }
+
+    /**
+     * Accessed from FFI layer.
+     */
+    public static SEXPTYPE gnuRTypeForObject(Object obj) {
         SEXPTYPE type = typeForClass(obj.getClass());
-        return gnuRType(type, obj).code;
+        return gnuRType(type, obj);
     }
 
     /**
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
index 48d34db470d1bc751044c3411b51a433f78c5d02..d482babaaccb3273a41e04bbd89879c250c25ad2 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
@@ -125,4 +125,31 @@ rffi.null.C <- function() {
 	.Call(C_null)
 }
 
+rffi.asReal <- function(x) {
+	.Call("test_asReal", x)
+}
+
+rffi.asInteger <- function(x) {
+	.Call("test_asInteger", x)
+}
+
+rffi.asLogical <- function(x) {
+	.Call("test_asLogical", x)
+}
+
+rffi.asChar <- function(x) {
+	.Call("test_asChar", x)
+}
+
+rffi.CAR <- function(x) {
+	.Call("test_CAR", x)
+}
+
+rffi.CDR <- function(x) {
+	.Call("test_CDR", x)
+}
+
+rffi.LENGTH <- function(x) {
+	.Call("test_LENGTH", x)
+}
 
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
index 5af8e6bb9f7b8298be0b5a6ee5a99fafd51ffe25..8ac5196404c7c117a757160d193864554b728259 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,6 +58,13 @@ static const R_CallMethodDef CallEntries[] = {
 	    CALLDEF(preserve_object, 0),
 	    CALLDEF(release_object, 1),
 	    CALLDEF(findvar, 2),
+	    CALLDEF(test_asReal, 1),
+	    CALLDEF(test_asChar, 1),
+	    CALLDEF(test_asInteger, 1),
+	    CALLDEF(test_asLogical, 1),
+		CALLDEF(test_CAR, 1),
+		CALLDEF(test_CDR, 1),
+		CALLDEF(test_LENGTH, 1),
 	    {NULL, NULL, 0}
 };
 
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
index b8f04f014f1932f69092eaeda8e7e26737c065e7..e15a466e947a7acb2f3ce0dfd7515e354afee256 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -290,3 +290,30 @@ SEXP findvar(SEXP x, SEXP env) {
 	}
 }
 
+SEXP test_asReal(SEXP x) {
+	return Rf_ScalarReal(Rf_asReal(x));
+}
+
+SEXP test_asInteger(SEXP x) {
+	return Rf_ScalarInteger(Rf_asInteger(x));
+}
+
+SEXP test_asLogical(SEXP x) {
+	return Rf_ScalarLogical(Rf_asLogical(x));
+}
+
+SEXP test_asChar(SEXP x) {
+	return Rf_ScalarString(Rf_asChar(x));
+}
+
+SEXP test_CAR(SEXP x) {
+	return CAR(x);
+}
+
+SEXP test_CDR(SEXP x) {
+	return CDR(x);
+}
+
+SEXP test_LENGTH(SEXP x) {
+	return ScalarInteger(LENGTH(x));
+}
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
index 44de64f3dacf7f6b4dcda78ca61fe0ab4b58eff2..040107cedf1d35e934248ce635cd3f95d11e355c 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -71,3 +71,18 @@ extern SEXP preserve_object(void);
 extern SEXP release_object(SEXP x);
 
 extern SEXP findvar(SEXP x, SEXP env);
+
+extern SEXP test_asReal(SEXP x);
+
+extern SEXP test_asChar(SEXP x);
+
+extern SEXP test_asInteger(SEXP x);
+
+extern SEXP test_asLogical(SEXP x);
+
+extern SEXP test_CAR(SEXP x);
+
+extern SEXP test_CDR(SEXP x);
+
+extern SEXP test_LENGTH(SEXP x);
+
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 ce4e31970c1c8b676edc3d5efb2b65ba18b0450b..0732ffe87e3190c9065c358ff959feccb57d8d9c 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
@@ -136983,6 +136983,195 @@ non-integer value 12345678909876543212L qualified with L; using numeric value
 #'\ ' == ' '
 [1] TRUE
 
+##com.oracle.truffle.r.test.rffi.TestRFFIPackage.TestLENGTH#Output.MayIgnoreErrorContext#
+#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.LENGTH(1)); x <- append(x, rffi.LENGTH(c(1,2,3))); x <- append(x, rffi.LENGTH(list(1,2,3))); x <- append(x, rffi.LENGTH(expression(1,2))); ; detach("package:testrffi", unload=T); x }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 3
+
+[[3]]
+[1] 3
+
+[[4]]
+[1] 2
+
+
+##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testAsFunctions#Output.MayIgnoreWarningContext#
+#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.asChar(1L)); x <- append(x, rffi.asInteger(1L)); x <- append(x, rffi.asReal(1L)); x <- append(x, rffi.asLogical(1L)); x <- append(x, rffi.asChar(2)); x <- append(x, rffi.asInteger(2)); x <- append(x, rffi.asReal(2)); x <- append(x, rffi.asLogical(2)); x <- append(x, rffi.asChar(2.2)); x <- append(x, rffi.asInteger(2.2)); x <- append(x, rffi.asReal(2.2)); x <- append(x, rffi.asLogical(2.2)); x <- append(x, rffi.asChar(T)); x <- append(x, rffi.asInteger(T)); x <- append(x, rffi.asReal(T)); x <- append(x, rffi.asLogical(T)); x <- append(x, rffi.asChar(integer())); x <- append(x, rffi.asInteger(integer())); x <- append(x, rffi.asReal(integer())); x <- append(x, rffi.asLogical(integer())); x <- append(x, rffi.asChar(numeric())); x <- append(x, rffi.asInteger(numeric())); x <- append(x, rffi.asReal(numeric())); x <- append(x, rffi.asLogical(numeric())); x <- append(x, rffi.asChar(logical())); x <- append(x, rffi.asInteger(logical())); x <- append(x, rffi.asReal(logical())); x <- append(x, rffi.asLogical(logical())); x <- append(x, rffi.asChar(character())); x <- append(x, rffi.asInteger(character())); x <- append(x, rffi.asReal(character())); x <- append(x, rffi.asLogical(character())); x <- append(x, rffi.asChar(c(5,6))); x <- append(x, rffi.asInteger(c(5,6))); x <- append(x, rffi.asReal(c(5,6))); x <- append(x, rffi.asLogical(c(5,6))); x <- append(x, rffi.asChar(c(2.3, 3.4))); x <- append(x, rffi.asInteger(c(2.3, 3.4))); x <- append(x, rffi.asReal(c(2.3, 3.4))); x <- append(x, rffi.asLogical(c(2.3, 3.4))); x <- append(x, rffi.asChar(c(T, F))); x <- append(x, rffi.asInteger(c(T, F))); x <- append(x, rffi.asReal(c(T, F))); x <- append(x, rffi.asLogical(c(T, F))); x <- append(x, rffi.asChar(as.symbol("sym"))); x <- append(x, rffi.asInteger(as.symbol("sym"))); x <- append(x, rffi.asReal(as.symbol("sym"))); x <- append(x, rffi.asLogical(as.symbol("sym"))); x <- append(x, rffi.asChar(list())); x <- append(x, rffi.asInteger(list())); x <- append(x, rffi.asReal(list())); x <- append(x, rffi.asLogical(list())); ; detach("package:testrffi", unload=T); x }
+[[1]]
+[1] "1"
+
+[[2]]
+[1] 1
+
+[[3]]
+[1] 1
+
+[[4]]
+[1] TRUE
+
+[[5]]
+[1] "2"
+
+[[6]]
+[1] 2
+
+[[7]]
+[1] 2
+
+[[8]]
+[1] TRUE
+
+[[9]]
+[1] "2.2"
+
+[[10]]
+[1] 2
+
+[[11]]
+[1] 2.2
+
+[[12]]
+[1] TRUE
+
+[[13]]
+[1] "TRUE"
+
+[[14]]
+[1] 1
+
+[[15]]
+[1] 1
+
+[[16]]
+[1] TRUE
+
+[[17]]
+[1] NA
+
+[[18]]
+[1] NA
+
+[[19]]
+[1] NA
+
+[[20]]
+[1] NA
+
+[[21]]
+[1] NA
+
+[[22]]
+[1] NA
+
+[[23]]
+[1] NA
+
+[[24]]
+[1] NA
+
+[[25]]
+[1] NA
+
+[[26]]
+[1] NA
+
+[[27]]
+[1] NA
+
+[[28]]
+[1] NA
+
+[[29]]
+[1] NA
+
+[[30]]
+[1] NA
+
+[[31]]
+[1] NA
+
+[[32]]
+[1] NA
+
+[[33]]
+[1] "5"
+
+[[34]]
+[1] 5
+
+[[35]]
+[1] 5
+
+[[36]]
+[1] TRUE
+
+[[37]]
+[1] "2.3"
+
+[[38]]
+[1] 2
+
+[[39]]
+[1] 2.3
+
+[[40]]
+[1] TRUE
+
+[[41]]
+[1] "TRUE"
+
+[[42]]
+[1] 1
+
+[[43]]
+[1] 1
+
+[[44]]
+[1] TRUE
+
+[[45]]
+[1] "sym"
+
+[[46]]
+[1] NA
+
+[[47]]
+[1] NA
+
+[[48]]
+[1] NA
+
+[[49]]
+[1] NA
+
+[[50]]
+[1] NA
+
+[[51]]
+[1] NA
+
+[[52]]
+[1] NA
+
+
+##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testListFunctions#Output.MayIgnoreErrorContext#
+#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.CAR(pairlist(1,2))); x <- append(x, rffi.CDR(pairlist(1,2))); x <- append(x, rffi.CAR(pairlist(x=1L, y=2L))); x <- append(x, rffi.CDR(pairlist(x=1L, y=2L))); ; detach("package:testrffi", unload=T); x }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 1
+
+$y
+[1] 2
+
+
 ##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI1#
 #{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.addInt(2L, 3L); detach("package:testrffi", unload=T); x }
 [1] 5
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java
index 400a9c7b8f90f0a833c0fa568b46212095152d8c..372f4a1f906ef6f4df0f67c57524e0142e8729ca 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
+import com.oracle.truffle.r.test.TestTrait;
 import com.oracle.truffle.r.test.rpackages.TestRPackages;
 
 public class TestRFFIPackage extends TestRPackages {
@@ -48,12 +49,22 @@ public class TestRFFIPackage extends TestRPackages {
      * micro-tests in one big test. It might be that this should be switched to an R file-based
      * approach as the number of tests increase.
      */
-    private void assertEvalWithLibWithSetup(String setup, String test) {
-        assertEval(TestBase.template("{ library(\"testrffi\", lib.loc = \"%0\"); " + setup + "x <- " + test + "; detach(\"package:testrffi\", unload=T); x }", new String[]{TestRPackages.libLoc()}));
+    private void assertEvalWithLibWithSetupAndTrait(TestTrait trait, String setup, String test) {
+        String[] tests = TestBase.template("{ library(\"testrffi\", lib.loc = \"%0\"); " + setup + "x <- " + test + "; detach(\"package:testrffi\", unload=T); x }",
+                        new String[]{TestRPackages.libLoc()});
+        if (trait == null) {
+            assertEval(tests);
+        } else {
+            assertEval(trait, tests);
+        }
     }
 
     private void assertEvalWithLib(String test) {
-        assertEvalWithLibWithSetup("", test);
+        assertEvalWithLibWithSetupAndTrait(null, "", test);
+    }
+
+    private void assertEvalWithLibWithSetup(String setup, String test) {
+        assertEvalWithLibWithSetupAndTrait(null, setup, test);
     }
 
     @Test
@@ -165,4 +176,44 @@ public class TestRFFIPackage extends TestRPackages {
     public void testRFFI20() {
         assertEvalWithLibWithSetup("x <- \"12345\"; ", "rffi.char_length(x)");
     }
+
+    private static final String[] AS_VALUES = new String[]{"1L", "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", "c(T, F)",
+                    "as.symbol(\"sym\")", "list()"};
+
+    private static final String[] AS_FUNS = new String[]{"Char", "Integer", "Real", "Logical"};
+
+    @Test
+    public void testAsFunctions() {
+        String[] asCalls = template("x <- append(x, rffi.as%0(%1)); ", AS_FUNS, AS_VALUES);
+        assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreWarningContext, "x <- list(); ", flatten(asCalls));
+    }
+
+    private static final String[] LIST_FUNS = new String[]{"CAR", "CDR"};
+
+    private static final String[] LIST_VALUES = new String[]{"pairlist(1,2)", "pairlist(x=1L, y=2L)"};
+
+    @Test
+    public void testListFunctions() {
+        String[] calls = template("x <- append(x, rffi.%0(%1)); ", LIST_FUNS, LIST_VALUES);
+        assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreErrorContext, "x <- list(); ", flatten(calls));
+
+    }
+
+    private static String flatten(String[] tests) {
+        StringBuilder sb = new StringBuilder();
+        for (String test : tests) {
+            sb.append(test);
+        }
+        return sb.toString();
+    }
+
+    private static final String[] LENGTH_VALUES = new String[]{"1", "c(1,2,3)", "list(1,2,3)", "expression(1,2)"};
+
+    // Checkstyle: stop method name check
+    @Test
+    public void TestLENGTH() {
+        String[] calls = template("x <- append(x, rffi.LENGTH(%0)); ", LENGTH_VALUES);
+        assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreErrorContext, "x <- list(); ", flatten(calls));
+    }
+
 }
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 347e963809bda3f4b3530ec00eb103088bb3ae12..a556b1a51e80115339ef0f4014b5dcf0035ab2f7 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -230,7 +230,7 @@ suite = {
     "com.oracle.truffle.r.runtime.ffi" : {
       "sourceDirs" : ["src"],
       "dependencies" : [
-        "com.oracle.truffle.r.runtime",
+        "com.oracle.truffle.r.nodes",
       ],
       "checkstyle" : "com.oracle.truffle.r.runtime",
       "javaCompliance" : "1.8",
@@ -253,7 +253,6 @@ suite = {
     "com.oracle.truffle.r.library" : {
       "sourceDirs" : ["src"],
       "dependencies" : [
-        "com.oracle.truffle.r.nodes",
         "com.oracle.truffle.r.runtime.ffi",
       ],
       "annotationProcessors" : [