diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArray.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArray.java
deleted file mode 100644
index 9819981f46b37646dc0a11b1a44640c4cbcd2055..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArray.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.ffi.impl.interop;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RTruffleObject;
-
-/**
- * Handles the requirement that the R FFI sees "logical" arrays as {@code int[]} but the actual
- * array in FastR is represented as {@code byte[]}.
- */
-public final class NativeLogicalArray extends NativeNACheck<byte[]> implements RTruffleObject {
-
-    public final byte[] data;
-
-    public NativeLogicalArray(Object obj, byte[] value) {
-        super(obj);
-        this.data = value;
-    }
-
-    int read(int index) {
-        return data[index] & 0xFF;
-    }
-
-    void write(int index, int value) {
-        byte newVal;
-        if (value == RRuntime.INT_NA) {
-            newVal = RRuntime.LOGICAL_NA;
-            setIncomplete();
-        } else {
-            newVal = (byte) (value & 0xFF);
-        }
-        data[index] = newVal;
-    }
-
-    @Override
-    public ForeignAccess getForeignAccess() {
-        return NativeLogicalArrayMRForeign.ACCESS;
-    }
-
-    @Override
-    @TruffleBoundary
-    protected void allocateNative() {
-        throw RInternalError.shouldNotReachHere();
-    }
-
-    @Override
-    protected void copyBackFromNative() {
-        throw RInternalError.shouldNotReachHere();
-    }
-}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArrayMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArrayMR.java
deleted file mode 100644
index 6cadbb1a64d93009b616adbd20d40f59a7cb2ba7..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArrayMR.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.ffi.impl.interop;
-
-import com.oracle.truffle.api.interop.CanResolve;
-import com.oracle.truffle.api.interop.MessageResolution;
-import com.oracle.truffle.api.interop.Resolve;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.nodes.Node;
-
-@MessageResolution(receiverType = NativeLogicalArray.class)
-public class NativeLogicalArrayMR {
-    @Resolve(message = "READ")
-    public abstract static class NLAReadNode extends Node {
-        protected int access(NativeLogicalArray receiver, int index) {
-            return receiver.read(index);
-        }
-    }
-
-    @Resolve(message = "WRITE")
-    public abstract static class NLAWriteNode extends Node {
-        protected Object access(NativeLogicalArray receiver, int index, int value) {
-            receiver.write(index, value);
-            return value;
-        }
-    }
-
-    @Resolve(message = "GET_SIZE")
-    public abstract static class NLAGetSizeNode extends Node {
-        protected int access(NativeLogicalArray receiver) {
-            return receiver.data.length;
-        }
-    }
-
-    @CanResolve
-    public abstract static class NLACheck extends Node {
-        protected static boolean test(TruffleObject receiver) {
-            return receiver instanceof NativeLogicalArray;
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java
index 50f798fb1baf60f2b4395d7f9e87114bc83a36a6..2852cded38785fd95670e9fa2ccfa8b3c48d6d8b 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java
@@ -30,16 +30,16 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
-import com.oracle.truffle.r.ffi.impl.interop.NativeDoubleArray;
-import com.oracle.truffle.r.ffi.impl.interop.NativeIntegerArray;
-import com.oracle.truffle.r.ffi.impl.interop.NativeNACheck;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.ffi.DownCallNodeFactory;
 import com.oracle.truffle.r.runtime.ffi.NativeFunction;
+import com.oracle.truffle.r.runtime.ffi.interop.NativeArray;
 import com.oracle.truffle.r.runtime.ffi.interop.NativeCharArray;
+import com.oracle.truffle.r.runtime.ffi.interop.NativeDoubleArray;
+import com.oracle.truffle.r.runtime.ffi.interop.NativeIntegerArray;
 import com.oracle.truffle.r.runtime.ffi.interop.NativePointer;
 
 final class TruffleLLVM_DownCallNodeFactory extends DownCallNodeFactory {
@@ -93,9 +93,10 @@ final class TruffleLLVM_DownCallNodeFactory extends DownCallNodeFactory {
             @Override
             @ExplodeLoop
             protected void afterCall(long before, NativeFunction fn, TruffleObject target, Object[] args) {
-                for (Object obj : args) {
-                    if (obj instanceof NativeNACheck<?>) {
-                        ((NativeNACheck<?>) obj).close();
+                for (int i = 0; i < args.length; i++) {
+                    Object obj = args[i];
+                    if (obj instanceof NativeArray<?>) {
+                        ((NativeArray<?>) obj).refresh();
                     }
                 }
             }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DownCallNodeFactory.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DownCallNodeFactory.java
index a4da40eb926c59d646d8a52f5410db6e699843a1..912485e008a7cb6098409dc3c4dee2f5dd3c1ae8 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DownCallNodeFactory.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DownCallNodeFactory.java
@@ -26,10 +26,10 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
-import com.oracle.truffle.r.ffi.impl.interop.NativeNACheck;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.DownCallNodeFactory;
 import com.oracle.truffle.r.runtime.ffi.NativeFunction;
+import com.oracle.truffle.r.runtime.ffi.interop.NativeArray;
 import com.oracle.truffle.r.runtime.ffi.interop.NativeUInt8Array;
 
 public final class TruffleNFI_DownCallNodeFactory extends DownCallNodeFactory {
@@ -95,8 +95,8 @@ public final class TruffleNFI_DownCallNodeFactory extends DownCallNodeFactory {
 
                 for (Object obj : args) {
                     // TODO: can this ever happen in NFI?
-                    if (obj instanceof NativeNACheck<?>) {
-                        ((NativeNACheck<?>) obj).close();
+                    if (obj instanceof NativeArray<?>) {
+                        ((NativeArray<?>) obj).refresh();
                     }
                 }
             }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Utils.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Utils.java
index 3959906169e0b52656d406d18f2e84f176d96d92..7777937fac600b5bebf7a3a1f2b81b15b0339a96 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Utils.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Utils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -24,7 +24,7 @@ package com.oracle.truffle.r.ffi.impl.nfi;
 
 import java.nio.charset.StandardCharsets;
 
-import com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter;
+import com.oracle.truffle.r.runtime.ffi.interop.UnsafeAdapter;
 
 public class TruffleNFI_Utils {
     static String getString(long address, int len) {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/TryRfEvalNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/TryRfEvalNode.java
index 7783c59bf988b1f200e47ac52d89c47a7a878689..d67afc7497c75b1ff3788a730821f731a2c705a8 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/TryRfEvalNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/TryRfEvalNode.java
@@ -29,10 +29,10 @@ import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter;
 import com.oracle.truffle.r.runtime.RErrorHandling;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.ffi.interop.UnsafeAdapter;
 
 public final class TryRfEvalNode extends FFIUpCallNode.Arg4 {
     @Child private RfEvalNode rfEvalNode = RfEvalNode.create();
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeNACheck.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeArray.java
similarity index 65%
rename from com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeNACheck.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeArray.java
index 35bc45761689f013ca17b2c54eb32b58582092b0..32c75fbde5f9f83c5e45af44a3d53c1166d32cc1 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeNACheck.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeArray.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,40 +20,24 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.ffi.impl.interop;
+package com.oracle.truffle.r.runtime.ffi.interop;
 
-import static com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter.UNSAFE;
+import static com.oracle.truffle.r.runtime.ffi.interop.UnsafeAdapter.UNSAFE;
 
-import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
 
-/**
- * Handles the {@code complete} flag in an {@link RVector} when an {@code NA} value is assigned in
- * native code.
- *
- */
-public abstract class NativeNACheck<T> implements AutoCloseable {
-
-    private final RVector<?> vec;
+public abstract class NativeArray<T> implements RTruffleObject {
 
     /**
      * If the array escapes the Truffle world via {@link #convertToNative()}, this value will be
      * non-zero and is used exclusively thereafter.
      */
     protected long nativeAddress;
+    protected T array;
+    @SuppressWarnings("unused") private NativeFinalizer finalizer;
 
-    protected NativeNACheck(Object x) {
-        if (x instanceof RVector<?>) {
-            vec = (RVector<?>) x;
-        } else {
-            // scalar (length 1) vector or no associated R object
-            vec = null;
-        }
-    }
-
-    public void setIncomplete() {
-        if (vec != null) {
-            vec.setComplete(false);
-        }
+    protected NativeArray(T array) {
+        this.array = array;
     }
 
     protected abstract void allocateNative();
@@ -62,15 +46,29 @@ public abstract class NativeNACheck<T> implements AutoCloseable {
 
     final long convertToNative() {
         if (nativeAddress == 0) {
-            allocateNative();
+            finalizer = new NativeFinalizer();
         }
         return nativeAddress;
     }
 
-    @Override
-    public final void close() {
+    public final T refresh() {
         if (nativeAddress != 0) {
             copyBackFromNative();
+        }
+        return array;
+    }
+
+    private final class NativeFinalizer {
+
+        {
+            allocateNative();
+            assert nativeAddress != 0;
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            assert nativeAddress != 0;
+            super.finalize();
             UNSAFE.freeMemory(nativeAddress);
         }
     }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArray.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeDoubleArray.java
similarity index 66%
rename from com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArray.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeDoubleArray.java
index 05267fdf39e9010c930420429531a0e73bfa315c..d4919d9382e5448a0b81f3b9e54d176ef82aaf54 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArray.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeDoubleArray.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,34 +20,26 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.ffi.impl.interop;
+package com.oracle.truffle.r.runtime.ffi.interop;
 
-import static com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter.UNSAFE;
+import static com.oracle.truffle.r.runtime.ffi.interop.UnsafeAdapter.UNSAFE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.r.runtime.data.RTruffleObject;
 
 import sun.misc.Unsafe;
 
-public final class NativeDoubleArray extends NativeNACheck<double[]> implements RTruffleObject {
-
-    public final double[] value;
-
-    public NativeDoubleArray(Object obj, double[] value) {
-        super(obj);
-        this.value = value;
-    }
+public final class NativeDoubleArray extends NativeArray<double[]> {
 
     public NativeDoubleArray(double[] value) {
-        this(null, value);
+        super(value);
     }
 
     double read(int index) {
         if (nativeAddress != 0) {
             return UNSAFE.getDouble(nativeAddress + index * Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
         } else {
-            return value[index];
+            return array[index];
         }
     }
 
@@ -55,22 +47,22 @@ public final class NativeDoubleArray extends NativeNACheck<double[]> implements
         if (nativeAddress != 0) {
             UNSAFE.putDouble(nativeAddress + index * Unsafe.ARRAY_DOUBLE_INDEX_SCALE, nv);
         } else {
-            value[index] = nv;
+            array[index] = nv;
         }
     }
 
     @Override
     @TruffleBoundary
     protected void allocateNative() {
-        nativeAddress = UNSAFE.allocateMemory(value.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
-        UNSAFE.copyMemory(value, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, null, nativeAddress, value.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
+        nativeAddress = UNSAFE.allocateMemory(array.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
+        UNSAFE.copyMemory(array, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, null, nativeAddress, array.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
     }
 
     @Override
     @TruffleBoundary
-    protected void copyBackFromNative() {
+    public void copyBackFromNative() {
         // copy back
-        UNSAFE.copyMemory(null, nativeAddress, value, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, value.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
+        UNSAFE.copyMemory(null, nativeAddress, array, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, array.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArrayMR.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeDoubleArrayMR.java
similarity index 73%
rename from com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArrayMR.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeDoubleArrayMR.java
index 556fd3763ce994eeafc31337d4e60524c8f521b2..c83b242556e9b76f634e188fe9fa3228fbc8934e 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArrayMR.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeDoubleArrayMR.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,14 +20,13 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.ffi.impl.interop;
+package com.oracle.truffle.r.runtime.ffi.interop;
 
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RRuntime;
 
 @MessageResolution(receiverType = NativeDoubleArray.class)
 public class NativeDoubleArrayMR {
@@ -42,33 +41,15 @@ public class NativeDoubleArrayMR {
     @Resolve(message = "WRITE")
     public abstract static class NDAWriteNode extends Node {
         protected double access(NativeDoubleArray receiver, int index, double value) {
-            if (value == RRuntime.DOUBLE_NA) {
-                receiver.setIncomplete();
-            }
             receiver.write(index, value);
             return value;
         }
     }
 
-    @Resolve(message = "IS_POINTER")
-    public abstract static class NDAIsPointer extends Node {
-
-        public Object access(@SuppressWarnings("unused") NativeDoubleArray receiver) {
-            return true;
-        }
-    }
-
-    @Resolve(message = "AS_POINTER")
-    public abstract static class NDAAsPointerNode extends Node {
-        protected long access(NativeDoubleArray receiver) {
-            return receiver.convertToNative();
-        }
-    }
-
     @Resolve(message = "TO_NATIVE")
     public abstract static class NDAToNativeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") NativeDoubleArray receiver) {
-            return this;
+        protected Object access(NativeDoubleArray receiver) {
+            return new DoubleNativePointer(receiver);
         }
     }
 
@@ -79,4 +60,20 @@ public class NativeDoubleArrayMR {
             return receiver instanceof NativeDoubleArray;
         }
     }
+
+    private static final class DoubleNativePointer extends NativePointer {
+        private final NativeDoubleArray nativeDoubleArray;
+
+        private DoubleNativePointer(NativeDoubleArray object) {
+            super(object);
+            this.nativeDoubleArray = object;
+        }
+
+        @Override
+        protected long asPointerImpl() {
+            long result = nativeDoubleArray.convertToNative();
+            return result;
+        }
+    }
+
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArray.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeIntegerArray.java
similarity index 66%
rename from com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArray.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeIntegerArray.java
index 17b238ed20aea5e69543eedfba4d5ac88e5901bf..4c0b846bc1fd84da0f95eca08ad7857e5f7b2cc1 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArray.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeIntegerArray.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,34 +20,26 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.ffi.impl.interop;
+package com.oracle.truffle.r.runtime.ffi.interop;
 
-import static com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter.UNSAFE;
+import static com.oracle.truffle.r.runtime.ffi.interop.UnsafeAdapter.UNSAFE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.r.runtime.data.RTruffleObject;
 
 import sun.misc.Unsafe;
 
-public final class NativeIntegerArray extends NativeNACheck<int[]> implements RTruffleObject {
-
-    public final int[] value;
-
-    public NativeIntegerArray(Object obj, int[] value) {
-        super(obj);
-        this.value = value;
-    }
+public final class NativeIntegerArray extends NativeArray<int[]> {
 
     public NativeIntegerArray(int[] value) {
-        this(null, value);
+        super(value);
     }
 
     int read(int index) {
         if (nativeAddress != 0) {
             return UNSAFE.getInt(nativeAddress + index * Unsafe.ARRAY_INT_INDEX_SCALE);
         } else {
-            return value[index];
+            return array[index];
         }
     }
 
@@ -55,22 +47,22 @@ public final class NativeIntegerArray extends NativeNACheck<int[]> implements RT
         if (nativeAddress != 0) {
             UNSAFE.putInt(nativeAddress + index * Unsafe.ARRAY_INT_INDEX_SCALE, nv);
         } else {
-            value[index] = nv;
+            array[index] = nv;
         }
     }
 
     @Override
     @TruffleBoundary
     protected void allocateNative() {
-        nativeAddress = UNSAFE.allocateMemory(value.length * Unsafe.ARRAY_INT_INDEX_SCALE);
-        UNSAFE.copyMemory(value, Unsafe.ARRAY_INT_BASE_OFFSET, null, nativeAddress, value.length * Unsafe.ARRAY_INT_INDEX_SCALE);
+        nativeAddress = UNSAFE.allocateMemory(array.length * Unsafe.ARRAY_INT_INDEX_SCALE);
+        UNSAFE.copyMemory(array, Unsafe.ARRAY_INT_BASE_OFFSET, null, nativeAddress, array.length * Unsafe.ARRAY_INT_INDEX_SCALE);
     }
 
     @Override
     @TruffleBoundary
-    protected void copyBackFromNative() {
+    public void copyBackFromNative() {
         // copy back
-        UNSAFE.copyMemory(null, nativeAddress, value, Unsafe.ARRAY_INT_BASE_OFFSET, value.length * Unsafe.ARRAY_INT_INDEX_SCALE);
+        UNSAFE.copyMemory(null, nativeAddress, array, Unsafe.ARRAY_INT_BASE_OFFSET, array.length * Unsafe.ARRAY_INT_INDEX_SCALE);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArrayMR.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeIntegerArrayMR.java
similarity index 91%
rename from com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArrayMR.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeIntegerArrayMR.java
index aa6edfb67d5892b158eb7ef574b8a3dc00a05fcd..f82da7f56a003c13c9cfff81d5e99c9f1df0718f 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArrayMR.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeIntegerArrayMR.java
@@ -20,15 +20,13 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.ffi.impl.interop;
+package com.oracle.truffle.r.runtime.ffi.interop;
 
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.ffi.interop.NativePointer;
 
 @MessageResolution(receiverType = NativeIntegerArray.class)
 public class NativeIntegerArrayMR {
@@ -43,9 +41,6 @@ public class NativeIntegerArrayMR {
     @Resolve(message = "WRITE")
     public abstract static class NIAWriteNode extends Node {
         protected int access(NativeIntegerArray receiver, int index, int value) {
-            if (value == RRuntime.INT_NA) {
-                receiver.setIncomplete();
-            }
             receiver.write(index, value);
             return value;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeRawArrayMR.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeRawArrayMR.java
index 21d367ac68ef86d580f089f60c8d168cfbf98a90..94f567c11bfb2a9f102cf259a9f76f7078b58950 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeRawArrayMR.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeRawArrayMR.java
@@ -33,14 +33,14 @@ public class NativeRawArrayMR {
     @Resolve(message = "READ")
     public abstract static class NRAReadNode extends Node {
         protected byte access(NativeRawArray receiver, int index) {
-            return receiver.bytes[index];
+            return receiver.array[index];
         }
     }
 
     @Resolve(message = "WRITE")
     public abstract static class NRAWriteNode extends Node {
         protected Object access(NativeRawArray receiver, int index, byte value) {
-            receiver.bytes[index] = value;
+            receiver.array[index] = value;
             return value;
         }
     }
@@ -48,7 +48,7 @@ public class NativeRawArrayMR {
     @Resolve(message = "GET_SIZE")
     public abstract static class NRAGetSizeNode extends Node {
         protected int access(NativeRawArray receiver) {
-            return receiver.bytes.length;
+            return receiver.array.length;
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeUInt8Array.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeUInt8Array.java
index 033d78e53b96f2ee582c71c3147a368d23ccb9fe..13a4e965d9b9237bf75687bfce088f778bef76ee 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeUInt8Array.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/NativeUInt8Array.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.runtime.ffi.interop;
 import static com.oracle.truffle.r.runtime.ffi.UnsafeAdapter.UNSAFE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.data.RTruffleObject;
 
 import sun.misc.Unsafe;
 
@@ -40,24 +39,17 @@ import sun.misc.Unsafe;
  * If {@link #fakesNullTermination()} is {@code true}, then {@link #read} returns 0, else it is an
  * error; similar for {@link #write}.
  */
-public abstract class NativeUInt8Array implements RTruffleObject {
+public abstract class NativeUInt8Array extends NativeArray<byte[]> {
 
-    public byte[] bytes;
-
-    /**
-     * If the array escapes the Truffle world via {@link #convertToNative()}, this value will be
-     * non-zero and is used exclusively thereafter.
-     */
-    protected long nativeAddress;
     private int effectiveLength;
 
-    protected NativeUInt8Array(byte[] bytes, boolean nullTerminate) {
-        this.bytes = bytes;
-        this.effectiveLength = bytes.length + (nullTerminate ? 1 : 0);
+    protected NativeUInt8Array(byte[] array, boolean nullTerminate) {
+        super(array);
+        this.effectiveLength = array.length + (nullTerminate ? 1 : 0);
     }
 
     public boolean fakesNullTermination() {
-        return bytes.length != effectiveLength;
+        return array.length != effectiveLength;
     }
 
     private void checkNativeIndex(int index) {
@@ -71,10 +63,10 @@ public abstract class NativeUInt8Array implements RTruffleObject {
             checkNativeIndex(index);
             UNSAFE.putByte(nativeAddress + index, value);
         } else {
-            if (index == bytes.length && fakesNullTermination()) {
+            if (index == array.length && fakesNullTermination()) {
                 // ignore
             } else {
-                bytes[index] = value;
+                array[index] = value;
             }
         }
     }
@@ -84,48 +76,44 @@ public abstract class NativeUInt8Array implements RTruffleObject {
             checkNativeIndex(index);
             return UNSAFE.getByte(nativeAddress + index);
         } else {
-            if (index == bytes.length && fakesNullTermination()) {
+            if (index == array.length && fakesNullTermination()) {
                 return (byte) 0;
             }
-            return bytes[index];
+            return array[index];
         }
     }
 
     int getSize() {
-        return bytes.length;
-    }
-
-    long convertToNative() {
-        if (nativeAddress == 0) {
-            allocateNative();
-        }
-        return nativeAddress;
+        return array.length;
     }
 
     @TruffleBoundary
-    private void allocateNative() {
+    @Override
+    protected final void allocateNative() {
         nativeAddress = UNSAFE.allocateMemory(effectiveLength);
-        UNSAFE.copyMemory(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, nativeAddress, bytes.length);
+        UNSAFE.copyMemory(array, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, nativeAddress, array.length);
         if (fakesNullTermination()) {
-            UNSAFE.putByte(nativeAddress + bytes.length, (byte) 0);
+            UNSAFE.putByte(nativeAddress + array.length, (byte) 0);
         }
     }
 
     public byte[] getValue() {
         if (nativeAddress != 0) {
-            copyBackFromNative(bytes);
+            copyBackFromNative();
         }
-        return bytes;
+        return array;
     }
 
     public void setValue(byte[] newBytes, boolean isNullTerminated) {
-        bytes = newBytes;
-        effectiveLength = isNullTerminated ? bytes.length + 1 : bytes.length;
+        array = newBytes;
+        effectiveLength = isNullTerminated ? array.length + 1 : array.length;
     }
 
     @TruffleBoundary
-    private void copyBackFromNative(byte[] target) {
+    @Override
+    public void copyBackFromNative() {
         // copy back
-        UNSAFE.copyMemory(null, nativeAddress, target, Unsafe.ARRAY_BYTE_BASE_OFFSET, bytes.length);
+        UNSAFE.copyMemory(null, nativeAddress, array, Unsafe.ARRAY_BYTE_BASE_OFFSET, array.length);
     }
+
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/UnsafeAdapter.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/UnsafeAdapter.java
similarity index 93%
rename from com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/UnsafeAdapter.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/UnsafeAdapter.java
index 413e72ff60ed329f3b683fdd031dd392e730515a..e15c0501e573fa1db8ea8cf016fc615cbd82ef9e 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/UnsafeAdapter.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/interop/UnsafeAdapter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.ffi.impl.interop;
+package com.oracle.truffle.r.runtime.ffi.interop;
 
 import java.lang.reflect.Field;