From 08469690cad0edb0630a5ac90d3619fdf1619d2d Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 25 Aug 2017 11:44:13 +0200
Subject: [PATCH] Nodes for operations on vectors in c.o.t.r.runtime.data

---
 .../r/runtime/data/NativeDataAccess.java      |  43 ++-
 .../truffle/r/runtime/data/RIntVector.java    |   1 -
 .../r/runtime/data/RLogicalVector.java        |   1 -
 .../truffle/r/runtime/data/RRawVector.java    |   1 -
 .../truffle/r/runtime/data/RStringVector.java |   1 +
 .../truffle/r/runtime/data/RVector.java       |   8 +-
 .../data/closures/RToVectorClosure.java       |   4 +-
 .../data/model/RAbstractContainer.java        |   9 +-
 .../r/runtime/data/nodes/GetDataAt.java       | 333 +++++++++++++++++
 .../r/runtime/data/nodes/GetDataCopy.java     |  96 +++++
 .../r/runtime/data/nodes/GetDataStore.java    |  68 ++++
 .../r/runtime/data/nodes/GetReadonlyData.java |  77 ++++
 .../r/runtime/data/nodes/ReadAccessor.java    | 184 +++++++++
 .../r/runtime/data/nodes/SetDataAt.java       | 218 +++++++++++
 .../data/nodes/VectorAccessAdapter.java       |  37 ++
 .../r/runtime/data/nodes/VectorIterator.java  | 348 ++++++++++++++++++
 .../runtime/data/nodes/VectorReadAccess.java  | 152 ++++++++
 .../runtime/data/nodes/VectorWriteAccess.java | 118 ++++++
 18 files changed, 1682 insertions(+), 17 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataAt.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataCopy.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataStore.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetReadonlyData.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/ReadAccessor.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/SetDataAt.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorAccessAdapter.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorIterator.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorReadAccess.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorWriteAccess.java

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java
index 9c6878788b..2b31a68422 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java
@@ -104,7 +104,8 @@ public final class NativeDataAccess {
          */
         private long dataAddress;
         /**
-         * Length of the native data array. E.g. for CHARSXP this is not just the length of the Java String.
+         * Length of the native data array. E.g. for CHARSXP this is not just the length of the Java
+         * String.
          */
         private long length;
 
@@ -121,9 +122,11 @@ public final class NativeDataAccess {
 
         void allocateNative(String source) {
             assert dataAddress == 0;
-            byte[] bytes = source.getBytes(StandardCharsets.UTF_8);
+            byte[] bytes = source.getBytes(StandardCharsets.US_ASCII);
             dataAddress = UnsafeAdapter.UNSAFE.allocateMemory(bytes.length + 1);
-            UnsafeAdapter.UNSAFE.copyMemory(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, dataAddress, bytes.length + 1);
+            UnsafeAdapter.UNSAFE.copyMemory(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, dataAddress, bytes.length);
+            UnsafeAdapter.UNSAFE.putByte(dataAddress + bytes.length, (byte) 0); // C strings
+                                                                                // terminator
             this.length = bytes.length + 1;
         }
 
@@ -235,6 +238,14 @@ public final class NativeDataAccess {
         return UnsafeAdapter.UNSAFE.getByte(address + index * Unsafe.ARRAY_BYTE_INDEX_SCALE);
     }
 
+    public static RComplex getComplexNativeMirrorData(Object nativeMirror, int index) {
+        long address = ((NativeMirror) nativeMirror).dataAddress;
+        assert address != 0;
+        assert index < ((NativeMirror) nativeMirror).length;
+        return RComplex.valueOf(UnsafeAdapter.UNSAFE.getDouble(address + index * 2 * Unsafe.ARRAY_DOUBLE_INDEX_SCALE),
+                        UnsafeAdapter.UNSAFE.getDouble(address + (index * 2 + 1) * Unsafe.ARRAY_DOUBLE_INDEX_SCALE));
+    }
+
     public static void setNativeMirrorData(Object nativeMirror, int index, double value) {
         long address = ((NativeMirror) nativeMirror).dataAddress;
         assert address != 0;
@@ -242,6 +253,27 @@ public final class NativeDataAccess {
         UnsafeAdapter.UNSAFE.putDouble(address + index * Unsafe.ARRAY_DOUBLE_INDEX_SCALE, value);
     }
 
+    public static void setNativeMirrorData(Object nativeMirror, int index, byte value) {
+        long address = ((NativeMirror) nativeMirror).dataAddress;
+        assert address != 0;
+        assert index < ((NativeMirror) nativeMirror).length;
+        UnsafeAdapter.UNSAFE.putByte(address + index * Unsafe.ARRAY_BYTE_INDEX_SCALE, value);
+    }
+
+    public static void setNativeMirrorData(Object nativeMirror, int index, int value) {
+        long address = ((NativeMirror) nativeMirror).dataAddress;
+        assert address != 0;
+        assert index < ((NativeMirror) nativeMirror).length;
+        UnsafeAdapter.UNSAFE.putInt(address + index * Unsafe.ARRAY_INT_INDEX_SCALE, value);
+    }
+
+    public static void setNativeMirrorLogicalData(Object nativeMirror, int index, byte logical) {
+        long address = ((NativeMirror) nativeMirror).dataAddress;
+        assert address != 0;
+        assert index < ((NativeMirror) nativeMirror).length;
+        UnsafeAdapter.UNSAFE.putInt(address + index * Unsafe.ARRAY_INT_INDEX_SCALE, RRuntime.logical2int(logical));
+    }
+
     public static double[] copyDoubleNativeData(Object mirrorObj) {
         NativeMirror mirror = (NativeMirror) mirrorObj;
         long address = mirror.dataAddress;
@@ -386,10 +418,7 @@ public final class NativeDataAccess {
         if (noComplexNative.isValid() || data != null) {
             return RComplex.valueOf(data[index * 2], data[index * 2 + 1]);
         } else {
-            long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
-            assert address != 0;
-            return RComplex.valueOf(UnsafeAdapter.UNSAFE.getDouble(address + index * 2 * Unsafe.ARRAY_DOUBLE_INDEX_SCALE),
-                            UnsafeAdapter.UNSAFE.getDouble(address + (index * 2 + 1) * Unsafe.ARRAY_DOUBLE_INDEX_SCALE));
+            return getComplexNativeMirrorData(vector.getNativeMirror(), index);
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
index 93d5547fc5..f52c7cb614 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
@@ -79,7 +79,6 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
 
     @Override
     public int[] getInternalStore() {
-        assert data != null;
         return data;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
index 8d87a76756..1d5bcca090 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
@@ -86,7 +86,6 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
 
     @Override
     public byte[] getInternalStore() {
-        assert data != null;
         return data;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
index 1bd4e1e70c..58025d7eb7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
@@ -84,7 +84,6 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
 
     @Override
     public byte[] getInternalStore() {
-        assert data != null;
         return data;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
index b0e42cf3ac..4a0374063a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
@@ -68,6 +68,7 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
 
     @Override
     public String[] getInternalStore() {
+        assert data != null : "support for native memory backed vectors is not complete";
         return data;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
index 27ad924f7b..f13b35c636 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 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.VectorToArray;
+import com.oracle.truffle.r.runtime.data.nodes.GetReadonlyData;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
@@ -88,7 +88,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
     /**
      * Returns the internal data Java array for read only purposes only or {@code null} if the
      * vector has been materialized to native mirror and it does not hold managed data anymore. This
-     * method is for only very specific purposes especially of {@link VectorToArray}.
+     * method is for only very specific purposes especially of {@link GetReadonlyData}.
      *
      * @return vector data
      */
@@ -106,9 +106,9 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
     /**
      * Returns data for read-only purposes. The result may or may not be copy of the internal data.
      * This is a slow path operation for vector types that may have a native mirror, use
-     * {@link VectorToArray} node for fast path in such cases.
+     * {@link GetReadonlyData} node for fast path in such cases.
      *
-     * @see VectorToArray
+     * @see GetReadonlyData
      * @see RObject#getNativeMirror()
      * @return vector data
      */
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
index 2f0146bee3..e8c5104485 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
@@ -49,8 +49,8 @@ abstract class RToVectorClosure implements RAbstractVector {
     }
 
     @Override
-    public Void getInternalStore() {
-        return null;
+    public EmptyInternalStore getInternalStore() {
+        return EmptyInternalStore.INSTANCE;
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
index 928229bfae..0a2bd4c3d4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
@@ -68,7 +68,7 @@ public interface RAbstractContainer extends RAttributable, RTypedValue {
      * beneficial when in loop.
      */
     default Object getInternalStore() {
-        return null;
+        return EmptyInternalStore.INSTANCE;
     }
 
     default RStringVector getNames() {
@@ -100,4 +100,11 @@ public interface RAbstractContainer extends RAttributable, RTypedValue {
         CompilerAsserts.neverPartOfCompilation();
         setAttr(RRuntime.ROWNAMES_ATTR_KEY, rowNames);
     }
+
+    final class EmptyInternalStore {
+        private EmptyInternalStore() {
+        }
+
+        public static EmptyInternalStore INSTANCE = new EmptyInternalStore();
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataAt.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataAt.java
new file mode 100644
index 0000000000..1c4c4d158b
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataAt.java
@@ -0,0 +1,333 @@
+/*
+ * 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.ImportStatic;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.NativeDataAccess;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
+import com.oracle.truffle.r.runtime.data.RDoubleSequence;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntSequence;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRawVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+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.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.GetDataAtFactory.DoubleNodeGen;
+import com.oracle.truffle.r.runtime.data.nodes.GetDataAtFactory.IntNodeGen;
+
+/**
+ * Contains nodes implementing fast-path versions of e.g.
+ * {@link RAbstractIntVector#getDataAt(Object, int)}. The first parameter 'store' should be
+ * retrieved for given vector using {@link GetDataStore} node. Store object must be used only for
+ * accessing the data of the vector for which it was created. The reason for having a store object
+ * is to avoid field load (field of the RVector object) on every data access.
+ */
+public abstract class GetDataAt extends Node {
+
+    public abstract Object getAsObject(RAbstractVector vector, Object store, int index);
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class Int extends GetDataAt {
+
+        public static Int create() {
+            return IntNodeGen.create();
+        }
+
+        @Override
+        public Object getAsObject(RAbstractVector vector, Object store, int index) {
+            return get((RAbstractIntVector) vector, store, index);
+        }
+
+        public final int get(RAbstractIntVector vector, Object store, int index) {
+            return execute(vector, store, index);
+        }
+
+        public abstract int execute(RAbstractIntVector vector, Object store, int index);
+
+        protected int doRVector(RIntVector vector, int[] store, int index) {
+            return store[index];
+        }
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected int doRVector(RIntVector vector, Object store, int index) {
+            return NativeDataAccess.getIntNativeMirrorData(store, index);
+        }
+
+        @Specialization
+        protected int doSequence(RIntSequence sequence, Object store, int index) {
+            return sequence.getStart() + index * sequence.getStride();
+        }
+
+        // This accounts for other vector types, like closures
+        @Specialization(guards = {"isGenericVector(vector)", "cachedClass == vector.getClass()"})
+        protected int doDoubleClosure(RAbstractIntVector vector, Object store, int index,
+                        @Cached("vector.getClass()") Class<? extends RAbstractIntVector> cachedClass) {
+            return cachedClass.cast(vector).getDataAt(store, index);
+        }
+
+        @Fallback
+        protected int doDoubleClosure(RAbstractIntVector vector, Object store, int index) {
+            return vector.getDataAt(store, index);
+        }
+
+        protected static boolean isGenericVector(RAbstractIntVector vector) {
+            return !(vector instanceof RIntVector) && !(vector instanceof RIntSequence);
+        }
+    }
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class Double extends GetDataAt {
+
+        public static Double create() {
+            return DoubleNodeGen.create();
+        }
+
+        @Override
+        public Object getAsObject(RAbstractVector vector, Object store, int index) {
+            return get((RAbstractDoubleVector) vector, store, index);
+        }
+
+        public final double get(RAbstractDoubleVector vector, Object store, int index) {
+            return execute(vector, store, index);
+        }
+
+        public abstract double execute(RAbstractDoubleVector vector, Object store, int index);
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected double doRVector(RDoubleVector vector, Object store, int index) {
+            return NativeDataAccess.getDoubleNativeMirrorData(store, index);
+        }
+
+        @Specialization
+        protected double doRVector(RDoubleVector vector, double[] store, int index) {
+            return store[index];
+        }
+
+        @Specialization
+        protected double doSequence(RDoubleSequence sequence, Object store, int index) {
+            return sequence.getStart() + index * sequence.getStride();
+        }
+
+        @Specialization(guards = {"isGenericVector(vector)", "cachedClass == vector.getClass()"}, limit = "3")
+        protected double doDoubleClosure(RAbstractDoubleVector vector, Object store, int index,
+                        @Cached("vector.getClass()") Class<?> cachedClass) {
+            return ((RAbstractDoubleVector) cachedClass.cast(vector)).getDataAt(store, index);
+        }
+
+        @Fallback
+        protected double doDoubleClosure(RAbstractDoubleVector vector, Object store, int index) {
+            return vector.getDataAt(store, index);
+        }
+
+        protected static boolean isGenericVector(RAbstractDoubleVector vector) {
+            return !(vector instanceof RDoubleVector) && !(vector instanceof RDoubleSequence);
+        }
+    }
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class Logical extends GetDataAt {
+
+        public static Logical create() {
+            return GetDataAtFactory.LogicalNodeGen.create();
+        }
+
+        @Override
+        public Object getAsObject(RAbstractVector vector, Object store, int index) {
+            return get((RAbstractLogicalVector) vector, store, index);
+        }
+
+        public final byte get(RAbstractLogicalVector vector, Object store, int index) {
+            return execute(vector, store, index);
+        }
+
+        public abstract byte execute(RAbstractLogicalVector vector, Object store, int index);
+
+        protected byte doRVector(RLogicalVector vector, byte[] store, int index) {
+            return store[index];
+        }
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected byte doRVector(RLogicalVector vector, Object store, int index) {
+            return NativeDataAccess.getLogicalNativeMirrorData(store, index);
+        }
+
+        // This accounts for other vector types, like closures
+        @Specialization(guards = {"isGenericVector(vector)", "cachedClass == vector.getClass()"})
+        protected byte doDoubleClosure(RAbstractLogicalVector vector, Object store, int index,
+                        @Cached("vector.getClass()") Class<? extends RAbstractLogicalVector> cachedClass) {
+            return cachedClass.cast(vector).getDataAt(store, index);
+        }
+
+        @Fallback
+        protected byte doDoubleClosure(RAbstractLogicalVector vector, Object store, int index) {
+            return vector.getDataAt(store, index);
+        }
+
+        protected static boolean isGenericVector(RAbstractLogicalVector vector) {
+            return !(vector instanceof RLogicalVector);
+        }
+    }
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class Raw extends GetDataAt {
+
+        public static Raw create() {
+            return GetDataAtFactory.RawNodeGen.create();
+        }
+
+        @Override
+        public Object getAsObject(RAbstractVector vector, Object store, int index) {
+            return get((RAbstractRawVector) vector, store, index);
+        }
+
+        public final byte get(RAbstractRawVector vector, Object store, int index) {
+            return execute(vector, store, index);
+        }
+
+        public abstract byte execute(RAbstractRawVector vector, Object store, int index);
+
+        protected byte doRVector(RRawVector vector, byte[] store, int index) {
+            return store[index];
+        }
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected byte doRVector(RRawVector vector, Object store, int index) {
+            return NativeDataAccess.getRawNativeMirrorData(store, index);
+        }
+
+        // This accounts for other vector types, like closures
+        @Specialization(guards = {"isGenericVector(vector)", "cachedClass == vector.getClass()"})
+        protected byte doDoubleClosure(RAbstractRawVector vector, Object store, int index,
+                        @Cached("vector.getClass()") Class<? extends RAbstractRawVector> cachedClass) {
+            return cachedClass.cast(vector).getRawDataAt(store, index);
+        }
+
+        @Fallback
+        protected byte doDoubleClosure(RAbstractRawVector vector, Object store, int index) {
+            return vector.getRawDataAt(store, index);
+        }
+
+        protected static boolean isGenericVector(RAbstractRawVector vector) {
+            return !(vector instanceof RRawVector);
+        }
+    }
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class Complex extends GetDataAt {
+
+        public static Complex create() {
+            return GetDataAtFactory.ComplexNodeGen.create();
+        }
+
+        @Override
+        public Object getAsObject(RAbstractVector vector, Object store, int index) {
+            return get((RAbstractComplexVector) vector, store, index);
+        }
+
+        public final RComplex get(RAbstractComplexVector vector, Object store, int index) {
+            return execute(vector, store, index);
+        }
+
+        public abstract RComplex execute(RAbstractComplexVector vector, Object store, int index);
+
+        protected RComplex doRVector(RComplexVector vector, double[] store, int index) {
+            return RComplex.valueOf(store[index * 2], store[index * 2 + 1]);
+        }
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected RComplex doRVector(RComplexVector vector, Object store, int index) {
+            throw RInternalError.unimplemented();
+        }
+
+        @Specialization(guards = {"isGenericVector(vector)", "cachedClass == vector.getClass()"})
+        protected RComplex doDoubleClosure(RAbstractComplexVector vector, Object store, int index,
+                        @Cached("vector.getClass()") Class<? extends RAbstractComplexVector> cachedClass) {
+            return cachedClass.cast(vector).getDataAt(store, index);
+        }
+
+        @Fallback
+        protected RComplex doDoubleClosure(RAbstractComplexVector vector, Object store, int index) {
+            return vector.getDataAt(store, index);
+        }
+
+        protected static boolean isGenericVector(RAbstractComplexVector vector) {
+            return !(vector instanceof RComplexVector);
+        }
+    }
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class String extends GetDataAt {
+
+        public static String create() {
+            return GetDataAtFactory.StringNodeGen.create();
+        }
+
+        @Override
+        public Object getAsObject(RAbstractVector vector, Object store, int index) {
+            return get((RAbstractStringVector) vector, store, index);
+        }
+
+        public final java.lang.String get(RAbstractStringVector vector, Object store, int index) {
+            return execute(vector, store, index);
+        }
+
+        public abstract java.lang.String execute(RAbstractStringVector vector, Object store, int index);
+
+        protected java.lang.String doRVector(RStringVector vector, java.lang.String[] store, int index) {
+            return store[index];
+        }
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected java.lang.String doRVector(RStringVector vector, Object store, int index) {
+            throw RInternalError.unimplemented();
+        }
+
+        @Specialization(guards = {"isGenericVector(vector)", "cachedClass == vector.getClass()"})
+        protected java.lang.String doDoubleClosure(RAbstractStringVector vector, Object store, int index,
+                        @Cached("vector.getClass()") Class<? extends RAbstractStringVector> cachedClass) {
+            return cachedClass.cast(vector).getDataAt(store, index);
+        }
+
+        @Fallback
+        protected java.lang.String doDoubleClosure(RAbstractStringVector vector, Object store, int index) {
+            return vector.getDataAt(store, index);
+        }
+
+        protected static boolean isGenericVector(RAbstractStringVector vector) {
+            return !(vector instanceof RStringVector);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataCopy.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataCopy.java
new file mode 100644
index 0000000000..f5b86c65dd
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataCopy.java
@@ -0,0 +1,96 @@
+/*
+ * 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 java.util.Arrays;
+
+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.RInternalError;
+import com.oracle.truffle.r.runtime.data.NativeDataAccess;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.nodes.GetDataCopyFactory.DoubleNodeGen;
+import com.oracle.truffle.r.runtime.data.nodes.GetDataCopyFactory.StringNodeGen;
+
+/**
+ * Nodes contained in this class materialize given vector into an array of corresponding type. The
+ * array is always a copy of the original data and can be modified freely.
+ *
+ * @see RVector#getDataCopy()
+ */
+public abstract class GetDataCopy {
+
+    public abstract static class Double extends Node {
+        public abstract double[] execute(RAbstractDoubleVector vector);
+
+        public static Double create() {
+            return DoubleNodeGen.create();
+        }
+
+        @Specialization(guards = "!vec.hasNativeMemoryData()")
+        protected double[] doManagedRVector(RDoubleVector vec) {
+            double[] data = vec.getInternalManagedData();
+            return Arrays.copyOf(data, data.length);
+        }
+
+        @Specialization(guards = "vec.hasNativeMemoryData()")
+        protected double[] doNativeDataRVector(RDoubleVector vec) {
+            return NativeDataAccess.copyDoubleNativeData(vec.getNativeMirror());
+        }
+
+        @Fallback
+        protected double[] doOthers(RAbstractDoubleVector vec) {
+            int len = vec.getLength();
+            double[] result = new double[len];
+            Object store = vec.getInternalStore();
+            for (int i = 0; i < len; i++) {
+                result[i] = vec.getDataAt(store, i);
+            }
+            return result;
+        }
+    }
+
+    public abstract static class String extends Node {
+        public abstract java.lang.String[] execute(RAbstractStringVector vector);
+
+        public static String create() {
+            return StringNodeGen.create();
+        }
+
+        @Specialization(guards = "vec.hasNativeMemoryData()")
+        protected java.lang.String[] doManagedRVector(RStringVector vec) {
+            throw RInternalError.unimplemented("string vectors backed by native memory");
+        }
+
+        @Specialization(guards = "!vec.hasNativeMemoryData()")
+        protected java.lang.String[] doNativeDataRVector(RStringVector vec) {
+            java.lang.String[] data = vec.getInternalManagedData();
+            return Arrays.copyOf(data, data.length);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataStore.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataStore.java
new file mode 100644
index 0000000000..d3587b1ed9
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetDataStore.java
@@ -0,0 +1,68 @@
+/*
+ * 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.RVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public abstract class GetDataStore extends Node {
+
+    protected static final int CACHE_LIMIT = 6;
+
+    public static GetDataStore create() {
+        return GetDataStoreNodeGen.create();
+    }
+
+    public abstract Object execute(RAbstractVector vector);
+
+    @Specialization(guards = "vector.hasNativeMemoryData()")
+    protected Object doNative(RVector<?> vector) {
+        return vector.getNativeMirror();
+    }
+
+    @Specialization(guards = {"noNativeMemoryData(vector)", "vector.getClass() == vectorClass"}, limit = "CACHE_LIMIT")
+    protected Object doGeneric(RAbstractVector vector,
+                    @Cached("vector.getClass()") Class<? extends RAbstractVector> vectorClass,
+                    @Cached("getStoreClass(vector)") Class<?> storeClass) {
+        Object store = vectorClass.cast(vector).getInternalStore();
+        assert store.getClass() == storeClass : "every concrete implementation of RAbstractVector#getInternalStore() must always return a store object of the same type.";
+        return storeClass.cast(store);
+    }
+
+    @Fallback
+    protected Object doFallback(RAbstractVector vector) {
+        return vector.getInternalStore();
+    }
+
+    protected static boolean noNativeMemoryData(RAbstractVector vector) {
+        return !(vector instanceof RVector<?>) || !((RVector) vector).hasNativeMemoryData();
+    }
+
+    protected static Class<?> getStoreClass(RAbstractVector vector) {
+        return vector.getInternalStore().getClass();
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetReadonlyData.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetReadonlyData.java
new file mode 100644
index 0000000000..a30faf79fd
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/GetReadonlyData.java
@@ -0,0 +1,77 @@
+/*
+ * 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.Specialization;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.data.NativeDataAccess;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RVector;
+
+/**
+ * Nodes contained in this class return an array that is either directly backing the vector data, or
+ * copy of it if the data is not internally represented as contiguous Java array. The result must
+ * not be modified, as it may result in different behaviour depending on the concrete vector
+ * implementation.
+ *
+ * @see RVector#getDataCopy()
+ */
+public class GetReadonlyData {
+
+    public abstract static class Double extends Node {
+        public abstract double[] execute(RDoubleVector vector);
+
+        @Specialization(guards = "!vec.hasNativeMemoryData()")
+        protected double[] doManagedRVector(RDoubleVector vec) {
+            return vec.getInternalManagedData();
+        }
+
+        @Specialization(guards = "vec.hasNativeMemoryData()")
+        protected double[] doNativeDataRVector(RDoubleVector vec) {
+            return NativeDataAccess.copyDoubleNativeData(vec.getNativeMirror());
+        }
+
+        public static Double create() {
+            return GetReadonlyDataFactory.DoubleNodeGen.create();
+        }
+    }
+
+    public abstract static class Int extends Node {
+        public abstract int[] execute(RIntVector vector);
+
+        @Specialization(guards = "!vec.hasNativeMemoryData()")
+        protected int[] doManagedRVector(RIntVector vec) {
+            return vec.getInternalManagedData();
+        }
+
+        @Specialization(guards = "vec.hasNativeMemoryData()")
+        protected int[] doNativeDataRVector(RIntVector vec) {
+            return NativeDataAccess.copyIntNativeData(vec.getNativeMirror());
+        }
+
+        public static Int create() {
+            return GetReadonlyDataFactory.IntNodeGen.create();
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/ReadAccessor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/ReadAccessor.java
new file mode 100644
index 0000000000..997488a9de
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/ReadAccessor.java
@@ -0,0 +1,184 @@
+/*
+ * 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.r.runtime.data.RComplex;
+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.RAbstractRawVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+/**
+ * Convenience classes that wraps {@link VectorReadAccess} node, the vector and its store so that
+ * those data can be passed around as a single paramter.
+ */
+public abstract class ReadAccessor {
+    private ReadAccessor() {
+    }
+
+    public static final class Int extends ReadAccessor {
+        private final RAbstractIntVector vector;
+        private final VectorReadAccess.Int readAccess;
+        private final Object store;
+
+        public Int(RAbstractIntVector vector, VectorReadAccess.Int readAccess) {
+            this.vector = vector;
+            this.readAccess = readAccess;
+            store = readAccess.getDataStore(vector);
+        }
+
+        public int getDataAt(int index) {
+            return readAccess.getDataAt(vector, store, index);
+        }
+
+        public Object getStore() {
+            return store;
+        }
+
+        public RAbstractIntVector getVector() {
+            return vector;
+        }
+    }
+
+    public static final class Double extends ReadAccessor {
+        private final RAbstractDoubleVector vector;
+        private final VectorReadAccess.Double readAccess;
+        private final Object store;
+
+        public Double(RAbstractDoubleVector vector, VectorReadAccess.Double readAccess) {
+            this.vector = vector;
+            this.readAccess = readAccess;
+            store = readAccess.getDataStore(vector);
+        }
+
+        public double getDataAt(int index) {
+            return readAccess.getDataAt(vector, store, index);
+        }
+
+        public Object getStore() {
+            return store;
+        }
+
+        public RAbstractDoubleVector getVector() {
+            return vector;
+        }
+    }
+
+    public static final class Logical extends ReadAccessor {
+        private final RAbstractLogicalVector vector;
+        private final VectorReadAccess.Logical readAccess;
+        private final Object store;
+
+        public Logical(RAbstractLogicalVector vector, VectorReadAccess.Logical readAccess) {
+            this.vector = vector;
+            this.readAccess = readAccess;
+            store = readAccess.getDataStore(vector);
+        }
+
+        public byte getDataAt(int index) {
+            return readAccess.getDataAt(vector, store, index);
+        }
+
+        public Object getStore() {
+            return store;
+        }
+
+        public RAbstractLogicalVector getVector() {
+            return vector;
+        }
+    }
+
+    public static final class Raw extends ReadAccessor {
+        private final RAbstractRawVector vector;
+        private final VectorReadAccess.Raw readAccess;
+        private final Object store;
+
+        public Raw(RAbstractRawVector vector, VectorReadAccess.Raw readAccess) {
+            this.vector = vector;
+            this.readAccess = readAccess;
+            store = readAccess.getDataStore(vector);
+        }
+
+        public byte getDataAt(int index) {
+            return readAccess.getDataAt(vector, store, index);
+        }
+
+        public Object getStore() {
+            return store;
+        }
+
+        public RAbstractRawVector getVector() {
+            return vector;
+        }
+    }
+
+    public static final class Complex extends ReadAccessor {
+        private final RAbstractComplexVector vector;
+        private final VectorReadAccess.Complex readAccess;
+        private final Object store;
+
+        public Complex(RAbstractComplexVector vector, VectorReadAccess.Complex readAccess) {
+            this.vector = vector;
+            this.readAccess = readAccess;
+            store = readAccess.getDataStore(vector);
+        }
+
+        public RComplex getDataAt(int index) {
+            return readAccess.getDataAt(vector, store, index);
+        }
+
+        public Object getStore() {
+            return store;
+        }
+
+        public RAbstractComplexVector getVector() {
+            return vector;
+        }
+    }
+
+    public static final class String extends ReadAccessor {
+        private final RAbstractStringVector vector;
+        private final VectorReadAccess.String readAccess;
+        private final Object store;
+
+        public String(RAbstractStringVector vector, VectorReadAccess.String readAccess) {
+            this.vector = vector;
+            this.readAccess = readAccess;
+            store = readAccess.getDataStore(vector);
+        }
+
+        public java.lang.String getDataAt(int index) {
+            return readAccess.getDataAt(vector, store, index);
+        }
+
+        public Object getStore() {
+            return store;
+        }
+
+        public RAbstractStringVector getVector() {
+            return vector;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/SetDataAt.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/SetDataAt.java
new file mode 100644
index 0000000000..46f7a849bc
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/SetDataAt.java
@@ -0,0 +1,218 @@
+/*
+ * 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.ImportStatic;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.NativeDataAccess;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRawVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RVector;
+
+public abstract class SetDataAt extends Node {
+
+    public abstract void setDataAtAsObject(RVector<?> vector, Object store, int index, Object value);
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class Double extends SetDataAt {
+
+        @Override
+        public final void setDataAtAsObject(RVector<?> vector, Object store, int index, Object value) {
+            setDataAt((RDoubleVector) vector, store, index, (double) value);
+        }
+
+        public final void setDataAt(RDoubleVector vector, Object store, int index, double value) {
+            execute(vector, store, index, value);
+        }
+
+        public abstract void execute(RDoubleVector vector, Object store, int index, double value);
+
+        @Specialization(guards = "!isNativeMirror(store)")
+        protected void doManagedRVector(RDoubleVector vec, Object store, int index, double value) {
+            ((double[]) store)[index] = value;
+        }
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected void doNativeDataRVector(RDoubleVector vec, Object store, int index, double value) {
+            NativeDataAccess.setNativeMirrorData(store, index, value);
+        }
+
+        public static Double create() {
+            return SetDataAtFactory.DoubleNodeGen.create();
+        }
+    }
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class Int extends SetDataAt {
+
+        @Override
+        public final void setDataAtAsObject(RVector<?> vector, Object store, int index, Object value) {
+            setDataAt((RIntVector) vector, store, index, (int) value);
+        }
+
+        public final void setDataAt(RIntVector vector, Object store, int index, int value) {
+            execute(vector, store, index, value);
+        }
+
+        public abstract void execute(RIntVector vector, Object store, int index, int value);
+
+        @Specialization(guards = "!isNativeMirror(store)")
+        protected void doManagedRVector(RIntVector vec, Object store, int index, int value) {
+            ((int[]) store)[index] = value;
+        }
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected void doNativeDataRVector(RIntVector vec, Object store, int index, int value) {
+            NativeDataAccess.setNativeMirrorData(store, index, value);
+        }
+
+        public static Int create() {
+            return SetDataAtFactory.IntNodeGen.create();
+        }
+    }
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class Logical extends SetDataAt {
+
+        @Override
+        public final void setDataAtAsObject(RVector<?> vector, Object store, int index, Object value) {
+            setDataAt((RLogicalVector) vector, store, index, (byte) value);
+        }
+
+        public final void setDataAt(RLogicalVector vector, Object store, int index, byte value) {
+            execute(vector, store, index, value);
+        }
+
+        public abstract void execute(RLogicalVector vector, Object store, int index, byte value);
+
+        @Specialization(guards = "!isNativeMirror(store)")
+        protected void doManagedRVector(RLogicalVector vec, Object store, int index, byte value) {
+            ((byte[]) store)[index] = value;
+        }
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected void doNativeDataRVector(RLogicalVector vec, Object store, int index, byte value) {
+            NativeDataAccess.setNativeMirrorData(store, index, value);
+        }
+
+        public static Logical create() {
+            return SetDataAtFactory.LogicalNodeGen.create();
+        }
+    }
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class Raw extends SetDataAt {
+
+        @Override
+        public final void setDataAtAsObject(RVector<?> vector, Object store, int index, Object value) {
+            setDataAt((RRawVector) vector, store, index, (byte) value);
+        }
+
+        public final void setDataAt(RRawVector vector, Object store, int index, byte value) {
+            execute(vector, store, index, value);
+        }
+
+        public abstract void execute(RRawVector vector, Object store, int index, byte value);
+
+        @Specialization(guards = "!isNativeMirror(store)")
+        protected void doManagedRVector(RRawVector vec, Object store, int index, byte value) {
+            ((byte[]) store)[index] = value;
+        }
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected void doNativeDataRVector(RRawVector vec, Object store, int index, byte value) {
+            NativeDataAccess.setNativeMirrorData(store, index, value);
+        }
+
+        public static Raw create() {
+            return SetDataAtFactory.RawNodeGen.create();
+        }
+    }
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class Complex extends SetDataAt {
+
+        @Override
+        public final void setDataAtAsObject(RVector<?> vector, Object store, int index, Object value) {
+            setDataAt((RComplexVector) vector, store, index, (RComplex) value);
+        }
+
+        public final void setDataAt(RComplexVector vector, Object store, int index, RComplex value) {
+            execute(vector, store, index, value);
+        }
+
+        public abstract void execute(RComplexVector vector, Object store, int index, RComplex value);
+
+        @Specialization(guards = "!isNativeMirror(storeObj)")
+        protected void doManagedRVector(RComplexVector vec, Object storeObj, int index, RComplex value) {
+            double[] store = (double[]) storeObj;
+            store[index * 2] = value.getRealPart();
+            store[index * 2 + 1] = value.getImaginaryPart();
+        }
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected void doNativeDataRVector(RComplexVector vec, Object store, int index, RComplex value) {
+            throw RInternalError.unimplemented();
+        }
+
+        public static Complex create() {
+            return SetDataAtFactory.ComplexNodeGen.create();
+        }
+    }
+
+    @ImportStatic(NativeDataAccess.class)
+    public abstract static class String extends SetDataAt {
+
+        @Override
+        public final void setDataAtAsObject(RVector<?> vector, Object store, int index, Object value) {
+            setDataAt((RStringVector) vector, store, index, (java.lang.String) value);
+        }
+
+        public final void setDataAt(RStringVector vector, Object store, int index, java.lang.String value) {
+            execute(vector, store, index, value);
+        }
+
+        public abstract void execute(RStringVector vector, Object store, int index, java.lang.String value);
+
+        @Specialization(guards = "!isNativeMirror(store)")
+        protected void doManagedRVector(RStringVector vec, Object store, int index, java.lang.String value) {
+            ((java.lang.String[]) store)[index] = value;
+        }
+
+        @Specialization(guards = "isNativeMirror(store)")
+        protected void doNativeDataRVector(RStringVector vec, Object store, int index, java.lang.String value) {
+            throw RInternalError.unimplemented();
+        }
+
+        public static String create() {
+            return SetDataAtFactory.StringNodeGen.create();
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorAccessAdapter.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorAccessAdapter.java
new file mode 100644
index 0000000000..c42c45e40b
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorAccessAdapter.java
@@ -0,0 +1,37 @@
+/*
+ * 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.nodes.Node;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+/**
+ * Factors out common code.
+ */
+abstract class VectorAccessAdapter extends Node {
+    @Child private GetDataStore getDataStoreNode = GetDataStoreNodeGen.create();
+
+    public Object getDataStore(RAbstractVector vector) {
+        return getDataStoreNode.execute(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
new file mode 100644
index 0000000000..d87792ed94
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorIterator.java
@@ -0,0 +1,348 @@
+/*
+ * 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.CompilerDirectives.ValueType;
+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.RInternalError;
+import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.data.NativeDataAccess;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRawVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RVector;
+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.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.VectorIterator.IteratorData;
+
+abstract class VectorIteratorNodeAdapter extends Node {
+    public static boolean hasNoNativeMemoryData(RAbstractVector vector) {
+        return !(vector instanceof RVector) || !((RVector) vector).hasNativeMemoryData();
+    }
+
+    public static boolean isRVector(RAbstractVector vector) {
+        return vector instanceof RVector;
+    }
+}
+
+abstract class GetIteratorNode extends VectorIteratorNodeAdapter {
+    public abstract IteratorData<?> execute(RAbstractVector vector);
+
+    @Specialization(guards = "vector.hasNativeMemoryData()")
+    protected IteratorData<?> nativeMirrorIterator(RVector<?> vector) {
+        return new IteratorData<>(vector.getNativeMirror(), vector.getLength());
+    }
+
+    @Specialization(guards = {"hasNoNativeMemoryData(vector)", "vectorClass == vector.getClass()"})
+    protected IteratorData<?> generic(RAbstractVector vector,
+                    @Cached("vector.getClass()") Class<? extends RAbstractVector> vectorClass) {
+        RAbstractVector profiledVec = vectorClass.cast(vector);
+        return new IteratorData<>(profiledVec.getInternalStore(), vector.getLength());
+    }
+
+    @Fallback
+    protected IteratorData<?> generic(RAbstractVector vector) {
+        return new IteratorData<>(vector.getInternalStore(), vector.getLength());
+    }
+}
+
+abstract class HasNextNode extends VectorIteratorNodeAdapter {
+    public abstract boolean execute(RAbstractVector vector, IteratorData<?> iterator);
+
+    @Specialization(guards = "!iter.hasNativeMirror()")
+    protected boolean intVector(RIntVector vector, IteratorData<?> iter) {
+        return iter.index < ((int[]) iter.store).length;
+    }
+
+    @Specialization(guards = "!iter.hasNativeMirror()")
+    protected boolean doubleVector(RDoubleVector vector, IteratorData<?> iter) {
+        return iter.index < ((double[]) iter.store).length;
+    }
+
+    @Specialization(guards = "!iter.hasNativeMirror()")
+    protected boolean logicalVector(RLogicalVector vector, IteratorData<?> iter) {
+        return iter.index < ((byte[]) iter.store).length;
+    }
+
+    @Specialization(guards = "!iter.hasNativeMirror()")
+    protected boolean rawVector(RRawVector vector, IteratorData<?> iter) {
+        return iter.index < ((byte[]) iter.store).length;
+    }
+
+    @Specialization(guards = "!iter.hasNativeMirror()")
+    protected boolean stringVector(RStringVector vector, IteratorData<?> iter) {
+        return iter.index < ((String[]) iter.store).length;
+    }
+
+    @Specialization(guards = {"!isRVector(vector)", "vectorClass == vector.getClass()"})
+    protected boolean generic(RAbstractVector vector, IteratorData<?> iter,
+                    @Cached("vector.getClass()") Class<? extends RAbstractVector> vectorClass) {
+        RAbstractVector profiledVec = vectorClass.cast(vector);
+        return iter.index < profiledVec.getLength();
+    }
+
+    @Fallback
+    protected boolean generic(RAbstractVector vector, IteratorData<?> iter) {
+        return iter.index < vector.getLength();
+    }
+}
+
+abstract class GetNextNode extends VectorIteratorNodeAdapter {
+    public abstract Object execute(RAbstractVector vector, IteratorData<?> iterator);
+
+    @Specialization(guards = "!iter.hasNativeMirror()")
+    protected int intVector(RIntVector vector, IteratorData<?> iter) {
+        return ((int[]) iter.store)[iter.index];
+    }
+
+    @Specialization(guards = "!iter.hasNativeMirror()")
+    protected double doubleVector(RDoubleVector vector, IteratorData<?> iter) {
+        return ((double[]) iter.store)[iter.index];
+    }
+
+    @Specialization(guards = "!iter.hasNativeMirror()")
+    protected byte logicalVector(RLogicalVector vector, IteratorData<?> iter) {
+        return ((byte[]) iter.store)[iter.index];
+    }
+
+    @Specialization(guards = "!iter.hasNativeMirror()")
+    protected RComplex doComplexVector(RComplexVector vector, IteratorData<?> iter) {
+        double[] arr = (double[]) iter.store;
+        return RComplex.valueOf(arr[iter.index * 2], arr[iter.index * 2 + 1]);
+    }
+
+    @Specialization(guards = "!iter.hasNativeMirror()")
+    protected byte doRawVector(RRawVector vector, IteratorData<?> iter) {
+        return ((byte[]) iter.store)[iter.index];
+    }
+
+    @Specialization(guards = "!iter.hasNativeMirror()")
+    protected String doStringVector(RStringVector vector, IteratorData<?> iter) {
+        return ((String[]) iter.store)[iter.index];
+    }
+
+    @Specialization(guards = "iter.hasNativeMirror()")
+    protected int intVectorNative(RIntVector vector, IteratorData<?> iter) {
+        return NativeDataAccess.getIntNativeMirrorData(iter.store, iter.index);
+    }
+
+    @Specialization(guards = "iter.hasNativeMirror()")
+    protected double doubleVectorNative(RDoubleVector vector, IteratorData<?> iter) {
+        return NativeDataAccess.getDoubleNativeMirrorData(iter.store, iter.index);
+    }
+
+    @Specialization(guards = "iter.hasNativeMirror()")
+    protected byte logicalVectorNative(RLogicalVector vector, IteratorData<?> iter) {
+        return NativeDataAccess.getLogicalNativeMirrorData(iter.store, iter.index);
+    }
+
+    @Specialization(guards = "iter.hasNativeMirror()")
+    protected byte doubleVectorNative(RRawVector vector, IteratorData<?> iter) {
+        return NativeDataAccess.getRawNativeMirrorData(iter.store, iter.index);
+    }
+
+    @Specialization(guards = "iter.hasNativeMirror()")
+    protected RComplex complexVectorNative(RComplexVector vector, IteratorData<?> iter) {
+        return NativeDataAccess.getComplexNativeMirrorData(iter.store, iter.index);
+    }
+
+    @Specialization(guards = "iter.hasNativeMirror()")
+    protected byte stringVectorNative(RStringVector vector, IteratorData<?> iter) {
+        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);
+    }
+
+    @Specialization(guards = "!isRVector(vector)")
+    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 String stringVectorGeneric(RAbstractStringVector vector, IteratorData<?> iter,
+                    @Cached("create()") GetDataAt.String getDataAtNode) {
+        return getDataAtNode.get(vector, iter.store, iter.index);
+    }
+
+    @Specialization(guards = "!isRVector(vector)")
+    protected byte rawVectorGeneric(RAbstractRawVector vector, IteratorData<?> iter,
+                    @Cached("create()") GetDataAt.Raw getDataAtNode) {
+        return getDataAtNode.get(vector, iter.store, iter.index);
+    }
+
+    @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(guards = "!isRVector(vector)")
+    protected RComplex complexVectorGeneric(RAbstractComplexVector vector, IteratorData<?> iter,
+                    @Cached("create()") GetDataAt.Complex getDataAtNode) {
+        return getDataAtNode.get(vector, iter.store, iter.index);
+    }
+}
+
+// Checkstyle: stop final class check
+// Note: the VectorIterator cannot be final, it has inner subclasses, which probably confuses check
+// style
+
+/**
+ * This node wraps 3 nodes needed to sequentially iterate a given vector and provides convenience
+ * methods to invoke those nodes: {@link #init(RAbstractVector)},
+ * {@link #next(RAbstractVector, Object)} and {@link #hasNext(RAbstractVector, Object)}.
+ * 
+ * To construct use factory methods from type specialized inner classes, e.g. {@link Int#create()},
+ * or generic version if the iterated vector could be of any type {@link Generic#create()}.
+ * 
+ * Iterator can wrap around, i.e. once the iteration ends, it starts again from the first element.
+ */
+public abstract class VectorIterator<T> extends Node {
+
+    // Note: it could be worth adding a LoopConditionProfile, however, it must be shared between
+    // getIteratorNode and getNextNode
+
+    @Child private GetIteratorNode getIteratorNode = GetIteratorNodeGen.create();
+    @Child private HasNextNode hasNextNode;
+    @Child private GetNextNode getNextNode = GetNextNodeGen.create();
+    private final boolean wrapAround;
+
+    private VectorIterator(boolean wrapAround) {
+        this.wrapAround = wrapAround;
+        if (!wrapAround) {
+            hasNextNode = HasNextNodeGen.create();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public Object init(RAbstractVector vector) {
+        return (IteratorData<T>) getIteratorNode.execute(vector);
+    }
+
+    public boolean hasNext(RAbstractVector vector, Object iterator) {
+        assert !wrapAround : "wrap-around iteration does not support hasNext";
+        return hasNextNode.execute(vector, (IteratorData<?>) iterator);
+    }
+
+    @SuppressWarnings("unchecked")
+    public T next(RAbstractVector vector, Object iterator) {
+        IteratorData<T> it = (IteratorData<T>) iterator;
+        assert it.index < it.length;
+        Object result = getNextNode.execute(vector, it);
+        if (wrapAround) {
+            it.index = Utils.incMod(it.index, it.length);
+        } else {
+            it.index++;
+        }
+        return (T) result;
+    }
+
+    public static final class Generic extends VectorIterator<Object> {
+
+        private Generic(boolean wrapAround) {
+            super(wrapAround);
+        }
+
+        public static Generic create() {
+            return new Generic(false);
+        }
+
+        public static Generic createWrapAround() {
+            return new Generic(true);
+        }
+    }
+
+    public static final class Int extends VectorIterator<Integer> {
+
+        public Int(boolean wrapAround) {
+            super(wrapAround);
+        }
+
+        public static Int create() {
+            return new Int(false);
+        }
+    }
+
+    public static final class Double extends VectorIterator<java.lang.Double> {
+        public Double(boolean wrapAround) {
+            super(wrapAround);
+        }
+
+        public static Double create() {
+            return new Double(false);
+        }
+    }
+
+    public static final class Logical extends VectorIterator<Byte> {
+        public Logical(boolean wrapAround) {
+            super(wrapAround);
+        }
+
+        public static Logical create() {
+            return new Logical(false);
+        }
+    }
+
+    public static final class Raw extends VectorIterator<Byte> {
+        public Raw(boolean wrapAround) {
+            super(wrapAround);
+        }
+
+        public static Raw create() {
+            return new Raw(false);
+        }
+    }
+
+    @ValueType
+    public static final class IteratorData<StoreT> {
+        public int index = 0;
+        public final StoreT store;
+        public final int length;
+
+        public IteratorData(StoreT store, int length) {
+            this.store = store;
+            this.length = length;
+        }
+
+        public boolean hasNativeMirror() {
+            return NativeDataAccess.isNativeMirror(store);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorReadAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorReadAccess.java
new file mode 100644
index 0000000000..f4d70cdf22
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorReadAccess.java
@@ -0,0 +1,152 @@
+/*
+ * 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.nodes.NodeCost;
+import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.r.runtime.data.RComplex;
+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.RAbstractRawVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+/**
+ * Contains nodes that encapsulate {@link GetDataStore} and one of the nodes from {@link GetDataAt}
+ * as these are often used together. These are convenience wrappers to be used e.g. for a @Cached
+ * parameter.
+ */
+public abstract class VectorReadAccess extends VectorAccessAdapter {
+
+    public abstract Object getDataAtAsObject(RAbstractVector vector, Object store, int index);
+
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class Double extends VectorReadAccess {
+        @Child private GetDataAt.Double getDataAtNode = GetDataAt.Double.create();
+
+        public double getDataAt(RAbstractDoubleVector vec, Object store, int index) {
+            return getDataAtNode.get(vec, store, index);
+        }
+
+        @Override
+        public Object getDataAtAsObject(RAbstractVector vector, Object store, int index) {
+            return getDataAt((RAbstractDoubleVector) vector, store, index);
+        }
+
+        public static Double create() {
+            return new Double();
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class Int extends VectorReadAccess {
+        @Child private GetDataAt.Int getDataAtNode = GetDataAt.Int.create();
+
+        public int getDataAt(RAbstractIntVector vec, Object store, int index) {
+            return getDataAtNode.get(vec, store, index);
+        }
+
+        @Override
+        public Object getDataAtAsObject(RAbstractVector vector, Object store, int index) {
+            return getDataAt((RAbstractIntVector) vector, store, index);
+        }
+
+        public static Int create() {
+            return new Int();
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class Logical extends VectorReadAccess {
+        @Child private GetDataAt.Logical getDataAtNode = GetDataAt.Logical.create();
+
+        public byte getDataAt(RAbstractLogicalVector vec, Object store, int index) {
+            return getDataAtNode.get(vec, store, index);
+        }
+
+        @Override
+        public Object getDataAtAsObject(RAbstractVector vector, Object store, int index) {
+            return getDataAt((RAbstractLogicalVector) vector, store, index);
+        }
+
+        public static Logical create() {
+            return new Logical();
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class Complex extends VectorReadAccess {
+        @Child private GetDataAt.Complex getDataAtNode = GetDataAt.Complex.create();
+
+        public RComplex getDataAt(RAbstractComplexVector vec, Object store, int index) {
+            return getDataAtNode.get(vec, store, index);
+        }
+
+        @Override
+        public Object getDataAtAsObject(RAbstractVector vector, Object store, int index) {
+            return getDataAt((RAbstractComplexVector) vector, store, index);
+        }
+
+        public static Complex create() {
+            return new Complex();
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class String extends VectorReadAccess {
+        @Child private GetDataAt.String getDataAtNode = GetDataAt.String.create();
+
+        public java.lang.String getDataAt(RAbstractStringVector vec, Object store, int index) {
+            return getDataAtNode.get(vec, store, index);
+        }
+
+        @Override
+        public Object getDataAtAsObject(RAbstractVector vector, Object store, int index) {
+            return getDataAt((RAbstractStringVector) vector, store, index);
+        }
+
+        public static String create() {
+            return new String();
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class Raw extends VectorReadAccess {
+        @Child private GetDataAt.Raw getDataAtNode = GetDataAt.Raw.create();
+
+        public byte getDataAt(RAbstractRawVector vec, Object store, int index) {
+            return getDataAtNode.get(vec, store, index);
+        }
+
+        @Override
+        public Object getDataAtAsObject(RAbstractVector vector, Object store, int index) {
+            return getDataAt((RAbstractRawVector) vector, store, index);
+        }
+
+        public static Raw create() {
+            return new Raw();
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorWriteAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorWriteAccess.java
new file mode 100644
index 0000000000..8c8af33639
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/VectorWriteAccess.java
@@ -0,0 +1,118 @@
+/*
+ * 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.nodes.NodeCost;
+import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRawVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+
+/**
+ * Contains nodes that encapsulate {@link GetDataStore} and one of the nodes from {@link SetDataAt}
+ * as these are often used together. These are convenience wrappers to be used e.g. for a @Cached
+ * parameter.
+ */
+public abstract class VectorWriteAccess {
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class Double extends VectorAccessAdapter {
+        @Child private SetDataAt.Double setDataAtNode = SetDataAt.Double.create();
+
+        public void setDataAt(RDoubleVector vector, Object store, int index, double value) {
+            setDataAtNode.setDataAt(vector, store, index, value);
+        }
+
+        public static Double create() {
+            return new Double();
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class Int extends VectorAccessAdapter {
+        @Child private SetDataAt.Int setDataAtNode = SetDataAt.Int.create();
+
+        public void setDataAt(RIntVector vector, Object store, int index, int value) {
+            setDataAtNode.setDataAt(vector, store, index, value);
+        }
+
+        public static Int create() {
+            return new Int();
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class Logical extends VectorAccessAdapter {
+        @Child private SetDataAt.Logical setDataAtNode = SetDataAt.Logical.create();
+
+        public void setDataAt(RLogicalVector vector, Object store, int index, byte value) {
+            setDataAtNode.setDataAt(vector, store, index, value);
+        }
+
+        public static Logical create() {
+            return new Logical();
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class Raw extends VectorAccessAdapter {
+        @Child private SetDataAt.Raw setDataAtNode = SetDataAt.Raw.create();
+
+        public void setDataAt(RRawVector vector, Object store, int index, byte value) {
+            setDataAtNode.setDataAt(vector, store, index, value);
+        }
+
+        public static Raw create() {
+            return new Raw();
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class String extends VectorAccessAdapter {
+        @Child private SetDataAt.String setDataAtNode = SetDataAt.String.create();
+
+        public void setDataAt(RStringVector vector, Object store, int index, java.lang.String value) {
+            setDataAtNode.setDataAt(vector, store, index, value);
+        }
+
+        public static String create() {
+            return new String();
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    public static final class Complex extends VectorAccessAdapter {
+        @Child private SetDataAt.Complex setDataAtNode = SetDataAt.Complex.create();
+
+        public void setDataAt(RComplexVector vector, Object store, int index, RComplex value) {
+            setDataAtNode.setDataAt(vector, store, index, value);
+        }
+
+        public static Complex create() {
+            return new Complex();
+        }
+    }
+}
-- 
GitLab