diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
index 5b1928a954265a3a102a64432cc8678f717d0e9a..ad560f471c1f8e794e525b770770c2932c34fbe6 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
@@ -16,10 +16,10 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
@@ -34,8 +34,7 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.nodes.ReadAccessor;
-import com.oracle.truffle.r.runtime.data.nodes.VectorReadAccess;
+import com.oracle.truffle.r.runtime.data.nodes.GetReadonlyData;
 import com.oracle.truffle.r.runtime.nmath.RMath;
 
 /*
@@ -73,20 +72,20 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
     /**
      * Compute Cov(xx[], yy[]) or Cor(.,.) with n = length(xx)
      */
-    private static void COV_PAIRWISE_BODY(double[] ans, int n, int ncx, int i, int j, ReadAccessor.Double x, ReadAccessor.Double y, int xx, int yy, boolean[] sd_0, boolean cor, boolean kendall) {
+    private static void COV_PAIRWISE_BODY(double[] ans, int n, int ncx, int i, int j, double[] x, double[] y, int xx, int yy, boolean[] sd_0, boolean cor, boolean kendall) {
         double xmean = 0, ymean = 0;
         int nobs = 0;
         if (!kendall) {
             for (int k = 0; k < n; k++) {
-                if (!(ISNAN(x.getDataAt(xx + k)) || ISNAN(y.getDataAt(yy + k)))) {
+                if (!(ISNAN(x[xx + k]) || ISNAN(y[yy + k]))) {
                     nobs++;
-                    xmean += x.getDataAt(xx + k);
-                    ymean += y.getDataAt(yy + k);
+                    xmean += x[xx + k];
+                    ymean += y[yy + k];
                 }
             }
         } else /* kendall */
             for (int k = 0; k < n; k++) {
-                if (!(ISNAN(x.getDataAt(xx + k)) || ISNAN(y.getDataAt(yy + k)))) {
+                if (!(ISNAN(x[xx + k]) || ISNAN(y[yy + k]))) {
                     nobs++;
                 }
             }
@@ -100,10 +99,10 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                 n1 = nobs - 1;
             }
             for (int k = 0; k < n; k++) {
-                if (!(ISNAN(x.getDataAt(xx + k)) || ISNAN(y.getDataAt(yy + k)))) {
+                if (!(ISNAN(x[xx + k]) || ISNAN(y[yy + k]))) {
                     if (!kendall) {
-                        double xm = x.getDataAt(xx + k) - xmean;
-                        double ym = y.getDataAt(yy + k) - ymean;
+                        double xm = x[xx + k] - xmean;
+                        double ym = y[yy + k] - ymean;
 
                         sum += xm * ym;
                         if (cor) {
@@ -114,9 +113,9 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
 
                     else { /* Kendall's tau */
                         for (n1 = 0; n1 < k; n1++) {
-                            if (!(ISNAN(x.getDataAt(xx + n1)) || ISNAN(y.getDataAt(yy + n1)))) {
-                                double xm = RMath.sign(x.getDataAt(xx + k) - x.getDataAt(xx + n1));
-                                double ym = RMath.sign(y.getDataAt(yy + k) - y.getDataAt(yy + n1));
+                            if (!(ISNAN(x[xx + n1]) || ISNAN(y[yy + n1]))) {
+                                double xm = RMath.sign(x[xx + k] - x[xx + n1]);
+                                double ym = RMath.sign(y[yy + k] - y[yy + n1]);
 
                                 sum += xm * ym;
                                 if (cor) {
@@ -151,7 +150,8 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    private static void cov_pairwise1(int n, int ncx, ReadAccessor.Double x, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) {
+    @TruffleBoundary
+    private static void cov_pairwise1(int n, int ncx, double[] x, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) {
         for (int i = 0; i < ncx; i++) {
             int xx = i * n;
             for (int j = 0; j <= i; j++) {
@@ -164,7 +164,8 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    private static void cov_pairwise2(int n, int ncx, int ncy, ReadAccessor.Double x, ReadAccessor.Double y, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) {
+    @TruffleBoundary
+    private static void cov_pairwise2(int n, int ncx, int ncy, double[] x, double[] y, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) {
         for (int i = 0; i < ncx; i++) {
             int xx = i * n;
             for (int j = 0; j < ncy; j++) {
@@ -180,14 +181,14 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
      */
 
     /* This uses two passes for better accuracy */
-    private static void MEAN(int n, int ncx, ReadAccessor.Double x, double[] xm, boolean[] ind, int nobs) {
+    private static void MEAN(int n, int ncx, double[] x, double[] xm, boolean[] ind, int nobs) {
         /* variable means */
         for (int i = 0; i < ncx; i++) {
             int xx = i * n;
             double sum = 0;
             for (int k = 0; k < n; k++) {
                 if (ind[k]) {
-                    sum += x.getDataAt(xx + k);
+                    sum += x[xx + k];
                 }
             }
             double tmp = sum / nobs;
@@ -195,7 +196,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                 sum = 0;
                 for (int k = 0; k < n; k++) {
                     if (ind[k]) {
-                        sum += (x.getDataAt(xx + k) - tmp);
+                        sum += (x[xx + k] - tmp);
                     }
                 }
                 tmp = tmp + sum / nobs;
@@ -205,7 +206,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
     }
 
     /* This uses two passes for better accuracy */
-    private static void MEAN_(int n, int ncx, ReadAccessor.Double x, double[] xm, boolean[] has_na) {
+    private static void MEAN_(int n, int ncx, double[] x, double[] xm, boolean[] has_na) {
         /* variable means (has_na) */
         for (int i = 0; i < ncx; i++) {
             double tmp;
@@ -215,13 +216,13 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                 int xx = i * n;
                 double sum = 0;
                 for (int k = 0; k < n; k++) {
-                    sum += x.getDataAt(xx + k);
+                    sum += x[xx + k];
                 }
                 tmp = sum / n;
                 if (Double.isFinite(tmp)) {
                     sum = 0;
                     for (int k = 0; k < n; k++) {
-                        sum += (x.getDataAt(xx + k) - tmp);
+                        sum += (x[xx + k] - tmp);
                     }
                     tmp = tmp + sum / n;
                 }
@@ -230,7 +231,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    private static void cov_complete1(int n, int ncx, ReadAccessor.Double x, double[] xm, boolean[] ind, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) {
+    private static void cov_complete1(int n, int ncx, double[] x, double[] xm, boolean[] ind, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) {
         int n1 = -1;
 
         /* total number of complete observations */
@@ -264,7 +265,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                     double sum = 0;
                     for (int k = 0; k < n; k++) {
                         if (ind[k]) {
-                            sum += (x.getDataAt(xx + k) - xxm) * (x.getDataAt(yy + k) - yym);
+                            sum += (x[xx + k] - xxm) * (x[yy + k] - yym);
                         }
                     }
                     double result = sum / n1;
@@ -279,7 +280,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                         if (ind[k]) {
                             for (n1 = 0; n1 < n; n1++) {
                                 if (ind[n1]) {
-                                    sum += RMath.sign(x.getDataAt(xx + k) - x.getDataAt(xx + n1)) * RMath.sign(x.getDataAt(yy + k) - x.getDataAt(yy + n1));
+                                    sum += RMath.sign(x[xx + k] - x[xx + n1]) * RMath.sign(x[yy + k] - x[yy + n1]);
                                 }
                             }
                         }
@@ -316,7 +317,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    private static void cov_na_1(int n, int ncx, ReadAccessor.Double x, double[] xm, boolean[] has_na, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) {
+    private static void cov_na_1(int n, int ncx, double[] x, double[] xm, boolean[] has_na, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) {
         int n1 = -1;
         if (n <= 1) { /* too many missing */
             for (int i = 0; i < ncx; i++) {
@@ -351,7 +352,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                             double yym = xm[j];
                             double sum = 0;
                             for (int k = 0; k < n; k++) {
-                                sum += (x.getDataAt(xx + k) - xxm) * (x.getDataAt(yy + k) - yym);
+                                sum += (x[xx + k] - xxm) * (x[yy + k] - yym);
                             }
                             double result = sum / n1;
                             ANS(ans, ncx, j, i, result);
@@ -368,7 +369,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                             double sum = 0;
                             for (int k = 0; k < n; k++) {
                                 for (n1 = 0; n1 < n; n1++) {
-                                    sum += RMath.sign(x.getDataAt(xx + k) - x.getDataAt(xx + n1)) * RMath.sign(x.getDataAt(yy + k) - x.getDataAt(yy + n1));
+                                    sum += RMath.sign(x[xx + k] - x[xx + n1]) * RMath.sign(x[yy + k] - x[yy + n1]);
                                 }
                             }
                             ANS(ans, ncx, j, i, sum);
@@ -409,7 +410,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    private static void COV_SDEV1(int n, int n1, int nc, ReadAccessor.Double array, double[] m, boolean[] ind, boolean kendall) {
+    private static void COV_SDEV1(int n, int n1, int nc, double[] array, double[] m, boolean[] ind, boolean kendall) {
         for (int i = 0; i < nc; i++) { /* Var(X[i]) */
             int xx = i * n;
             double sum = 0;
@@ -417,7 +418,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                 double xxm = m[i];
                 for (int k = 0; k < n; k++) {
                     if (ind[k]) {
-                        sum += (array.getDataAt(xx + k) - xxm) * (array.getDataAt(xx + k) - xxm);
+                        sum += (array[xx + k] - xxm) * (array[xx + k] - xxm);
                     }
                 }
                 sum /= n1;
@@ -425,7 +426,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                 for (int k = 0; k < n; k++) {
                     if (ind[k]) {
                         for (int n1_ = 0; n1_ < n; n1_++) {
-                            if (ind[n1_] && array.getDataAt(xx + k) != array.getDataAt(xx + n1_)) {
+                            if (ind[n1_] && array[xx + k] != array[xx + n1_]) {
                                 sum++; /* = sign(. - .)^2 */
                             }
                         }
@@ -436,8 +437,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    private static void cov_complete2(int n, int ncx, int ncy, ReadAccessor.Double x, ReadAccessor.Double y, double[] xm, double[] ym, boolean[] ind, double[] ans, boolean[] sd_0, boolean cor,
-                    boolean kendall) {
+    private static void cov_complete2(int n, int ncx, int ncy, double[] x, double[] y, double[] xm, double[] ym, boolean[] ind, double[] ans, boolean[] sd_0, boolean cor, boolean kendall) {
         int n1 = -1;
 
         /* total number of complete observations */
@@ -471,7 +471,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                     double sum = 0;
                     for (int k = 0; k < n; k++) {
                         if (ind[k]) {
-                            sum += (x.getDataAt(xx + k) - xxm) * (y.getDataAt(yy + k) - yym);
+                            sum += (x[xx + k] - xxm) * (y[yy + k] - yym);
                         }
                     }
                     ANS(ans, ncx, i, j, sum / n1);
@@ -484,7 +484,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                         if (ind[k]) {
                             for (n1 = 0; n1 < n; n1++) {
                                 if (ind[n1]) {
-                                    sum += RMath.sign(x.getDataAt(xx + k) - x.getDataAt(xx + n1)) * RMath.sign(y.getDataAt(yy + k) - y.getDataAt(yy + n1));
+                                    sum += RMath.sign(x[xx + k] - x[xx + n1]) * RMath.sign(y[yy + k] - y[yy + n1]);
                                 }
                             }
                         }
@@ -519,7 +519,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    private static void COV_SDEV2(int n, int n1, int nc, ReadAccessor.Double array, double[] m, boolean[] has_na, boolean kendall) {
+    private static void COV_SDEV2(int n, int n1, int nc, double[] array, double[] m, boolean[] has_na, boolean kendall) {
         for (int i = 0; i < nc; i++) {
             if (!has_na[i]) { /* Var(X[j]) */
                 int xx = i * n;
@@ -527,13 +527,13 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                 if (!kendall) {
                     double xxm = m[i];
                     for (int k = 0; k < n; k++) {
-                        sum += (array.getDataAt(xx + k) - xxm) * (array.getDataAt(xx + k) - xxm);
+                        sum += (array[xx + k] - xxm) * (array[xx + k] - xxm);
                     }
                     sum /= n1;
                 } else { /* Kendall's tau */
                     for (int k = 0; k < n; k++) {
                         for (int n1_ = 0; n1_ < n; n1_++) {
-                            if (array.getDataAt(xx + k) != array.getDataAt(xx + n1_)) {
+                            if (array[xx + k] != array[xx + n1_]) {
                                 sum++; /* = sign(. - .)^2 */
                             }
                         }
@@ -544,8 +544,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    private static void cov_na_2(int n, int ncx, int ncy, ReadAccessor.Double x, ReadAccessor.Double y, double[] xm, double[] ym, boolean[] has_na_x, boolean[] has_na_y, double[] ans, boolean[] sd_0,
-                    boolean cor,
+    private static void cov_na_2(int n, int ncx, int ncy, double[] x, double[] y, double[] xm, double[] ym, boolean[] has_na_x, boolean[] has_na_y, double[] ans, boolean[] sd_0, boolean cor,
                     boolean kendall) {
         int n1 = -1;
         if (n <= 1) {/* too many missing */
@@ -579,7 +578,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                             double yym = ym[j];
                             double sum = 0;
                             for (int k = 0; k < n; k++) {
-                                sum += (x.getDataAt(xx + k) - xxm) * (y.getDataAt(yy + k) - yym);
+                                sum += (x[xx + k] - xxm) * (y[yy + k] - yym);
                             }
                             ANS(ans, ncx, i, j, sum / n1);
                         }
@@ -593,7 +592,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                             double sum = 0;
                             for (int k = 0; k < n; k++) {
                                 for (n1 = 0; n1 < n; n1++) {
-                                    sum += RMath.sign(x.getDataAt(xx + k) - x.getDataAt(xx + n1)) * RMath.sign(y.getDataAt(yy + k) - y.getDataAt(yy + n1));
+                                    sum += RMath.sign(x[xx + k] - x[xx + n1]) * RMath.sign(y[yy + k] - y[yy + n1]);
                                 }
                             }
                             ANS(ans, ncx, i, j, sum);
@@ -641,9 +640,9 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
      * This might look slightly inefficient, but it is designed to optimise paging in virtual memory
      * systems ... (or at least that's my story, and I'm sticking to it.)
      */
-    private static void NA_LOOP(int n, int z, ReadAccessor.Double x, boolean[] ind, boolean na_fail) {
+    private static void NA_LOOP(int n, int z, double[] x, boolean[] ind, boolean na_fail) {
         for (int i = 0; i < n; i++) {
-            if (ISNAN(x.getDataAt(z + i))) {
+            if (ISNAN(x[z + i])) {
                 if (na_fail) {
                     error("missing observations in cov/cor");
                 } else {
@@ -653,7 +652,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    private static void complete1(int n, int ncx, ReadAccessor.Double x, boolean[] ind, boolean na_fail) {
+    private static void complete1(int n, int ncx, double[] x, boolean[] ind, boolean na_fail) {
         for (int i = 0; i < n; i++) {
             ind[i] = true;
         }
@@ -663,7 +662,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    static void complete2(int n, int ncx, int ncy, ReadAccessor.Double x, ReadAccessor.Double y, boolean[] ind, boolean na_fail) {
+    static void complete2(int n, int ncx, int ncy, double[] x, double[] y, boolean[] ind, boolean na_fail) {
         complete1(n, ncx, x, ind, na_fail);
 
         for (int j = 0; j < ncy; j++) {
@@ -672,12 +671,12 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    static void find_na_1(int n, int ncx, ReadAccessor.Double x, boolean[] has_na) {
+    static void find_na_1(int n, int ncx, double[] x, boolean[] has_na) {
         for (int j = 0; j < ncx; j++) {
             int z = j * n;
             has_na[j] = false;
             for (int i = 0; i < n; i++) {
-                if (ISNAN(x.getDataAt(z + i))) {
+                if (ISNAN(x[z + i])) {
                     has_na[j] = true;
                     break;
                 }
@@ -685,7 +684,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    static void find_na_2(int n, int ncx, int ncy, ReadAccessor.Double x, ReadAccessor.Double y, boolean[] has_na_x, boolean[] has_na_y) {
+    static void find_na_2(int n, int ncx, int ncy, double[] x, double[] y, boolean[] has_na_x, boolean[] has_na_y) {
         find_na_1(n, ncx, x, has_na_x);
         find_na_1(n, ncy, y, has_na_y);
     }
@@ -694,36 +693,36 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
      * co[vr](x, y, use = { 1, 2, 3, 4, 5 } "all.obs", "complete.obs", "pairwise.complete",
      * "everything", "na.or.complete" kendall = TRUE/FALSE)
      */
-    public RDoubleVector corcov(ReadAccessor.Double x, ReadAccessor.Double y, int method, boolean kendall) throws RError {
+    public RDoubleVector corcov(RDoubleVector x, RDoubleVector y, int method, boolean kendall) throws RError {
         int n, ncx, ncy;
 
         /* Arg.1: x */
-        if (isFactorX.executeIsFactor(x.getVector())) {
+        if (isFactorX.executeIsFactor(x)) {
             error("'x' is a factor");
             // maybe only warning: "Calling var(x) on a factor x is deprecated and will become an
             // error.\n Use something like 'all(duplicated(x)[-1L])' to test for a constant vector."
         }
         /* length check of x -- only if(empty_err) --> below */
-        int[] xDims = getDimsXNode.getDimensions(x.getVector());
+        int[] xDims = getDimsXNode.getDimensions(x);
         boolean ansmat = matrixProfile.profile(GetDimAttributeNode.isMatrix(xDims));
         if ((ansmat)) {
             n = xDims[0];
             ncx = xDims[1];
         } else {
-            n = x.getVector().getLength();
+            n = x.getLength();
             ncx = 1;
         }
         /* Arg.2: y */
         if (y == null) {/* y = x : var() */
             ncy = ncx;
         } else {
-            if (isFactorY.executeIsFactor(y.getVector())) {
+            if (isFactorY.executeIsFactor(y)) {
                 error("'y' is a factor");
                 // maybe only warning: "Calling var(x) on a factor x is deprecated and will become
                 // an error.\n Use something like 'all(duplicated(x)[-1L])' to test for a constant
                 // vector."
             }
-            int[] yDims = getDimsYNode.getDimensions(y.getVector());
+            int[] yDims = getDimsYNode.getDimensions(y);
             if (GetDimAttributeNode.isMatrix(yDims)) {
                 if (yDims[0] != n) {
                     error("incompatible dimensions");
@@ -731,7 +730,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                 ncy = yDims[1];
                 ansmat = true;
             } else {
-                if (y.getVector().getLength() != n) {
+                if (y.getLength() != n) {
                     error("incompatible dimensions");
                 }
                 ncy = 1;
@@ -749,7 +748,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                 break;
             case 2: /* complete */
                 /* did na.omit in R */
-                if (x.getVector().getLength() == 0) {
+                if (x.getLength() == 0) {
                     error("no complete element pairs");
                 }
                 break;
@@ -766,14 +765,15 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
             default:
                 error("invalid 'use' (computational method)");
         }
-        if (empty_err && x.getVector().getLength() == 0) {
+        if (empty_err && x.getLength() == 0) {
             error("'x' is empty");
         }
 
+        double[] xData = getReadonlyDataNode.execute(x);
         double[] ans = new double[ncx * ncy];
         boolean[] sd_0 = new boolean[1];
 
-        evaluate(y, kendall, isCor, n, ncx, ncy, na_fail, everything, empty_err, pair, x, ans, sd_0);
+        evaluate(y, kendall, isCor, n, ncx, ncy, na_fail, everything, empty_err, pair, xData, ans, sd_0);
 
         if (sd_0[0]) { /* only in cor() */
             warning(RError.Message.SD_ZERO);
@@ -791,7 +791,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         if (ansmat) { /* set dimnames() when applicable */
             RList newDimNames = null;
             if (y == null) {
-                RList dimNames = getDimsNamesXNode.getDimNames(x.getVector());
+                RList dimNames = getDimsNamesXNode.getDimNames(x);
                 if (dimNames != null) {
                     Object names = dimNames.getDataAt(1);
                     if (names != RNull.instance) {
@@ -799,8 +799,8 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
                     }
                 }
             } else {
-                RList dimNamesX = getDimsNamesXNode.getDimNames(x.getVector());
-                RList dimNamesY = getDimsNamesYNode.getDimNames(y.getVector());
+                RList dimNamesX = getDimsNamesXNode.getDimNames(x);
+                RList dimNamesY = getDimsNamesYNode.getDimNames(y);
                 Object namesX = dimNamesX.getLength() >= 2 ? dimNamesX.getDataAt(1) : RNull.instance;
                 Object namesY = dimNamesY.getLength() >= 2 ? dimNamesY.getDataAt(1) : RNull.instance;
                 if (namesX != RNull.instance || namesY != RNull.instance) {
@@ -817,67 +817,98 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    @TruffleBoundary
-    private static void evaluate(ReadAccessor.Double y, boolean kendall, boolean cor, int n, int ncx, int ncy, boolean na_fail, boolean everything, boolean empty_err, boolean pair,
-                    ReadAccessor.Double x, double[] ans, boolean[] sd_0) {
+    private void evaluate(RDoubleVector y, boolean kendall, boolean cor, int n, int ncx, int ncy, boolean na_fail, boolean everything, boolean empty_err, boolean pair, double[] xData,
+                    double[] ans, boolean[] sd_0) {
         if (y == null) {
-            if (everything) { /* NA's are propagated */
-                double[] xm = new double[ncx];
-                boolean[] ind = new boolean[ncx];
-                find_na_1(n, ncx, x, /* --> has_na[] = */ ind);
-                cov_na_1(n, ncx, x, xm, ind, ans, sd_0, cor, kendall);
-            } else if (!pair) { /* all | complete "var" */
-                double[] xm = new double[ncx];
-                boolean[] ind = new boolean[n];
-                complete1(n, ncx, x, ind, na_fail);
-                cov_complete1(n, ncx, x, xm, ind, ans, sd_0, cor, kendall);
-                if (empty_err) {
-                    boolean indany = false;
-                    for (int i = 0; i < n; i++) {
-                        if (ind[i]) {
-                            indany = true;
-                            break;
-                        }
-                    }
-                    if (!indany) {
-                        error("no complete element pairs");
-                    }
+            evaluateXOnly(kendall, cor, n, ncx, na_fail, everything, empty_err, pair, xData, ans, sd_0);
+        } else { /* Co[vr] (x, y) */
+            evaluateWithY(y, kendall, cor, n, ncx, ncy, na_fail, everything, empty_err, pair, xData, ans, sd_0);
+        }
+    }
+
+    private void evaluateWithY(RDoubleVector y, boolean kendall, boolean cor, int n, int ncx, int ncy, boolean na_fail, boolean everything, boolean empty_err, boolean pair, double[] xData,
+                    double[] ans, boolean[] sd_0) {
+        double[] yData = getReadonlyDataNode.execute(y);
+        if (everything) {
+            evaluateWithYEverything(kendall, cor, n, ncx, ncy, xData, ans, sd_0, yData);
+        } else if (!pair) { /* all | complete */
+            evaluateWithYAllOrComplete(kendall, cor, n, ncx, ncy, na_fail, empty_err, xData, ans, sd_0, yData);
+        } else { /* pairwise */
+            cov_pairwise2(n, ncx, ncy, xData, yData, ans, sd_0, cor, kendall);
+        }
+    }
+
+    @TruffleBoundary
+    private static void evaluateWithYAllOrComplete(boolean kendall, boolean cor, int n, int ncx, int ncy, boolean na_fail, boolean empty_err, double[] xData, double[] ans, boolean[] sd_0,
+                    double[] yData) {
+        double[] xm = new double[ncx];
+        double[] ym = new double[ncy];
+        boolean[] ind = new boolean[n];
+        complete2(n, ncx, ncy, xData, yData, ind, na_fail);
+        cov_complete2(n, ncx, ncy, xData, yData, xm, ym, ind, ans, sd_0, cor, kendall);
+        if (empty_err) {
+            boolean indany = false;
+            for (int i = 0; i < n; i++) {
+                if (ind[i]) {
+                    indany = true;
+                    break;
                 }
-            } else { /* pairwise "var" */
-                cov_pairwise1(n, ncx, x, ans, sd_0, cor, kendall);
             }
-        } else { /* Co[vr] (x, y) */
-            if (everything) {
-                double[] xm = new double[ncx];
-                double[] ym = new double[ncy];
-                boolean[] ind = new boolean[ncx];
-                boolean[] has_na_y = new boolean[ncy];
-                find_na_2(n, ncx, ncy, x, y, ind, has_na_y);
-                cov_na_2(n, ncx, ncy, x, y, xm, ym, ind, has_na_y, ans, sd_0, cor, kendall);
-            } else if (!pair) { /* all | complete */
-                double[] xm = new double[ncx];
-                double[] ym = new double[ncy];
-                boolean[] ind = new boolean[n];
-                complete2(n, ncx, ncy, x, y, ind, na_fail);
-                cov_complete2(n, ncx, ncy, x, y, xm, ym, ind, ans, sd_0, cor, kendall);
-                if (empty_err) {
-                    boolean indany = false;
-                    for (int i = 0; i < n; i++) {
-                        if (ind[i]) {
-                            indany = true;
-                            break;
-                        }
-                    }
-                    if (!indany) {
-                        error("no complete element pairs");
-                    }
+            if (!indany) {
+                error("no complete element pairs");
+            }
+        }
+    }
+
+    @TruffleBoundary
+    private static void evaluateWithYEverything(boolean kendall, boolean cor, int n, int ncx, int ncy, double[] xData, double[] ans, boolean[] sd_0, double[] yData) {
+        double[] xm = new double[ncx];
+        double[] ym = new double[ncy];
+        boolean[] ind = new boolean[ncx];
+        boolean[] has_na_y = new boolean[ncy];
+        find_na_2(n, ncx, ncy, xData, yData, ind, has_na_y);
+        cov_na_2(n, ncx, ncy, xData, yData, xm, ym, ind, has_na_y, ans, sd_0, cor, kendall);
+    }
+
+    private static void evaluateXOnly(boolean kendall, boolean cor, int n, int ncx, boolean na_fail, boolean everything, boolean empty_err, boolean pair, double[] xData, double[] ans,
+                    boolean[] sd_0) {
+        if (everything) { /* NA's are propagated */
+            evaluateXOnlyEverything(kendall, cor, n, ncx, xData, ans, sd_0);
+        } else if (!pair) { /* all | complete "var" */
+            evaluateXOnlyAllOrComplete(kendall, cor, n, ncx, na_fail, empty_err, xData, ans, sd_0);
+        } else { /* pairwise "var" */
+            cov_pairwise1(n, ncx, xData, ans, sd_0, cor, kendall);
+        }
+    }
+
+    @TruffleBoundary
+    private static void evaluateXOnlyAllOrComplete(boolean kendall, boolean cor, int n, int ncx, boolean na_fail, boolean empty_err, double[] xData, double[] ans, boolean[] sd_0) {
+        double[] xm = new double[ncx];
+        boolean[] ind = new boolean[n];
+        complete1(n, ncx, xData, ind, na_fail);
+        cov_complete1(n, ncx, xData, xm, ind, ans, sd_0, cor, kendall);
+        if (empty_err) {
+            boolean indany = false;
+            for (int i = 0; i < n; i++) {
+                if (ind[i]) {
+                    indany = true;
+                    break;
                 }
-            } else { /* pairwise */
-                cov_pairwise2(n, ncx, ncy, x, y, ans, sd_0, cor, kendall);
+            }
+            if (!indany) {
+                error("no complete element pairs");
             }
         }
     }
 
+    @TruffleBoundary
+    private static void evaluateXOnlyEverything(boolean kendall, boolean cor, int n, int ncx, double[] xData, double[] ans, boolean[] sd_0) {
+        double[] xm = new double[ncx];
+        boolean[] ind = new boolean[ncx];
+        find_na_1(n, ncx, xData, /* --> has_na[] = */ ind);
+        cov_na_1(n, ncx, xData, xm, ind, ans, sd_0, cor, kendall);
+    }
+
     private final boolean isCor;
 
     public Covcor(boolean isCor) {
@@ -893,21 +924,20 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
     }
 
     @Specialization
-    public Object call(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y, int method, boolean iskendall,
-                    @Cached("create()") VectorReadAccess.Double vecReadAccess) {
-        return corcov(new ReadAccessor.Double(x, vecReadAccess), null, method, iskendall);
+    public Object call(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y, int method, boolean iskendall) {
+        return corcov(x.materialize(), null, methodValueProfile.profile(method), iskendall);
     }
 
     @Specialization
-    public Object call(RAbstractDoubleVector x, RAbstractDoubleVector y, int method, boolean iskendall,
-                    @Cached("create()") VectorReadAccess.Double xReadAccess,
-                    @Cached("create()") VectorReadAccess.Double yReadAccess) {
-        return corcov(new ReadAccessor.Double(x, xReadAccess), new ReadAccessor.Double(y, yReadAccess), method, iskendall);
+    public Object call(RAbstractDoubleVector x, RAbstractDoubleVector y, int method, boolean iskendall) {
+        return corcov(x.materialize(), y.materialize(), methodValueProfile.profile(method), iskendall);
     }
 
     private final BranchProfile naInRes = BranchProfile.create();
     private final ConditionProfile matrixProfile = ConditionProfile.createBinaryProfile();
+    private final ValueProfile methodValueProfile = ValueProfile.createEqualityProfile();
 
+    @Child private GetReadonlyData.Double getReadonlyDataNode = GetReadonlyData.Double.create();
     @Child private GetDimAttributeNode getDimsXNode = GetDimAttributeNode.create();
     @Child private GetDimAttributeNode getDimsYNode = GetDimAttributeNode.create();
     @Child private GetDimNamesAttributeNode getDimsNamesXNode = GetDimNamesAttributeNode.create();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
index 93cd847a3d3b093e9e1a5afe3530ebe9a3290052..f8b8ad866ba0f07df2f543055be4ad89d74ca373 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
@@ -13,11 +13,11 @@
 
 package com.oracle.truffle.r.library.stats;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_UNNAMED_ARGUMENTS;
+import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 
 import java.util.Arrays;
 
@@ -43,6 +43,7 @@ import com.oracle.truffle.r.runtime.data.RDouble;
 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.RAbstractVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorIterator;
 import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction1_Double;
 import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction2_Double;
 import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction3_Double;
@@ -161,6 +162,9 @@ public final class RandFunctionsNodes {
 
     protected abstract static class RandFunctionIntExecutorNode extends RandFunctionExecutorBase {
         @Child private RandFunction3_Double function;
+        @Child private VectorIterator.Double aIterator = VectorIterator.Double.createWrapAround();
+        @Child private VectorIterator.Double bIterator = VectorIterator.Double.createWrapAround();
+        @Child private VectorIterator.Double cIterator = VectorIterator.Double.createWrapAround();
 
         protected RandFunctionIntExecutorNode(RandFunction3_Double function) {
             this.function = function;
@@ -180,13 +184,16 @@ public final class RandFunctionsNodes {
                 return RDataFactory.createIntVector(nansResult, false);
             }
 
+            Object aIt = aIterator.init(a);
+            Object bIt = bIterator.init(b);
+            Object cIt = cIterator.init(c);
             boolean nans = false;
             int[] result = new int[length];
             nodeData.loopConditionProfile.profileCounted(length);
             for (int i = 0; nodeData.loopConditionProfile.inject(i < length); i++) {
-                double aValue = a.getDataAt(i % aLength);
-                double bValue = b.getDataAt(i % bLength);
-                double cValue = c.getDataAt(i % cLength);
+                double aValue = aIterator.next(a, aIt);
+                double bValue = bIterator.next(b, bIt);
+                double cValue = cIterator.next(c, cIt);
                 double value = function.execute(aValue, bValue, cValue, randProvider);
                 if (Double.isNaN(value) || value <= Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
                     nodeData.nan.enter();
@@ -206,6 +213,9 @@ public final class RandFunctionsNodes {
 
     protected abstract static class RandFunctionDoubleExecutorNode extends RandFunctionExecutorBase {
         @Child private RandFunction3_Double function;
+        @Child private VectorIterator.Double aIterator = VectorIterator.Double.createWrapAround();
+        @Child private VectorIterator.Double bIterator = VectorIterator.Double.createWrapAround();
+        @Child private VectorIterator.Double cIterator = VectorIterator.Double.createWrapAround();
 
         protected RandFunctionDoubleExecutorNode(RandFunction3_Double function) {
             this.function = function;
@@ -225,14 +235,17 @@ public final class RandFunctionsNodes {
                 return RDataFactory.createDoubleVector(nansResult, false);
             }
 
+            Object aIt = aIterator.init(a);
+            Object bIt = bIterator.init(b);
+            Object cIt = cIterator.init(c);
             boolean nans = false;
             double[] result;
             result = new double[length];
             nodeData.loopConditionProfile.profileCounted(length);
             for (int i = 0; nodeData.loopConditionProfile.inject(i < length); i++) {
-                double aValue = a.getDataAt(i % aLength);
-                double bValue = b.getDataAt(i % bLength);
-                double cValue = c.getDataAt(i % cLength);
+                double aValue = aIterator.next(a, aIt);
+                double bValue = bIterator.next(b, bIt);
+                double cValue = cIterator.next(c, cIt);
                 double value = function.execute(aValue, bValue, cValue, randProvider);
                 if (Double.isNaN(value) || RRuntime.isNA(value)) {
                     nodeData.nan.enter();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
index c735800f28448de09e66be4fe3eb42c86af9d703..ce8e18ff2ebd92f8acf013df7bf5e8a1b5db84fc 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
@@ -33,6 +33,7 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
+import com.oracle.truffle.r.nodes.control.RLengthNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -43,6 +44,7 @@ import com.oracle.truffle.r.runtime.data.RTypes;
 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.nodes.EnableNACheckNode;
 import com.oracle.truffle.r.runtime.data.nodes.VectorIterator;
 import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
@@ -201,11 +203,13 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
 
     @Specialization
     protected Object doIntVector(RAbstractIntVector operand, boolean naRm, boolean finite,
+                    @Cached("create()") EnableNACheckNode enableNACheckNode,
+                    @Cached("create()") RLengthNode lengthNode,
                     @Cached("create()") VectorIterator.Int iterator) {
-        RBaseNode.reportWork(this, operand.getLength());
+        RBaseNode.reportWork(this, lengthNode.executeInteger(operand));
         boolean profiledNaRm = naRmProfile.profile(naRm || finite);
         int result = semantics.getIntStart();
-        na.enable(operand);
+        enableNACheckNode.execute(na, operand);
         int opCount = 0;
         Object it = iterator.init(operand);
         while (iterator.hasNext(operand, it)) {
@@ -236,14 +240,16 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
 
     @Specialization
     protected double doDoubleVector(RAbstractDoubleVector operand, boolean naRm, boolean finite,
+                    @Cached("create()") EnableNACheckNode enableNACheckNode,
+                    @Cached("create()") RLengthNode lengthNode,
                     @Cached("create()") VectorIterator.Double iterator,
                     @Cached("createBinaryProfile()") ConditionProfile finiteProfile,
                     @Cached("createBinaryProfile()") ConditionProfile isInfiniteProfile) {
-        RBaseNode.reportWork(this, operand.getLength());
+        RBaseNode.reportWork(this, lengthNode.executeInteger(operand));
         boolean profiledNaRm = naRmProfile.profile(naRm || finite);
         boolean profiledFinite = finiteProfile.profile(finite);
         double result = semantics.getDoubleStart();
-        na.enable(operand);
+        enableNACheckNode.execute(na, operand);
         int opCount = 0;
 
         Object it = iterator.init(operand);
@@ -274,11 +280,13 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
 
     @Specialization
     protected Object doLogicalVector(RAbstractLogicalVector operand, boolean naRm, @SuppressWarnings("unused") boolean finite,
+                    @Cached("create()") EnableNACheckNode enableNACheckNode,
+                    @Cached("create()") RLengthNode lengthNode,
                     @Cached("create()") VectorIterator.Logical iterator) {
-        RBaseNode.reportWork(this, operand.getLength());
+        RBaseNode.reportWork(this, lengthNode.executeInteger(operand));
         boolean profiledNaRm = naRmProfile.profile(naRm);
         int result = semantics.getIntStart();
-        na.enable(operand);
+        enableNACheckNode.execute(na, operand);
         int opCount = 0;
 
         Object it = iterator.init(operand);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/EnableNACheckNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/EnableNACheckNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..63fd9a46ad164623671bbc371b8546643d7d846e
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/EnableNACheckNode.java
@@ -0,0 +1,49 @@
+/*
+ * 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.runtime.data.nodes;
+
+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.nodes.Node;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.ops.na.NACheck;
+
+public abstract class EnableNACheckNode extends Node {
+    public abstract void execute(NACheck check, RAbstractVector vector);
+
+    public static EnableNACheckNode create() {
+        return EnableNACheckNodeGen.create();
+    }
+
+    @Specialization(guards = "vector.getClass() == clazz", limit = "10")
+    public void doEnable(NACheck check, RAbstractVector vector,
+                    @Cached("vector.getClass()") Class<? extends RAbstractVector> clazz) {
+        check.enable(clazz.cast(vector));
+    }
+
+    @Fallback
+    public void doEnable(NACheck check, RAbstractVector vector) {
+        check.enable(vector);
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorIterator.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorIterator.java
index 4ba40b65984ec6251ce9df5be8e02effb52d9b29..f2ffc6e80be0be8bb4e4c0e5e6056f15d3f91d51 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorIterator.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorIterator.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data.nodes;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.ValueType;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
@@ -45,15 +46,16 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.data.nodes.GetNextNodeGen.GetNextGenericNodeGen;
 import com.oracle.truffle.r.runtime.data.nodes.VectorIterator.IteratorData;
 
 abstract class VectorIteratorNodeAdapter extends Node {
-    public static boolean hasNoNativeMemoryData(RAbstractVector vector) {
-        return !(vector instanceof RVector<?>) || !((RVector<?>) vector).hasNativeMemoryData();
+    public static boolean hasNoNativeMemoryData(RAbstractVector vector, Class<? extends RAbstractVector> vecClass) {
+        return !(RVector.class.isAssignableFrom(vecClass)) || !((RVector<?>) vecClass.cast(vector)).hasNativeMemoryData();
     }
 
-    public static boolean isRVector(RAbstractVector vector) {
-        return vector instanceof RVector<?>;
+    public static boolean isRVector(Class<? extends RAbstractVector> vecClass) {
+        return RVector.class.isAssignableFrom(vecClass);
     }
 }
 
@@ -65,11 +67,11 @@ abstract class GetIteratorNode extends VectorIteratorNodeAdapter {
         return new IteratorData<>(vector.getNativeMirror(), vector.getLength());
     }
 
-    @Specialization(guards = {"hasNoNativeMemoryData(vector)", "vectorClass == vector.getClass()"})
+    @Specialization(guards = {"vectorClass == vector.getClass()", "hasNoNativeMemoryData(vector, vectorClass)"}, limit = "10")
     protected IteratorData<?> generic(RAbstractVector vector,
                     @Cached("vector.getClass()") Class<? extends RAbstractVector> vectorClass) {
         RAbstractVector profiledVec = vectorClass.cast(vector);
-        return new IteratorData<>(profiledVec.getInternalStore(), vector.getLength());
+        return new IteratorData<>(profiledVec.getInternalStore(), profiledVec.getLength());
     }
 
     @Fallback
@@ -106,7 +108,7 @@ abstract class HasNextNode extends VectorIteratorNodeAdapter {
         return iter.index < ((String[]) iter.store).length;
     }
 
-    @Specialization(guards = {"!isRVector(vector)", "vectorClass == vector.getClass()"})
+    @Specialization(guards = {"vectorClass == vector.getClass()", "!isRVector(vectorClass)"}, limit = "10")
     protected boolean generic(RAbstractVector vector, IteratorData<?> iter,
                     @Cached("vector.getClass()") Class<? extends RAbstractVector> vectorClass) {
         RAbstractVector profiledVec = vectorClass.cast(vector);
@@ -183,40 +185,64 @@ abstract class GetNextNode extends VectorIteratorNodeAdapter {
         throw RInternalError.unimplemented("string vectors backed by native memory");
     }
 
-    @Specialization(guards = "!isRVector(vector)")
-    protected int intVectorGeneric(RAbstractIntVector vector, IteratorData<?> iter,
-                    @Cached("create()") GetDataAt.Int getDataAtNode) {
-        return getDataAtNode.get(vector, iter.store, iter.index);
-    }
+    @Child private GetNextGenericNode getNextGenericNode;
 
-    @Specialization(guards = "!isRVector(vector)")
-    protected double doubleVectorGeneric(RAbstractDoubleVector vector, IteratorData<?> iter,
-                    @Cached("create()") GetDataAt.Double getDataAtNode) {
-        return getDataAtNode.get(vector, iter.store, iter.index);
+    @Fallback
+    protected Object doGeneric(RAbstractVector vector, IteratorData<?> iter) {
+        // we use fallback and extra node so that we do not have to explicitly check that the vector
+        // is not
+        // RVector, DSL generates fallback guard that compares the class with the all RVector
+        // subclasses
+        // used in the specializations above, "vector instanceof RVector" would not be a leaf-check.
+        if (getNextGenericNode == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            getNextGenericNode = insert(GetNextGenericNode.create());
+        }
+        return getNextGenericNode.execute(vector, iter);
     }
 
-    @Specialization(guards = "!isRVector(vector)")
-    protected String stringVectorGeneric(RAbstractStringVector vector, IteratorData<?> iter,
-                    @Cached("create()") GetDataAt.String getDataAtNode) {
-        return getDataAtNode.get(vector, iter.store, iter.index);
-    }
+    abstract static class GetNextGenericNode extends Node {
+        public abstract Object execute(RAbstractVector vector, IteratorData<?> iter);
 
-    @Specialization(guards = "!isRVector(vector)")
-    protected byte rawVectorGeneric(RAbstractRawVector vector, IteratorData<?> iter,
-                    @Cached("create()") GetDataAt.Raw getDataAtNode) {
-        return getDataAtNode.get(vector, iter.store, iter.index);
-    }
+        public static GetNextGenericNode create() {
+            return GetNextGenericNodeGen.create();
+        }
 
-    @Specialization(guards = "!isRVector(vector)")
-    protected byte logicalVectorGeneric(RAbstractLogicalVector vector, IteratorData<?> iter,
-                    @Cached("create()") GetDataAt.Logical getDataAtNode) {
-        return getDataAtNode.get(vector, iter.store, iter.index);
-    }
+        @Specialization
+        protected int intVectorGeneric(RAbstractIntVector vector, IteratorData<?> iter,
+                        @Cached("create()") GetDataAt.Int getDataAtNode) {
+            return getDataAtNode.get(vector, iter.store, iter.index);
+        }
+
+        @Specialization
+        protected double doubleVectorGeneric(RAbstractDoubleVector vector, IteratorData<?> iter,
+                        @Cached("create()") GetDataAt.Double getDataAtNode) {
+            return getDataAtNode.get(vector, iter.store, iter.index);
+        }
 
-    @Specialization(guards = "!isRVector(vector)")
-    protected RComplex complexVectorGeneric(RAbstractComplexVector vector, IteratorData<?> iter,
-                    @Cached("create()") GetDataAt.Complex getDataAtNode) {
-        return getDataAtNode.get(vector, iter.store, iter.index);
+        @Specialization
+        protected String stringVectorGeneric(RAbstractStringVector vector, IteratorData<?> iter,
+                        @Cached("create()") GetDataAt.String getDataAtNode) {
+            return getDataAtNode.get(vector, iter.store, iter.index);
+        }
+
+        @Specialization
+        protected byte rawVectorGeneric(RAbstractRawVector vector, IteratorData<?> iter,
+                        @Cached("create()") GetDataAt.Raw getDataAtNode) {
+            return getDataAtNode.get(vector, iter.store, iter.index);
+        }
+
+        @Specialization
+        protected byte logicalVectorGeneric(RAbstractLogicalVector vector, IteratorData<?> iter,
+                        @Cached("create()") GetDataAt.Logical getDataAtNode) {
+            return getDataAtNode.get(vector, iter.store, iter.index);
+        }
+
+        @Specialization
+        protected RComplex complexVectorGeneric(RAbstractComplexVector vector, IteratorData<?> iter,
+                        @Cached("create()") GetDataAt.Complex getDataAtNode) {
+            return getDataAtNode.get(vector, iter.store, iter.index);
+        }
     }
 }
 
@@ -308,6 +334,10 @@ public abstract class VectorIterator<T> extends Node {
         public static Double create() {
             return new Double(false);
         }
+
+        public static Double createWrapAround() {
+            return new Double(true);
+        }
     }
 
     public static final class Logical extends VectorIterator<Byte> {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/IgnoreOS.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/IgnoreOS.java
index 0be605720b6299850a916cb0fb4261605df83e9d..b478fbf2a9bcd5be775eb6fcccf882037d09ad6e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/IgnoreOS.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/IgnoreOS.java
@@ -44,7 +44,7 @@ public enum IgnoreOS implements TestTrait {
 
     private boolean isIgnoring() {
         String current = System.getProperty("os.name");
-        return current != null && current.contains(osName);
+        return current != null && current.toLowerCase().contains(osName);
     }
 
     @Override