diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/PPSum.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/PPSum.java
index fc90f5fc2cc3c3903c806c11ef00bfb6e5629569..ae62a6fc97e476bc75d2919aef54df0fea26cd6e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/PPSum.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/PPSum.java
@@ -28,13 +28,11 @@ import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.library.stats.PPSumFactory.IntgrtVecNodeGen;
 import com.oracle.truffle.r.library.stats.PPSumFactory.PPSumExternalNodeGen;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDataFactory.VectorFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
 import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.RandomIterator;
-import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.SequentialIterator;
 
 public abstract class PPSum {
 
@@ -50,18 +48,19 @@ public abstract class PPSum {
                         @Cached("create()") VectorFactory factory,
                         @Cached("u.access()") VectorAccess uAccess) {
 
-            RandomIterator uIter = uAccess.randomAccess(u);
-            int n = uAccess.getLength(uIter);
-            double tmp1 = 0.0;
-            for (int i = 1; i <= sl; i++) {
-                double tmp2 = 0.0;
-                for (int j = i; j < n; j++) {
-                    tmp2 += uAccess.getDouble(uIter, j) * uAccess.getDouble(uIter, j - i);
+            try (RandomIterator uIter = uAccess.randomAccess(u)) {
+                int n = uAccess.getLength(uIter);
+                double tmp1 = 0.0;
+                for (int i = 1; i <= sl; i++) {
+                    double tmp2 = 0.0;
+                    for (int j = i; j < n; j++) {
+                        tmp2 += uAccess.getDouble(uIter, j) * uAccess.getDouble(uIter, j - i);
+                    }
+                    tmp2 *= 1.0 - i / (sl + 1.0);
+                    tmp1 += tmp2;
                 }
-                tmp2 *= 1.0 - i / (sl + 1.0);
-                tmp1 += tmp2;
+                return factory.createDoubleVectorFromScalar(2.0 * tmp1 / n);
             }
-            return factory.createDoubleVectorFromScalar(2.0 * tmp1 / n);
         }
 
         @Specialization(replaces = "doPPSum")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
index 58653d31ac1260cf5795ed598a7cc9d339a60374..bc38674178f38b0a86eb38ad494f1779ad74dbd0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
@@ -76,6 +76,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
@@ -96,7 +97,6 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
     @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create();
     @Children private final CombineInputCast[] inputCasts = new CombineInputCast[MAX_PROFILES];
     @Child private CombineInputCast overflowInputCast;
-    @Child private CastToVectorNode castVector;
 
     private final BranchProfile naBranch = BranchProfile.create();
     private final NACheck naCheck = NACheck.create();
@@ -140,7 +140,6 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
                     @Cached("precedence(args, cachedSignature.getLength())") int cachedPrecedence,
                     @Cached("createCast(cachedPrecedence)") CastNode cast,
                     @Cached("create()") BranchProfile naNameBranch,
-                    @Cached("create()") NACheck naNameCheck,
                     @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile,
                     @Cached("create()") GetNamesAttributeNode getNamesNode) {
         CompilerAsserts.partialEvaluationConstant(cachedSignature);
@@ -157,7 +156,7 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
         // prepare the names (if there are any)
         boolean signatureHasNames = signatureHasNames(cachedSignature);
         CompilerAsserts.partialEvaluationConstant(signatureHasNames);
-        RStringVector namesVector = hasNamesProfile.profile(signatureHasNames || hasNames(elements, getNamesNode)) ? foldNames(naNameBranch, naNameCheck, elements, size, cachedSignature, getNamesNode)
+        RStringVector namesVector = hasNamesProfile.profile(signatureHasNames || hasNames(elements, getNamesNode)) ? foldNames(naNameBranch, elements, size, cachedSignature, getNamesNode)
                         : null;
 
         // get the actual contents of the result
@@ -174,10 +173,9 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
                     @Cached("precedence(args, args.getLength())") int cachedPrecedence,
                     @Cached("createCast(cachedPrecedence)") CastNode cast,
                     @Cached("create()") BranchProfile naNameBranch,
-                    @Cached("create()") NACheck naNameCheck,
                     @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile,
                     @Cached("create()") GetNamesAttributeNode getNamesNode) {
-        return combineCached(args, false, args.getSignature(), cachedPrecedence, cast, naNameBranch, naNameCheck, hasNamesProfile, getNamesNode);
+        return combineCached(args, false, args.getSignature(), cachedPrecedence, cast, naNameBranch, hasNamesProfile, getNamesNode);
     }
 
     @Specialization(guards = "recursive")
@@ -251,19 +249,30 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
         return false;
     }
 
+    private static class FoldedNames {
+        final String[] names;
+        boolean complete = true;
+
+        FoldedNames(String[] array) {
+            this.names = array;
+        }
+    }
+
     @ExplodeLoop
-    private RStringVector foldNames(BranchProfile naNameBranch, NACheck naNameCheck, Object[] elements, int size, ArgumentsSignature signature, GetNamesAttributeNode getNamesNode) {
-        RStringVector result = RDataFactory.createStringVector(new String[size], true);
-        result.incRefCount();
+    private RStringVector foldNames(BranchProfile naNameBranch, Object[] elements, int size, ArgumentsSignature signature, GetNamesAttributeNode getNamesNode) {
+        FoldedNames foldedNames = new FoldedNames(new String[size]);
         int pos = 0;
         for (int i = 0; i < elements.length; i++) {
             Object element = getCast(i).valueProfile.profile(elements[i]);
-            pos += processNamesElement(naNameBranch, naNameCheck, result, pos, element, i, signature, getNamesNode);
+            pos += processNamesElement(naNameBranch, foldedNames, pos, element, i, signature, getNamesNode);
         }
+        RStringVector result = RDataFactory.createStringVector(foldedNames.names, foldedNames.complete);
+        result.incRefCount();
         return result;
     }
 
-    private int processNamesElement(BranchProfile naNameBranch, NACheck naNameCheck, RStringVector result, int pos, Object element, int index, ArgumentsSignature signature,
+    private int processNamesElement(BranchProfile naNameBranch, FoldedNames foldedNames, int pos, Object element,
+                    int index, ArgumentsSignature signature,
                     GetNamesAttributeNode getNamesNode) {
         String signatureName = signature.getName(index);
         if (element instanceof RAbstractVector) {
@@ -279,16 +288,19 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
                 }
             }
             if (hasNewNamesProfile.profile(newNames != null)) {
-                for (int i1 = 0; i1 < length; i1++) {
-                    result.transferElementSameType(pos + i1, newNames, i1);
-                }
-                if (!newNames.isComplete()) {
-                    naNameBranch.enter();
-                    result.setComplete(false);
+                VectorAccess newNamesAccess = newNames.slowPathAccess();
+                try (VectorAccess.RandomIterator newNamesIter = newNamesAccess.randomAccess(newNames)) {
+                    for (int i1 = 0; i1 < length; i1++) {
+                        foldedNames.names[pos + i1] = newNamesAccess.getString(newNamesIter, i1);
+                    }
+                    if (!newNames.isComplete()) {
+                        naNameBranch.enter();
+                        foldedNames.complete = false;
+                    }
                 }
             } else {
                 for (int i1 = 0; i1 < length; i1++) {
-                    result.updateDataAt(pos + i1, RRuntime.NAMES_ATTR_EMPTY_VALUE, naNameCheck);
+                    foldedNames.names[pos + i1] = RRuntime.NAMES_ATTR_EMPTY_VALUE;
                 }
             }
             return v.getLength();
@@ -297,7 +309,7 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
             return 0;
         } else {
             String name = signatureName != null ? signatureName : RRuntime.NAMES_ATTR_EMPTY_VALUE;
-            result.updateDataAt(pos, name, naNameCheck);
+            foldedNames.names[pos] = name;
             return 1;
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
index 0a382c92aa67d8b806d07d425eaf9e5e96b133a4..1419067f9bdf1dc4cf52d0c3be0dee3272057e04 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
@@ -28,6 +28,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 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.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -35,15 +36,14 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.ops.na.NACheck;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
+import com.oracle.truffle.r.runtime.data.nodes.VectorReuse;
 
 @RBuiltin(name = "make.names", kind = INTERNAL, parameterNames = {"names", "allow_"}, behavior = PURE)
 public abstract class MakeNames extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile namesLengthZero = ConditionProfile.createBinaryProfile();
-    private final NACheck dummyCheck = NACheck.create(); // never triggered (used for vector update)
 
     static {
         Casts casts = new Casts(MakeNames.class);
@@ -101,15 +101,28 @@ public abstract class MakeNames extends RBuiltinNode.Arg2 {
         }
     }
 
-    private static RStringVector getNewNames(RAbstractStringVector names, RStringVector newNames) {
-        RStringVector ret = newNames;
-        if (ret == null) {
-            ret = names.materialize();
-            if (ret.isShared()) {
-                ret = (RStringVector) ret.copy();
-            }
+    private static class NewNames {
+        final RAbstractStringVector vector;
+        final VectorAccess access;
+        final VectorAccess.RandomIterator iter;
+
+        NewNames(RAbstractStringVector vector, VectorAccess access, VectorAccess.RandomIterator iter) {
+            this.vector = vector;
+            this.access = access;
+            this.iter = iter;
+        }
+    }
+
+    private static NewNames updateNewNames(RAbstractStringVector names, VectorReuse reuse, int index, String newName, NewNames newNames) {
+        NewNames nn = newNames;
+        if (nn == null) {
+            RAbstractStringVector res = reuse.getResult(names);
+            VectorAccess access = reuse.access(res);
+            VectorAccess.RandomIterator iter = access.randomAccess(res);
+            nn = new NewNames(res, access, iter);
         }
-        return ret;
+        nn.access.setString(nn.iter, index, newName);
+        return nn;
     }
 
     private static char[] getNameArray(String name, char[] nameArray) {
@@ -145,29 +158,43 @@ public abstract class MakeNames extends RBuiltinNode.Arg2 {
         return newName;
     }
 
-    @Specialization
-    protected RAbstractStringVector makeNames(RAbstractStringVector names, byte allowUnderScoreArg) {
-        if (namesLengthZero.profile(names.getLength() == 0)) {
-            return names;
-        } else {
-            boolean allowUnderscore = allowUnderScoreArg == RRuntime.LOGICAL_TRUE;
-            RStringVector newNames = null;
-            for (int i = 0; i < names.getLength(); i++) {
-                String name = names.getDataAt(i);
-                String newName = getKeyword(name, allowUnderscore);
-                if (newName != null) {
-                    newNames = getNewNames(names, newNames);
-                    newNames.updateDataAt(i, newName, dummyCheck);
-                } else {
-                    newName = getName(name, allowUnderscore);
-                    if (newName != name) {
-                        // getName returns "name" in case nothing's changed
-                        newNames = getNewNames(names, newNames);
-                        newNames.updateDataAt(i, newName, dummyCheck);
+    @Specialization(guards = {"namesAccess.supports(names)", "reuse.supports(names)"})
+    protected RAbstractStringVector makeNames(RAbstractStringVector names, byte allowUnderScoreArg,
+                    @Cached("names.access()") VectorAccess namesAccess,
+                    @Cached("createNonShared(names)") VectorReuse reuse) {
+        try (VectorAccess.SequentialIterator namesIter = namesAccess.access(names)) {
+            if (namesLengthZero.profile(namesAccess.getLength(namesIter) == 0)) {
+                return names;
+            } else {
+                boolean allowUnderscore = allowUnderScoreArg == RRuntime.LOGICAL_TRUE;
+                NewNames newNames = null;
+                try {
+                    while (namesAccess.next(namesIter)) {
+                        String name = namesAccess.getString(namesIter);
+                        String newName = getKeyword(name, allowUnderscore);
+                        if (newName != null) {
+                            newNames = updateNewNames(names, reuse, namesIter.getIndex(), newName, newNames);
+                        } else {
+                            newName = getName(name, allowUnderscore);
+                            if (newName != name) {
+                                // getName returns "name" in case nothing's changed
+                                newNames = updateNewNames(names, reuse, namesIter.getIndex(), newName, newNames);
+                            }
+                        }
+                    }
+                } finally {
+                    if (newNames != null) {
+                        newNames.iter.close();
                     }
                 }
+                return newNames != null ? newNames.vector : names;
             }
-            return newNames != null ? newNames : names;
         }
     }
+
+    @Specialization(replaces = "makeNames")
+    protected RAbstractStringVector makeNamesGeneric(RAbstractStringVector names, byte allowUnderScoreArg,
+                    @Cached("createNonSharedGeneric()") VectorReuse reuse) {
+        return makeNames(names, allowUnderScoreArg, names.slowPathAccess(), reuse);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
index 79ba2deff626e7d39f093471d4326bae64af5500..793deb85bb760d07b144cfecf30b4f67c19c3460 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
@@ -43,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RStringSequence;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.ops.na.NACheck;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
 
 @RBuiltin(name = "make.unique", kind = INTERNAL, parameterNames = {"names", "sep"}, behavior = PURE)
 public abstract class MakeUnique extends RBuiltinNode.Arg2 {
@@ -51,7 +51,6 @@ public abstract class MakeUnique extends RBuiltinNode.Arg2 {
     @Child private ReuseNonSharedNode reuseNonSharedNode;
 
     private final ConditionProfile trivialSizeProfile = ConditionProfile.createBinaryProfile();
-    private final NACheck dummyCheck = NACheck.create(); // never triggered (used for vector update)
 
     static {
         Casts casts = new Casts(MakeUnique.class);
@@ -91,44 +90,48 @@ public abstract class MakeUnique extends RBuiltinNode.Arg2 {
 
     @TruffleBoundary
     protected RStringVector doLargeVector(RStringVector names, String sep) {
-        HashMap<String, AtomicInteger> keys = new HashMap<>(names.getLength());
-        boolean containsDuplicates = false;
-        boolean containsClashes = true;
-        for (int i = 0; i < names.getLength(); i++) {
-            AtomicInteger value = new AtomicInteger(0);
-            String element = names.getDataAt(i);
-            AtomicInteger prev = keys.put(element, value);
-            if (prev != null) {
-                containsDuplicates = true;
-                value.incrementAndGet();
-                if (!containsClashes) {
-                    int lastIndexOf = element.lastIndexOf(sep);
-                    // If an element contains the separator string followed by a digit, we may
-                    // encounter clashes.
-                    containsClashes = lastIndexOf != -1 && lastIndexOf + 1 < element.length() && Character.isDigit(element.charAt(lastIndexOf + 1));
+        VectorAccess access = names.slowPathAccess();
+        try (VectorAccess.RandomIterator iter = access.randomAccess(names)) {
+            int length = access.getLength(iter);
+            HashMap<String, AtomicInteger> keys = new HashMap<>(length);
+            boolean containsDuplicates = false;
+            boolean containsClashes = true;
+            for (int i = 0; i < length; i++) {
+                AtomicInteger value = new AtomicInteger(0);
+                String element = access.getString(iter, i);
+                AtomicInteger prev = keys.put(element, value);
+                if (prev != null) {
+                    containsDuplicates = true;
+                    value.incrementAndGet();
+                    if (!containsClashes) {
+                        int lastIndexOf = element.lastIndexOf(sep);
+                        // If an element contains the separator string followed by a digit, we may
+                        // encounter clashes.
+                        containsClashes = lastIndexOf != -1 && lastIndexOf + 1 < element.length() && Character.isDigit(element.charAt(lastIndexOf + 1));
+                    }
                 }
             }
-        }
-        if (containsDuplicates) {
-            for (int i = 0; i < names.getLength(); i++) {
-                AtomicInteger atomicInteger = keys.get(names.getDataAt(i));
-                int curCnt = atomicInteger.getAndIncrement() - 1;
-                if (curCnt > 0) {
-                    String updatedElement;
-                    do {
-                        updatedElement = names.getDataAt(i) + sep + curCnt;
+            if (containsDuplicates) {
+                for (int i = 0; i < length; i++) {
+                    AtomicInteger atomicInteger = keys.get(access.getString(iter, i));
+                    int curCnt = atomicInteger.getAndIncrement() - 1;
+                    if (curCnt > 0) {
+                        String updatedElement;
+                        do {
+                            updatedElement = access.getString(iter, i) + sep + curCnt;
 
-                        // The generated string may already be in the vector.
-                        if (containsClashes && keys.containsKey(updatedElement)) {
-                            curCnt = atomicInteger.getAndIncrement() - 1;
-                        } else {
-                            break;
-                        }
-                    } while (true);
-                    names.updateDataAt(i, updatedElement, dummyCheck);
+                            // The generated string may already be in the vector.
+                            if (containsClashes && keys.containsKey(updatedElement)) {
+                                curCnt = atomicInteger.getAndIncrement() - 1;
+                            } else {
+                                break;
+                            }
+                        } while (true);
+                        access.setString(iter, i, updatedElement);
+                    }
                 }
             }
+            return names;
         }
-        return names;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
index add7367ea2fa6a0b51217e0b763c8e0559dc305e..22c41124aa124dc10b49b36ad21dc9561b0ba7e7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
@@ -36,9 +36,10 @@ import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.Conver
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.data.RDoubleVector;
-import com.oracle.truffle.r.runtime.data.RIntVector;
+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.VectorAccess;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
@@ -170,18 +171,38 @@ class SpecialsUtils {
             return value;
         }
 
-        @Specialization(guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null", "hasAttrsNode.execute(value)"})
-        protected static int convertIntVector(RIntVector value,
+        @Specialization(guards = {"access.supports(value)", "value.getLength() == 1", "hierarchyNode.execute(value) == null", "hasAttrsNode.execute(value)"})
+        protected static int convertIntVector(RAbstractIntVector value,
+                        @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode,
+                        @Cached("create()") @SuppressWarnings("unused") HasAttributesNode hasAttrsNode,
+                        @Cached("value.access()") VectorAccess access) {
+            try (VectorAccess.RandomIterator iter = access.randomAccess(value)) {
+                return access.getInt(iter, 0);
+            }
+        }
+
+        @Specialization(replaces = "convertIntVector", guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null", "hasAttrsNode.execute(value)"})
+        protected static int convertIntVectorGeneric(RAbstractIntVector value,
                         @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode,
                         @Cached("create()") @SuppressWarnings("unused") HasAttributesNode hasAttrsNode) {
-            return value.getDataAt(0);
+            return convertIntVector(value, hierarchyNode, hasAttrsNode, value.slowPathAccess());
+        }
+
+        @Specialization(guards = {"access.supports(value)", "value.getLength() == 1", "hierarchyNode.execute(value) == null", "hasAttrsNode.execute(value)"})
+        protected static double convertDoubleVector(RAbstractDoubleVector value,
+                        @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode,
+                        @Cached("create()") @SuppressWarnings("unused") HasAttributesNode hasAttrsNode,
+                        @Cached("value.access()") VectorAccess access) {
+            try (VectorAccess.RandomIterator iter = access.randomAccess(value)) {
+                return access.getDouble(iter, 0);
+            }
         }
 
-        @Specialization(guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null", "hasAttrsNode.execute(value)"})
-        protected static double convertDoubleVector(RDoubleVector value,
+        @Specialization(replaces = "convertDoubleVector", guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null", "hasAttrsNode.execute(value)"})
+        protected static double convertDoubleVectorGeneric(RAbstractDoubleVector value,
                         @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode,
                         @Cached("create()") @SuppressWarnings("unused") HasAttributesNode hasAttrsNode) {
-            return value.getDataAt(0);
+            return convertDoubleVector(value, hierarchyNode, hasAttrsNode, value.slowPathAccess());
         }
 
         @Specialization(replaces = {"convertIntVector", "convertDoubleVector"})
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
index 1cf72271811fdea2e4d1ce12505e81076984229d..1e5a320d89dcebbaaa0b5174eb2dd3b9e6e3c1af 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
@@ -57,6 +57,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
 /**
@@ -72,19 +73,43 @@ abstract class SubscriptSpecialBase extends SubscriptSpecialCommon {
 
     public abstract Object execute(VirtualFrame frame, Object vec, int index);
 
-    @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index)"})
-    protected int access(RAbstractIntVector vector, int index) {
-        return vector.getDataAt(index - 1);
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "isValidIndex(vector, index)"})
+    protected int accessInt(RAbstractIntVector vector, int index,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            return access.getInt(iter, index - 1);
+        }
+    }
+
+    @Specialization(replaces = "accessInt", guards = {"simpleVector(vector)", "isValidIndex(vector, index)"})
+    protected int accessIntGeneric(RAbstractIntVector vector, int index) {
+        return accessInt(vector, index, vector.slowPathAccess());
     }
 
-    @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index)"})
-    protected double access(RAbstractDoubleVector vector, int index) {
-        return vector.getDataAt(index - 1);
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "isValidIndex(vector, index)"})
+    protected double accessDouble(RAbstractDoubleVector vector, int index,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            return access.getDouble(iter, index - 1);
+        }
+    }
+
+    @Specialization(replaces = "accessDouble", guards = {"simpleVector(vector)", "isValidIndex(vector, index)"})
+    protected double accessDoubleGeneric(RAbstractDoubleVector vector, int index) {
+        return accessDouble(vector, index, vector.slowPathAccess());
+    }
+
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "isValidIndex(vector, index)"})
+    protected String accessString(RAbstractStringVector vector, int index,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            return access.getString(iter, index - 1);
+        }
     }
 
-    @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index)"})
-    protected String access(RAbstractStringVector vector, int index) {
-        return vector.getDataAt(index - 1);
+    @Specialization(replaces = "accessString", guards = {"simpleVector(vector)", "isValidIndex(vector, index)"})
+    protected String accessStringGeneric(RAbstractStringVector vector, int index) {
+        return accessString(vector, index, vector.slowPathAccess());
     }
 
     @SuppressWarnings("unused")
@@ -107,19 +132,43 @@ abstract class SubscriptSpecial2Base extends SubscriptSpecial2Common {
 
     public abstract Object execute(VirtualFrame frame, Object vec, int index1, int index2);
 
-    @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index1, index2)"})
-    protected int access(RAbstractIntVector vector, int index1, int index2) {
-        return vector.getDataAt(matrixIndex(vector, index1, index2));
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "isValidIndex(vector, index1, index2)"})
+    protected int accessInt(RAbstractIntVector vector, int index1, int index2,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            return access.getInt(iter, matrixIndex(vector, index1, index2));
+        }
+    }
+
+    @Specialization(replaces = "accessInt", guards = {"simpleVector(vector)", "isValidIndex(vector, index1, index2)"})
+    protected int accessIntGeneric(RAbstractIntVector vector, int index1, int index2) {
+        return accessInt(vector, index1, index2, vector.slowPathAccess());
     }
 
-    @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index1, index2)"})
-    protected double access(RAbstractDoubleVector vector, int index1, int index2) {
-        return vector.getDataAt(matrixIndex(vector, index1, index2));
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "isValidIndex(vector, index1, index2)"})
+    protected double accessDouble(RAbstractDoubleVector vector, int index1, int index2,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            return access.getDouble(iter, matrixIndex(vector, index1, index2));
+        }
+    }
+
+    @Specialization(replaces = "accessDouble", guards = {"simpleVector(vector)", "isValidIndex(vector, index1, index2)"})
+    protected double accessDoubleGeneric(RAbstractDoubleVector vector, int index1, int index2) {
+        return accessDouble(vector, index1, index2, vector.slowPathAccess());
+    }
+
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "isValidIndex(vector, index1, index2)"})
+    protected String accessString(RAbstractStringVector vector, int index1, int index2,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            return access.getString(iter, matrixIndex(vector, index1, index2));
+        }
     }
 
-    @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index1, index2)"})
-    protected String access(RAbstractStringVector vector, int index1, int index2) {
-        return vector.getDataAt(matrixIndex(vector, index1, index2));
+    @Specialization(replaces = "accessString", guards = {"simpleVector(vector)", "isValidIndex(vector, index1, index2)"})
+    protected String accessStringGeneric(RAbstractStringVector vector, int index1, int index2) {
+        return accessString(vector, index1, index2, vector.slowPathAccess());
     }
 
     @SuppressWarnings("unused")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
index dee733d610767ce17f9da037ee79639076c60102..42a5cc5eb45477cc96c0966a9d70c8330e8d5d97 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.infix;
 
+import com.oracle.truffle.api.dsl.Cached;
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex;
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertValue;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
@@ -45,6 +46,7 @@ import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpec
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecialCommon;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RSpecialFactory;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -53,8 +55,8 @@ import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
 import com.oracle.truffle.r.runtime.nodes.RNode;
-import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 abstract class UpdateSubscriptSpecial extends SubscriptSpecialCommon {
 
@@ -62,34 +64,90 @@ abstract class UpdateSubscriptSpecial extends SubscriptSpecialCommon {
         super(inReplacement);
     }
 
-    private final NACheck naCheck = NACheck.create();
-
     protected abstract Object execute(VirtualFrame frame, Object vec, Object index, Object value);
 
-    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
-    protected RIntVector set(RIntVector vector, int index, int value) {
-        return vector.updateDataAt(index - 1, value, naCheck);
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    protected RIntVector setInt(RIntVector vector, int index, int value,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            access.setInt(iter, index - 1, value);
+            if (RRuntime.isNA(value)) {
+                vector.setComplete(false);
+            }
+            return vector;
+        }
     }
 
-    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
-    protected RDoubleVector set(RDoubleVector vector, int index, double value) {
-        return vector.updateDataAt(index - 1, value, naCheck);
+    @Specialization(replaces = "setInt", guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    protected RIntVector setIntGeneric(RIntVector vector, int index, int value) {
+        return setInt(vector, index, value, vector.slowPathAccess());
     }
 
-    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
-    protected RStringVector set(RStringVector vector, int index, String value) {
-        return vector.updateDataAt(index - 1, value, naCheck);
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    protected RDoubleVector setDouble(RDoubleVector vector, int index, double value,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            access.setDouble(iter, index - 1, value);
+            if (RRuntime.isNA(value)) {
+                vector.setComplete(false);
+            }
+            return vector;
+        }
+    }
+
+    @Specialization(replaces = "setDouble", guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    protected RDoubleVector setDoubleGeneric(RDoubleVector vector, int index, double value) {
+        return setDouble(vector, index, value, vector.slowPathAccess());
+    }
+
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    protected RStringVector setString(RStringVector vector, int index, String value,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            access.setString(iter, index - 1, value);
+            if (RRuntime.isNA(value)) {
+                vector.setComplete(false);
+            }
+            return vector;
+        }
     }
 
-    @Specialization(guards = {"simpleVector(list)", "!list.isShared()", "isValidIndex(list, index)", "isSingleElement(value)"})
-    protected static Object set(RList list, int index, Object value) {
-        list.setDataAt(index - 1, value);
-        return list;
+    @Specialization(replaces = "setString", guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    protected RStringVector setStringGeneric(RStringVector vector, int index, String value) {
+        return setString(vector, index, value, vector.slowPathAccess());
+    }
+
+    @Specialization(guards = {"access.supports(list)", "simpleVector(list)", "!list.isShared()", "isValidIndex(list, index)", "isSingleElement(value)"})
+    protected static Object setList(RList list, int index, Object value,
+                    @Cached("list.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(list)) {
+            access.setListElement(iter, index - 1, value);
+            return list;
+        }
+    }
+
+    @Specialization(replaces = "setList", guards = {"simpleVector(list)", "!list.isShared()", "isValidIndex(list, index)", "isSingleElement(value)"})
+    protected static Object setListGeneric(RList list, int index, Object value) {
+        return setList(list, index, value, list.slowPathAccess());
+    }
+
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    protected RDoubleVector setDoubleIntIndexIntValue(RDoubleVector vector, int index, int value,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            if (RRuntime.isNA(value)) {
+                access.setDouble(iter, index - 1, RRuntime.DOUBLE_NA);
+                vector.setComplete(false);
+            } else {
+                access.setDouble(iter, index - 1, value);
+            }
+            return vector;
+        }
     }
 
-    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
-    protected RDoubleVector setDoubleIntIndexIntValue(RDoubleVector vector, int index, int value) {
-        return vector.updateDataAt(index - 1, value, naCheck);
+    @Specialization(replaces = "setDoubleIntIndexIntValue", guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    protected RDoubleVector setDoubleIntIndexIntValueGeneric(RDoubleVector vector, int index, int value) {
+        return setDoubleIntIndexIntValue(vector, index, value, vector.slowPathAccess());
     }
 
     @SuppressWarnings("unused")
@@ -109,34 +167,90 @@ abstract class UpdateSubscriptSpecial2 extends SubscriptSpecial2Common {
         super(inReplacement);
     }
 
-    private final NACheck naCheck = NACheck.create();
-
     protected abstract Object execute(VirtualFrame frame, Object vec, Object index1, Object index2, Object value);
 
-    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
-    protected RIntVector set(RIntVector vector, int index1, int index2, int value) {
-        return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck);
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    protected RIntVector setInt(RIntVector vector, int index1, int index2, int value,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            access.setInt(iter, matrixIndex(vector, index1, index2), value);
+            if (RRuntime.isNA(value)) {
+                vector.setComplete(false);
+            }
+            return vector;
+        }
     }
 
-    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
-    protected RDoubleVector set(RDoubleVector vector, int index1, int index2, double value) {
-        return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck);
+    @Specialization(replaces = "setInt", guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    protected RIntVector setIntGeneric(RIntVector vector, int index1, int index2, int value) {
+        return setInt(vector, index1, index2, value, vector.slowPathAccess());
     }
 
-    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
-    protected RStringVector set(RStringVector vector, int index1, int index2, String value) {
-        return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck);
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    protected RDoubleVector setDouble(RDoubleVector vector, int index1, int index2, double value,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            access.setDouble(iter, matrixIndex(vector, index1, index2), value);
+            if (RRuntime.isNA(value)) {
+                vector.setComplete(false);
+            }
+            return vector;
+        }
+    }
+
+    @Specialization(replaces = "setDouble", guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    protected RDoubleVector setDoubleGeneric(RDoubleVector vector, int index1, int index2, double value) {
+        return setDouble(vector, index1, index2, value, vector.slowPathAccess());
+    }
+
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    protected RStringVector setString(RStringVector vector, int index1, int index2, String value,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            access.setString(iter, matrixIndex(vector, index1, index2), value);
+            if (RRuntime.isNA(value)) {
+                vector.setComplete(false);
+            }
+            return vector;
+        }
     }
 
-    @Specialization(guards = {"simpleVector(list)", "!list.isShared()", "isValidIndex(list, index1, index2)", "isSingleElement(value)"})
-    protected Object set(RList list, int index1, int index2, Object value) {
-        list.setDataAt(matrixIndex(list, index1, index2), value);
-        return list;
+    @Specialization(replaces = "setString", guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    protected RStringVector setStringGeneric(RStringVector vector, int index1, int index2, String value) {
+        return setString(vector, index1, index2, value, vector.slowPathAccess());
+    }
+
+    @Specialization(guards = {"access.supports(list)", "simpleVector(list)", "!list.isShared()", "isValidIndex(list, index1, index2)", "isSingleElement(value)"})
+    protected Object setList(RList list, int index1, int index2, Object value,
+                    @Cached("list.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(list)) {
+            access.setListElement(iter, matrixIndex(list, index1, index2), value);
+            return list;
+        }
+    }
+
+    @Specialization(replaces = "setList", guards = {"simpleVector(list)", "!list.isShared()", "isValidIndex(list, index1, index2)", "isSingleElement(value)"})
+    protected Object setListGeneric(RList list, int index1, int index2, Object value) {
+        return setList(list, index1, index2, value, list.slowPathAccess());
+    }
+
+    @Specialization(guards = {"access.supports(vector)", "simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    protected RDoubleVector setDoubleIntIndexIntValue(RDoubleVector vector, int index1, int index2, int value,
+                    @Cached("vector.access()") VectorAccess access) {
+        try (VectorAccess.RandomIterator iter = access.randomAccess(vector)) {
+            if (RRuntime.isNA(value)) {
+                access.setDouble(iter, matrixIndex(vector, index1, index2), RRuntime.DOUBLE_NA);
+                vector.setComplete(false);
+            } else {
+                access.setDouble(iter, matrixIndex(vector, index1, index2), value);
+            }
+            return vector;
+        }
     }
 
-    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
-    protected RDoubleVector setDoubleIntIndexIntValue(RDoubleVector vector, int index1, int index2, int value) {
-        return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck);
+    @Specialization(replaces = "setDoubleIntIndexIntValue", guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    protected RDoubleVector setDoubleIntIndexIntValueGeneric(RDoubleVector vector, int index1, int index2, int value) {
+        return setDoubleIntIndexIntValue(vector, index1, index2, value, vector.slowPathAccess());
     }
 
     @SuppressWarnings("unused")
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
index b42c2d6f77235b2467e3710f84f488c19e996cd0..571186d79b9328ea8874562ce80a7631030c93f8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
@@ -108,10 +108,6 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
         NativeDataAccess.setData(this, (double[]) store, index, value.getRealPart(), value.getImaginaryPart());
     }
 
-    public void setDataAt(int index, RComplex value) {
-        NativeDataAccess.setData(this, data, index, value.getRealPart(), value.getImaginaryPart());
-    }
-
     @Override
     public RComplex getDataAt(int index) {
         return NativeDataAccess.getData(this, data, index);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
index e37787fd868e78c8d4c0f6523e10dbc293eb290d..a5192a138d12f15ee65efe76ba67c2ba134563b9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
@@ -103,10 +103,6 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
         NativeDataAccess.setData(this, (double[]) store, index, value);
     }
 
-    public void setDataAt(int index, double value) {
-        NativeDataAccess.setData(this, data, index, value);
-    }
-
     @Override
     public double getDataAt(Object store, int index) {
         assert data == store;
@@ -159,7 +155,7 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
         return RDataFactory.createDoubleVector(getReadonlyData(), isComplete(), newDimensions);
     }
 
-    public RDoubleVector updateDataAt(int index, double value, NACheck valueNACheck) {
+    private RDoubleVector updateDataAt(int index, double value, NACheck valueNACheck) {
         assert !this.isShared();
         NativeDataAccess.setData(this, data, index, value);
         if (valueNACheck.check(value)) {
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 17a03fc109ffdb06804919ad7e20376ae49d0f08..a1c914ba0471bb2c976917dd7a552834faaac70d 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
@@ -103,10 +103,6 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
         NativeDataAccess.setData(this, (int[]) store, index, value);
     }
 
-    public void setDataAt(int index, int value) {
-        NativeDataAccess.setData(this, data, index, value);
-    }
-
     @Override
     protected RIntVector internalCopy() {
         if (data != null) {
@@ -162,7 +158,7 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
         return RDataFactory.createIntVector(getReadonlyData(), isComplete(), newDimensions);
     }
 
-    public RIntVector updateDataAt(int index, int value, NACheck valueNACheck) {
+    private RIntVector updateDataAt(int index, int value, NACheck valueNACheck) {
         assert !this.isShared();
 
         NativeDataAccess.setData(this, data, index, value);
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 8e097a7a97a430f0e34301f0e884ae43b44e47d4..c130c384d37a62866e9f11c537633b6db9811aa4 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
@@ -99,10 +99,6 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
         NativeDataAccess.setData(this, (byte[]) store, index, value);
     }
 
-    public void setDataAt(int index, byte value) {
-        NativeDataAccess.setData(this, data, index, value);
-    }
-
     @Override
     public byte getDataAt(Object store, int index) {
         assert data == store;
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 8da699c972bc7448564d0178c33d9e7079b15c40..f1587fd6c7a2c971313c5e27bf4cd9aa9c437881 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
@@ -101,10 +101,6 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
         NativeDataAccess.setData(this, (byte[]) store, index, value);
     }
 
-    public void setRawDataAt(int index, byte value) {
-        NativeDataAccess.setData(this, data, index, value);
-    }
-
     @Override
     protected RRawVector internalCopy() {
         if (data != null) {
@@ -147,7 +143,7 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
         return this;
     }
 
-    public RRawVector updateDataAt(int index, RRaw value) {
+    private RRawVector updateDataAt(int index, RRaw value) {
         assert !this.isShared();
         NativeDataAccess.setData(this, data, index, value.getValue());
         return this;
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 ee59d39da0552ac2d5483e9b28c762e12bbbfcf0..b5ec016fbbbd0270999a9a3cc73f33c545d9d322 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
@@ -82,10 +82,6 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
         ((String[]) store)[index] = value;
     }
 
-    public void setDataAt(int index, String value) {
-        data[index] = value;
-    }
-
     @Override
     public String getDataAt(Object store, int index) {
         assert data == store;
@@ -132,7 +128,7 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
         return data[i];
     }
 
-    public RStringVector updateDataAt(int i, String right, NACheck rightNACheck) {
+    private RStringVector updateDataAt(int i, String right, NACheck rightNACheck) {
         if (this.isShared()) {
             throw RInternalError.shouldNotReachHere("update shared vector");
         }
@@ -147,7 +143,6 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
     @Override
     public RStringVector updateDataAtAsObject(int i, Object o, NACheck naCheck) {
         return updateDataAt(i, (String) o, naCheck);
-
     }
 
     private String[] copyResizedData(int size, String fill) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 68c0f9b81be958762a9e3d56baf9cc788e57433e..9077e094237b6506c1324fd97ddd554b386c8e36 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -77543,6 +77543,46 @@ Error in vector(character()) : invalid 'mode' argument
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorConstructor#
 #{ x<-as.vector(3); y<-vector(length=x) }
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorNASubscript#
+#v <- as.integer(c(1, 2)); v[1]<-NA_integer_; v
+[1] NA  2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorNASubscript#
+#v <- as.integer(c(1, 2, 3, 4)); dim(v)<-c(2,2); v[1, 1]<-NA_integer_; v
+     [,1] [,2]
+[1,]   NA    3
+[2,]    2    4
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorNASubscript#
+#v <- c('a', 'b'); v[1]<-NA_character_; v
+[1] NA  "b"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorNASubscript#
+#v <- c('a', 'b', 'c', 'd'); dim(v)<-c(2,2); v[1, 1]<-NA_character_; v
+     [,1] [,2]
+[1,] NA   "c"
+[2,] "b"  "d"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorNASubscript#
+#v <- c(1, 2); v[1]<-NA_integer_; v
+[1] NA  2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorNASubscript#
+#v <- c(1, 2); v[1]<-NA_real_; v
+[1] NA  2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorNASubscript#
+#v <- c(1, 2, 3, 4); dim(v)<-c(2,2); v[1, 1]<-NA_integer_; v
+     [,1] [,2]
+[1,]   NA    3
+[2,]    2    4
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorNASubscript#
+#v <- c(1, 2, 3, 4); dim(v)<-c(2,2); v[1, 1]<-NA_real_; v
+     [,1] [,2]
+[1,]   NA    3
+[2,]    2    4
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorWithPairlist#
 #vector('pairlist', 0)
 NULL
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vector.java
index e218f7e8d356838608ffdff845acebc860915c12..bd5cb7aa15f2b5656ea65350f365e76eb82c3e04 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vector.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vector.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -77,4 +77,17 @@ public class TestBuiltin_vector extends TestBase {
         assertEval("vector('pairlist', 0)");
         assertEval("vector('pairlist', 3)");
     }
+
+    @Test
+    public void testVectorNASubscript() {
+        assertEval("v <- as.integer(c(1, 2)); v[1]<-NA_integer_; v");
+        assertEval("v <- c(1, 2); v[1]<-NA_real_; v");
+        assertEval("v <- c('a', 'b'); v[1]<-NA_character_; v");
+        assertEval("v <- c(1, 2); v[1]<-NA_integer_; v");
+
+        assertEval("v <- as.integer(c(1, 2, 3, 4)); dim(v)<-c(2,2); v[1, 1]<-NA_integer_; v");
+        assertEval("v <- c(1, 2, 3, 4); dim(v)<-c(2,2); v[1, 1]<-NA_real_; v");
+        assertEval("v <- c('a', 'b', 'c', 'd'); dim(v)<-c(2,2); v[1, 1]<-NA_character_; v");
+        assertEval("v <- c(1, 2, 3, 4); dim(v)<-c(2,2); v[1, 1]<-NA_integer_; v");
+    }
 }