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 037edd13c8c4bf0df1030259484cd7a9733cbbeb..c8ef247f6f7abc76ac41990dbf06f05d035dcc58 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -65,6 +65,7 @@ static jmethodID Rf_gsetVarMethodID;
 static jmethodID Rf_inheritsMethodID;
 static jmethodID Rf_lengthgetsMethodID;
 static jmethodID CADR_MethodID;
+static jmethodID CADDR_MethodID;
 static jmethodID TAG_MethodID;
 static jmethodID PRINTNAME_MethodID;
 static jmethodID CAR_MethodID;
@@ -169,6 +170,7 @@ void init_internals(JNIEnv *env) {
 //	Rf_rPsortMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_rPsort", "(Lcom/oracle/truffle/r/runtime/data/RDoubleVector;II)", 1);
 //	Rf_iPsortMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_iPsort", "(Lcom/oracle/truffle/r/runtime/data/RIntVector;II)", 1);
 	CADR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "CADR", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
+	CADDR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "CADDR", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
 	TAG_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "TAG", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
 	PRINTNAME_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "PRINTNAME", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
 	CAR_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "CAR", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
@@ -862,8 +864,10 @@ SEXP CDDDR(SEXP e) {
 }
 
 SEXP CADDR(SEXP e) {
-    unimplemented("CADDR");
-    return NULL;
+    TRACE(TARGp, e);
+    JNIEnv *thisenv = getEnv();
+    SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, CADDR_MethodID, e);
+    return checkRef(thisenv, result);
 }
 
 SEXP CADDDR(SEXP e) {
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java
index fb1091c71e64335b1695b1dc4e444ae31861f7e2..f1818466bd3b1643929479caff96594ccd93fb1c 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java
@@ -540,37 +540,14 @@ public class CallRFFIHelper {
         if (RFFIUtils.traceEnabled()) {
             RFFIUtils.traceUpCall("Rf_nrows", x);
         }
-        if (x instanceof RAbstractContainer) {
-            RAbstractContainer xa = (RAbstractContainer) x;
-            if (xa.hasDimensions()) {
-                return xa.getDimensions()[0];
-            } else {
-                return xa.getLength();
-            }
-        } else {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.OBJECT_NOT_MATRIX);
-        }
+        return RRuntime.nrows(x);
     }
 
     public static int Rf_ncols(Object x) {
         if (RFFIUtils.traceEnabled()) {
             RFFIUtils.traceUpCall("Rf_ncols", x);
         }
-        if (x instanceof RAbstractContainer) {
-            RAbstractContainer xa = (RAbstractContainer) x;
-            if (xa.hasDimensions()) {
-                int[] dims = xa.getDimensions();
-                if (dims.length >= 2) {
-                    return dims[1];
-                } else {
-                    return 1;
-                }
-            } else {
-                return 1;
-            }
-        } else {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.OBJECT_NOT_MATRIX);
-        }
+        return RRuntime.ncols(x);
     }
 
     public static int LENGTH(Object x) {
@@ -748,6 +725,8 @@ public class CallRFFIHelper {
         guarantee(x instanceof RShareable || x instanceof RExternalPtr, "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of RShareable or RExternalPtr");
         if (x instanceof RShareable) {
             return deep == 1 ? ((RShareable) x).deepCopy() : ((RShareable) x).copy();
+        } else if (x instanceof RIntSequence) {
+            return ((RIntSequence) x).materialize();
         } else {
             return ((RExternalPtr) x).copy();
         }
@@ -824,6 +803,18 @@ public class CallRFFIHelper {
         }
     }
 
+    public static Object CADDR(Object e) {
+        if (RFFIUtils.traceEnabled()) {
+            RFFIUtils.traceUpCall("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);
+        }
+    }
+
     public static Object CDDR(Object e) {
         if (RFFIUtils.traceEnabled()) {
             RFFIUtils.traceUpCall("CDDR", e);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index b80c0d0f5456629723be9f4685d8419b527679e8..77387098a0b56bc12832f8cc0ee524473e2f1175 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 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;
@@ -856,4 +857,36 @@ public class RRuntime {
     public static double normalizeZero(double value) {
         return value == 0.0 ? 0.0 : value;
     }
+
+    public static int nrows(Object x) {
+        if (x instanceof RAbstractContainer) {
+            RAbstractContainer xa = (RAbstractContainer) x;
+            if (xa.hasDimensions()) {
+                return xa.getDimensions()[0];
+            } else {
+                return xa.getLength();
+            }
+        } else {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.OBJECT_NOT_MATRIX);
+        }
+    }
+
+    public static int ncols(Object x) {
+        if (x instanceof RAbstractContainer) {
+            RAbstractContainer xa = (RAbstractContainer) x;
+            if (xa.hasDimensions()) {
+                int[] dims = xa.getDimensions();
+                if (dims.length >= 2) {
+                    return dims[1];
+                } else {
+                    return 1;
+                }
+            } else {
+                return 1;
+            }
+        } else {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.OBJECT_NOT_MATRIX);
+        }
+    }
+
 }