diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ListMR.java
index a987ca171a446b048e9ca8afe8f211f9081f4a27..8423b27c8ba30c714d015eb667d5e52e9449c84b 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ListMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ListMR.java
@@ -39,7 +39,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.engine.interop.ListMRFactory.ListKeyInfoImplNodeGen;
 import com.oracle.truffle.r.engine.interop.ListMRFactory.ListReadImplNodeGen;
 import com.oracle.truffle.r.engine.interop.ListMRFactory.ListWriteImplNodeGen;
-import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
@@ -120,7 +119,7 @@ public class ListMR {
         @Resolve(message = "TO_NATIVE")
         public abstract static class RListToNativeNode extends Node {
             protected Object access(RTruffleObject receiver) {
-                return toNativePointer(receiver);
+                return NativeDataAccess.toNative(receiver);
             }
         }
 
@@ -218,7 +217,7 @@ public class ListMR {
         @Resolve(message = "TO_NATIVE")
         public abstract static class RExpressionToNativeNode extends Node {
             protected Object access(RTruffleObject receiver) {
-                return toNativePointer(receiver);
+                return NativeDataAccess.toNative(receiver);
             }
         }
 
@@ -310,7 +309,7 @@ public class ListMR {
         @Resolve(message = "TO_NATIVE")
         public abstract static class RPairListToNativeNode extends Node {
             protected Object access(RPairList receiver) {
-                return toNativePointer(receiver);
+                return NativeDataAccess.toNative(receiver);
             }
         }
 
@@ -536,8 +535,4 @@ public class ListMR {
         RStringVector names = getNamesNode.getNames(receiver);
         return names != null ? names : RNull.instance;
     }
-
-    private static Object toNativePointer(RTruffleObject receiver) {
-        return new NativePointer(receiver);
-    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
index a2482be68e27a7e78078c850134e79bdc4f09fc4..5cd19ab664801dd4672e28b25376aa76adc3f57d 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
@@ -47,7 +47,6 @@ import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactoryFactory.V
 import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactoryFactory.VectorKeyInfoRootNodeGen;
 import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactoryFactory.VectorReadImplNodeGen;
 import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactoryFactory.VectorWriteImplNodeGen;
-import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
@@ -347,7 +346,7 @@ public final class RAbstractVectorAccessFactory implements Factory26 {
             @Override
             public Object execute(VirtualFrame frame) {
                 RAbstractVector arg = (RAbstractVector) ForeignAccess.getReceiver(frame);
-                return new NativePointer(arg);
+                return NativeDataAccess.toNative(arg);
             }
         });
     }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
index 71fe7cdf9b9fb8c3b8c987ff6d7145c877eda25f..09fe5cd331eaeab927c936e01614b69858cd8928 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
@@ -41,7 +41,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.engine.interop.REnvironmentMRFactory.REnvironmentKeyInfoImplNodeGen;
 import com.oracle.truffle.r.engine.interop.REnvironmentMRFactory.REnvironmentReadImplNodeGen;
 import com.oracle.truffle.r.engine.interop.REnvironmentMRFactory.REnvironmentWriteImplNodeGen;
-import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
@@ -59,7 +58,7 @@ public class REnvironmentMR {
     @Resolve(message = "TO_NATIVE")
     public abstract static class REnvironmentToNativeNode extends Node {
         protected Object access(REnvironment receiver) {
-            return new NativePointer(receiver);
+            return NativeDataAccess.toNative(receiver);
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
index 790c817810d3ae72898fcb8aaf4816048293a018..1aeb17a752b2504414eceeff9ecfab6ef299734b 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
@@ -32,7 +32,6 @@ 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.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.function.RCallBaseNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -67,7 +66,7 @@ public class RFunctionMR {
     @Resolve(message = "TO_NATIVE")
     public abstract static class RFunctionToNativeNode extends Node {
         protected Object access(RFunction receiver) {
-            return new NativePointer(receiver);
+            return NativeDataAccess.toNative(receiver);
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
index 8b1c680448b02c965f53da984fd2538fbb6373ed..3dc32e487f0a9c8cd3af82c079f3e6af16a34896 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
@@ -35,7 +35,6 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.runtime.data.NativeDataAccess;
@@ -65,7 +64,7 @@ public class RLanguageMR {
     @Resolve(message = "TO_NATIVE")
     public abstract static class RLanguageToNativeNode extends Node {
         protected Object access(RLanguage receiver) {
-            return new NativePointer(receiver);
+            return NativeDataAccess.toNative(receiver);
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
index ab3db61d67cfd0241e8eafec2122a91c0d66b381..51b01c4cd2d6d7822a1a0994a826f854e71cf6ec 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
@@ -36,7 +36,6 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.engine.interop.RPromiseMRFactory.RPromiseKeyInfoImplNodeGen;
 import com.oracle.truffle.r.engine.interop.RPromiseMRFactory.RPromiseReadImplNodeGen;
 import com.oracle.truffle.r.engine.interop.RPromiseMRFactory.RPromiseWriteImplNodeGen;
-import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.NativeDataAccess;
@@ -90,7 +89,7 @@ public class RPromiseMR {
     @Resolve(message = "TO_NATIVE")
     public abstract static class RPromiseToNativeNode extends Node {
         protected Object access(RPromise receiver) {
-            return new NativePointer(receiver);
+            return NativeDataAccess.toNative(receiver);
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java
index f55d81fdefb9e952d1ce4dd18310b1bb4be6530d..4fed921ae442aed2ee89a0f05593466d7963cdbd 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java
@@ -27,7 +27,6 @@ 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.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.runtime.data.NativeDataAccess;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 
@@ -44,7 +43,7 @@ public class RSymbolMR {
     @Resolve(message = "TO_NATIVE")
     public abstract static class RSymbolToNativeNode extends Node {
         protected Object access(RSymbol receiver) {
-            return new NativePointer(receiver);
+            return NativeDataAccess.toNative(receiver);
         }
     }
 
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
index a76e4ee4ebe8b9ccb474c0f7c0684491fb07c4cd..4a8ea1bfe1df35217683f504252afa0a464ed420 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
@@ -67,15 +67,14 @@ import com.oracle.truffle.r.runtime.conn.NativeConnections.NativeRConnection;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RDoubleSequence;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -85,8 +84,6 @@ import com.oracle.truffle.r.runtime.data.RObject;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
-import com.oracle.truffle.r.runtime.data.RRaw;
-import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RSequence;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -105,7 +102,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
-import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.CEntry;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
@@ -514,61 +510,6 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return 0;
     }
 
-    @Override
-    public Object RAW(Object x) {
-        if (x instanceof RRawVector) {
-            return ((RRawVector) x).getDataWithoutCopying();
-        } else if (x instanceof RRaw) {
-            return new byte[]{((RRaw) x).getValue()};
-        } else {
-            throw unimplemented();
-        }
-    }
-
-    @Override
-    public Object LOGICAL(Object x) {
-        if (x instanceof RLogicalVector) {
-            return ((RLogicalVector) x).getDataWithoutCopying();
-        } else if (x instanceof Byte) {
-            return new byte[]{(Byte) x};
-        } else {
-            throw unimplemented();
-        }
-    }
-
-    @Override
-    public Object INTEGER(Object x) {
-        if (x instanceof RIntVector) {
-            return ((RIntVector) x).getDataWithoutCopying();
-        } else if (x instanceof RIntSequence) {
-            return ((RIntSequence) x).materialize().getDataWithoutCopying();
-        } else if (x instanceof Integer) {
-            return new int[]{(Integer) x};
-        } else if (x instanceof RLogicalVector) {
-            RLogicalVector vec = (RLogicalVector) x;
-            int[] result = new int[vec.getLength()];
-            for (int i = 0; i < result.length; i++) {
-                result[i] = vec.getDataAt(i);
-            }
-            return result;
-        } else {
-            guaranteeInstanceOf(x, Byte.class);
-            return new int[]{(Byte) x};
-        }
-    }
-
-    @Override
-    public Object REAL(Object x) {
-        if (x instanceof RDoubleVector) {
-            return ((RDoubleVector) x).getDataWithoutCopying();
-        } else if (x instanceof RDoubleSequence) {
-            return ((RDoubleSequence) x).materialize().getDataWithoutCopying();
-        } else {
-            guaranteeInstanceOf(x, Double.class);
-            return new double[]{(Double) x};
-        }
-    }
-
     @Override
     public Object STRING_ELT(Object x, long i) {
         RAbstractStringVector vector = guaranteeInstanceOf(RRuntime.asAbstractVector(x), RAbstractStringVector.class);
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/CharSXPWrapperMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/CharSXPWrapperMR.java
index 40ac2f5564469d7a6d81c5a642865b957547fa48..a59156ff9f1f76a71dfcc72da433151de9ca80da 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/CharSXPWrapperMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/CharSXPWrapperMR.java
@@ -27,8 +27,8 @@ 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.data.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.data.NativeDataAccess;
-import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 
 @MessageResolution(receiverType = CharSXPWrapper.class)
 public class CharSXPWrapperMR {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/FFI_RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/FFI_RForeignAccessFactoryImpl.java
index d7c09261ed77d45475d3aca1a53df32378bbf30a..18e434a657ac449a53ff211d2adc5bedb54db0e6 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/FFI_RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/FFI_RForeignAccessFactoryImpl.java
@@ -23,8 +23,8 @@
 package com.oracle.truffle.r.ffi.impl.interop;
 
 import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
-import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 
 public class FFI_RForeignAccessFactoryImpl {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java
index 38c36620486a731d86250af493e28ab4bc67a9c0..5c1923299bc8ac43112bb1b16d542ba66a4759af 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java
@@ -30,22 +30,18 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.ffi.impl.common.JavaUpCallsRFFIImpl;
 import com.oracle.truffle.r.ffi.impl.common.RFFIUtils;
 import com.oracle.truffle.r.ffi.impl.interop.NativeCharArray;
-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.NativeLogicalArray;
-import com.oracle.truffle.r.ffi.impl.interop.NativeRawArray;
 import com.oracle.truffle.r.ffi.impl.upcalls.Callbacks;
 import com.oracle.truffle.r.ffi.impl.upcalls.FFIUnwrapNode;
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RScalar;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
-import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.CEntry;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
@@ -87,35 +83,27 @@ public class TruffleLLVM_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
 
     @Override
     public Object RAW(Object x) {
-        byte[] value = (byte[]) super.RAW(x);
-
-        // TODO: this will leak memory if the pointer escapes
-        return new NativeRawArray(value);
+        throw RInternalError.unimplemented();
     }
 
     @Override
     public Object LOGICAL(Object x) {
-        byte[] value = (byte[]) super.LOGICAL(x);
-
-        // TODO: this will leak memory if the pointer escapes
-        return new NativeLogicalArray(x, value);
+        throw RInternalError.unimplemented();
     }
 
     @Override
     public Object INTEGER(Object x) {
-        int[] value = (int[]) super.INTEGER(x);
-
-        // TODO: this will leak memory if the pointer escapes
-        return new NativeIntegerArray(x, value);
+        throw RInternalError.unimplemented();
     }
 
     @Override
     public Object REAL(Object x) {
-        // Special handling in Truffle variant
-        double[] value = (double[]) super.REAL(x);
+        throw RInternalError.unimplemented();
+    }
 
-        // TODO: this will leak memory if the pointer escapes
-        return new NativeDoubleArray(x, value);
+    @Override
+    public Object COMPLEX(Object x) {
+        throw RInternalError.unimplemented();
     }
 
     @Override
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_UpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_UpCallsRFFIImpl.java
index 80a67a01665d7323df703d4a08221b147eac5c69..29aeb45671631c7ce7216a62f079fc0ec4f2c3e0 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_UpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_UpCallsRFFIImpl.java
@@ -25,6 +25,8 @@ package com.oracle.truffle.r.ffi.impl.nfi;
 import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.guaranteeInstanceOf;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
@@ -35,19 +37,22 @@ 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.common.JavaUpCallsRFFIImpl;
+import com.oracle.truffle.r.ffi.impl.nfi.TruffleNFI_UpCallsRFFIImplFactory.VectorWrapperMRFactory.DispatchAllocateNodeGen;
 import com.oracle.truffle.r.ffi.impl.upcalls.FFIUnwrapNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RVector;
-import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.CEntry;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
 import com.oracle.truffle.r.runtime.ffi.DLL.DotSymbol;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
-import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 
 public class TruffleNFI_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
 
@@ -89,17 +94,54 @@ public class TruffleNFI_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
             }
         }
 
+        public abstract static class DispatchAllocate extends Node {
+            public abstract long execute(Object vector);
+
+            @Specialization
+            protected static long get(RIntVector vector) {
+                return vector.allocateNativeContents();
+            }
+
+            @Specialization
+            protected static long get(RLogicalVector vector) {
+                return vector.allocateNativeContents();
+            }
+
+            @Specialization
+            protected static long get(RRawVector vector) {
+                return vector.allocateNativeContents();
+            }
+
+            @Specialization
+            protected static long get(RDoubleVector vector) {
+                return vector.allocateNativeContents();
+            }
+
+            @Specialization
+            protected static long get(RComplexVector vector) {
+                return vector.allocateNativeContents();
+            }
+
+            @Specialization
+            protected static long get(CharSXPWrapper vector) {
+                return vector.allocateNativeContents();
+            }
+
+            @Fallback
+            protected static long get(Object vector) {
+                throw RInternalError.shouldNotReachHere("invalid wrapped object " + vector.getClass().getSimpleName());
+            }
+        }
+
         @Resolve(message = "AS_POINTER")
         public abstract static class IntVectorWrapperNativeAsPointerNode extends Node {
+            @Child private DispatchAllocate dispatch = DispatchAllocateNodeGen.create();
+
             protected long access(VectorWrapper receiver) {
-                RVector<?> v = receiver.vector;
-                if (v instanceof RIntVector) {
-                    return ((RIntVector) v).allocateNativeContents();
-                } else if (v instanceof RLogicalVector) {
-                    return ((RLogicalVector) v).allocateNativeContents();
-                } else {
-                    throw RInternalError.shouldNotReachHere();
-                }
+                long address = dispatch.execute(receiver.vector);
+                // System.out.println(String.format("allocating native buffer for %s at %16x",
+                // receiver.vector.getClass().getSimpleName(), address));
+                return address;
             }
         }
 
@@ -113,9 +155,9 @@ public class TruffleNFI_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
 
     public static final class VectorWrapper implements TruffleObject {
 
-        private final RVector<?> vector;
+        private final Object vector;
 
-        public VectorWrapper(RVector<?> vector) {
+        public VectorWrapper(Object vector) {
             this.vector = vector;
         }
 
@@ -139,43 +181,22 @@ public class TruffleNFI_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
 
     @Override
     public Object REAL(Object x) {
-        long arrayAddress = TruffleNFI_NativeArray.findArray(x);
-        if (arrayAddress == 0) {
-            System.out.println("getting REAL contents");
-            Object array = super.REAL(x);
-            arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.REALSXP);
-        } else {
-            TruffleNFI_Call.returnArrayExisting(SEXPTYPE.REALSXP, arrayAddress);
-        }
-        return x;
-
+        return new VectorWrapper(guaranteeInstanceOf(x, RDoubleVector.class));
     }
 
     @Override
     public Object RAW(Object x) {
-        long arrayAddress = TruffleNFI_NativeArray.findArray(x);
-        if (arrayAddress == 0) {
-            System.out.println("getting RAW contents");
-            Object array = super.RAW(x);
-            arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.RAWSXP);
-        } else {
-            TruffleNFI_Call.returnArrayExisting(SEXPTYPE.RAWSXP, arrayAddress);
-        }
-        return x;
+        return new VectorWrapper(guaranteeInstanceOf(x, RRawVector.class));
+    }
+
+    @Override
+    public Object COMPLEX(Object x) {
+        return new VectorWrapper(guaranteeInstanceOf(x, RComplexVector.class));
     }
 
     @Override
     public Object R_CHAR(Object x) {
-        long arrayAddress = TruffleNFI_NativeArray.findArray(x);
-        if (arrayAddress == 0) {
-            System.out.println("getting R_CHAR contents");
-            CharSXPWrapper charSXP = (CharSXPWrapper) x;
-            Object array = charSXP.getContents().getBytes();
-            arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.CHARSXP);
-        } else {
-            TruffleNFI_Call.returnArrayExisting(SEXPTYPE.CHARSXP, arrayAddress);
-        }
-        return x;
+        return new VectorWrapper(guaranteeInstanceOf(x, CharSXPWrapper.class));
     }
 
     @Override
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsCharNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsCharNode.java
index e015164f75cdff7ecc6f132a7d5ae63a0ac0aecb..0566ba1618b1605e69f6648e1b88480106034383 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsCharNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsCharNode.java
@@ -29,11 +29,11 @@ import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 
 @TypeSystemReference(RTypes.class)
 public abstract class AsCharNode extends FFIUpCallNode.Arg1 {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java
index b4e1b39d568d6586c7c2ebcb9ae251cb0039956a..6d7d2f2c571aa8bfcf848a11ae41e5e9bf295a12 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java
@@ -39,13 +39,13 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctionsFactory.S
 import com.oracle.truffle.r.nodes.objects.NewObject;
 import com.oracle.truffle.r.nodes.objects.NewObjectNodeGen;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 
 public final class MiscNodes {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIUnwrapNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIUnwrapNode.java
index 2fb8d8a0c9e734a9d4e4d80bdb29be20b79e537f..d1228b6459c9a1d9e1375cbd1a3503b5100b8eb7 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIUnwrapNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIUnwrapNode.java
@@ -34,6 +34,10 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.NativeDataAccess;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
 
+/**
+ * Unwraps a value that is arriving from the native side. This unwrapping should only happen for
+ * arguments and return values that represent R data structures, not for primitive values.
+ */
 public final class FFIUnwrapNode extends Node {
 
     @Child private Node isPointer;
@@ -45,20 +49,6 @@ public final class FFIUnwrapNode extends Node {
     private final BranchProfile isRTruffleObject = BranchProfile.create();
     private final BranchProfile isNonBoxed = BranchProfile.create();
 
-    /**
-     * There are three possibilities as enumerated below.
-     * <ul>
-     * <li>For an {@link RTruffleObject} there is nothing to do, and indeed, calling {@code unbox}
-     * would be disastrous, as that means, e.g., for a RVector, extract the first element!</li>
-     * <li>Or we could get a {@code TruffleObject} from another language domain, e.g a
-     * {@code JavaObject} that wraps, e.g., an {@code Integer}. Such a value has to be unboxed.
-     * Similarly a {@code NativePointer} encoding, e.g., a C char array. One special case in the
-     * LLVM implementation is {@code NativePointer} that represents an object stored to memory,
-     * which requires a lookup (and not an {@code UNBOX}).</li>
-     * <li>We could also get a plain {@link Integer} or similar type in which case there is nothing
-     * to do.</li>
-     * </ul>
-     */
     public Object execute(Object x) {
         if (x instanceof RTruffleObject) {
             isRTruffleObject.enter();
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
index 72cd7552628087620e9d38bccb37f5ef80f9d3a2..0f495700d653bc750dcd1747e33d3483b137f0ee 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
@@ -158,6 +158,8 @@ public interface StdUpCallsRFFI {
 
     Object REAL(Object x);
 
+    Object COMPLEX(Object x);
+
     Object STRING_ELT(Object x, long i);
 
     Object VECTOR_ELT(Object x, long i);
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
index f3a5c2850db990360e88efb8c4b24c63d3613a7a..396ece126bdc87f7cabca9d5bfd138b4c9dfb565 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
@@ -67,97 +67,97 @@
 // R_GlobalEnv et al are not a variables in FASTR as they are RContext specific
 SEXP FASTR_R_GlobalEnv() {
     TRACE0();
-	return ((call_R_GlobalEnv) callbacks[R_GlobalEnv_x])();
+    return ((call_R_GlobalEnv) callbacks[R_GlobalEnv_x])();
 }
 
 SEXP FASTR_R_BaseEnv() {
     TRACE0();
-	return ((call_R_BaseEnv) callbacks[R_BaseEnv_x])();
+    return ((call_R_BaseEnv) callbacks[R_BaseEnv_x])();
 }
 
 SEXP FASTR_R_BaseNamespace() {
     TRACE0();
-	return ((call_R_BaseNamespace) callbacks[R_BaseNamespace_x])();
+    return ((call_R_BaseNamespace) callbacks[R_BaseNamespace_x])();
 }
 
 SEXP FASTR_R_NamespaceRegistry() {
     TRACE0();
-	return ((call_R_NamespaceRegistry) callbacks[R_NamespaceRegistry_x])();
+    return ((call_R_NamespaceRegistry) callbacks[R_NamespaceRegistry_x])();
 }
 
 CTXT FASTR_GlobalContext() {
     TRACE0();
-	return ((call_R_GlobalContext) callbacks[R_GlobalContext_x])();
+    return ((call_R_GlobalContext) callbacks[R_GlobalContext_x])();
 }
 
 Rboolean FASTR_R_Interactive() {
     TRACE0();
-	return (int) ((call_R_Interactive) callbacks[R_Interactive_x])();
+    return (int) ((call_R_Interactive) callbacks[R_Interactive_x])();
 }
 
 SEXP CAR(SEXP e) {
     TRACE1(e);
-	return ((call_CAR) callbacks[CAR_x])(e);
+    return ((call_CAR) callbacks[CAR_x])(e);
 }
 
 SEXP CDR(SEXP e) {
     TRACE1(e);
-	return ((call_CDR) callbacks[CDR_x])(e);
+    return ((call_CDR) callbacks[CDR_x])(e);
 }
 
 int LENGTH(SEXP x) {
     TRACE1(x);
-	return ((call_LENGTH) callbacks[LENGTH_x])(x);
+    return ((call_LENGTH) callbacks[LENGTH_x])(x);
 }
 
 SEXP Rf_ScalarString(SEXP value) {
     TRACE1(value);
-	return ((call_Rf_ScalarString) callbacks[Rf_ScalarString_x])(value);
+    return ((call_Rf_ScalarString) callbacks[Rf_ScalarString_x])(value);
 }
 
 SEXP Rf_mkString(const char *s) {
     TRACE0();
-	return ScalarString(Rf_mkChar(s));
+    return ScalarString(Rf_mkChar(s));
 }
 
 void Rf_gsetVar(SEXP symbol, SEXP value, SEXP rho) {
     TRACE0();
-	((call_Rf_gsetVar) callbacks[Rf_gsetVar_x])(symbol, value, rho);
+    ((call_Rf_gsetVar) callbacks[Rf_gsetVar_x])(symbol, value, rho);
 }
 
 SEXP Rf_coerceVector(SEXP x, SEXPTYPE mode) {
     TRACE0();
-	return ((call_Rf_coerceVector) callbacks[Rf_coerceVector_x])(x, mode);
+    return ((call_Rf_coerceVector) callbacks[Rf_coerceVector_x])(x, mode);
 }
 
 SEXP Rf_cons(SEXP car, SEXP cdr) {
     TRACE0();
-	return ((call_Rf_cons) callbacks[Rf_cons_x])(car, cdr);
+    return ((call_Rf_cons) callbacks[Rf_cons_x])(car, cdr);
 }
 
 SEXP Rf_GetOption1(SEXP tag) {
     TRACE0();
-	return ((call_Rf_GetOption1) callbacks[Rf_GetOption1_x])(tag);
+    return ((call_Rf_GetOption1) callbacks[Rf_GetOption1_x])(tag);
 }
 
 SEXP Rf_mkChar(const char *x) {
     TRACE0();
-	return Rf_mkCharLenCE(x, strlen(x), CE_NATIVE);
+    return Rf_mkCharLenCE(x, strlen(x), CE_NATIVE);
 }
 
 SEXP Rf_mkCharCE(const char *x, cetype_t y) {
     TRACE0();
-	return Rf_mkCharLenCE(x, strlen(x), y);
+    return Rf_mkCharLenCE(x, strlen(x), y);
 }
 
 SEXP Rf_mkCharLen(const char *x, int y) {
     TRACE0();
-	return Rf_mkCharLenCE(x, y, CE_NATIVE);
+    return Rf_mkCharLenCE(x, y, CE_NATIVE);
 }
 
 SEXP Rf_mkCharLenCE(const char *x, int len, cetype_t enc) {
     TRACE0();
-	return ((call_Rf_mkCharLenCE) callbacks[Rf_mkCharLenCE_x])(ensure_truffle_chararray_n(x, len), len, enc);
+    return ((call_Rf_mkCharLenCE) callbacks[Rf_mkCharLenCE_x])(ensure_truffle_chararray_n(x, len), len, enc);
 }
 
 #define BUFSIZE 8192
@@ -177,48 +177,48 @@ void Rf_errorcall(SEXP x, const char *format, ...) {
 
 void Rf_warningcall(SEXP x, const char *format, ...) {
     TRACE0();
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	((call_Rf_warningcall) callbacks[Rf_warningcall_x])(x, ensure_string(buf));
+    char buf[8192];
+    va_list(ap);
+    va_start(ap,format);
+    Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+    va_end(ap);
+    ((call_Rf_warningcall) callbacks[Rf_warningcall_x])(x, ensure_string(buf));
 }
 
 void Rf_warning(const char *format, ...) {
     TRACE0();
-	char buf[8192];
-	va_list(ap);
-	va_start(ap, format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	((call_Rf_warning) callbacks[Rf_warning_x])(ensure_string(buf));
+    char buf[8192];
+    va_list(ap);
+    va_start(ap, format);
+    Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+    va_end(ap);
+    ((call_Rf_warning) callbacks[Rf_warning_x])(ensure_string(buf));
 }
 
 void Rprintf(const char *format, ...) {
     TRACE0();
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	((call_Rprintf) callbacks[Rprintf_x])(ensure_string(buf));
+    char buf[8192];
+    va_list(ap);
+    va_start(ap,format);
+    Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+    va_end(ap);
+    ((call_Rprintf) callbacks[Rprintf_x])(ensure_string(buf));
 }
 
 void Rf_error(const char *format, ...) {
     TRACE0();
-	// This is a bit tricky. The usual error handling model in Java is "throw RError.error(...)" but
-	// RError.error does quite a lot of stuff including potentially searching for R condition handlers
-	// and, if it finds any, does not return, but throws a different exception than RError.
-	// We definitely need to exit the FFI call and we certainly cannot return to our caller.
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	((call_Rf_error) callbacks[Rf_error_x])(ensure_string(buf));
-	// Should not reach here
-	UNIMPLEMENTED;
+    // This is a bit tricky. The usual error handling model in Java is "throw RError.error(...)" but
+    // RError.error does quite a lot of stuff including potentially searching for R condition handlers
+    // and, if it finds any, does not return, but throws a different exception than RError.
+    // We definitely need to exit the FFI call and we certainly cannot return to our caller.
+    char buf[8192];
+    va_list(ap);
+    va_start(ap,format);
+    Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+    va_end(ap);
+    ((call_Rf_error) callbacks[Rf_error_x])(ensure_string(buf));
+    // Should not reach here
+    UNIMPLEMENTED;
 }
 
 /*
@@ -228,13 +228,13 @@ void Rf_error(const char *format, ...) {
 */
 void REprintf(const char *format, ...) {
     TRACE0();
-	// TODO: determine correct target for this message
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	// TODO
+    // TODO: determine correct target for this message
+    char buf[8192];
+    va_list(ap);
+    va_start(ap,format);
+    Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+    va_end(ap);
+    // TODO
 }
 
 void Rvprintf(const char *format, va_list args) {
@@ -249,17 +249,17 @@ void REvprintf(const char *format, va_list args) {
 
 SEXP Rf_ScalarInteger(int value) {
     TRACE0();
-	return ((call_Rf_ScalarInteger) callbacks[Rf_ScalarInteger_x])(value);
+    return ((call_Rf_ScalarInteger) callbacks[Rf_ScalarInteger_x])(value);
 }
 
 SEXP Rf_ScalarReal(double value) {
     TRACE0();
-	return ((call_Rf_ScalarReal) callbacks[Rf_ScalarDouble_x])(value);
+    return ((call_Rf_ScalarReal) callbacks[Rf_ScalarDouble_x])(value);
 }
 
 SEXP Rf_ScalarLogical(int value) {
     TRACE0();
-	return ((call_Rf_ScalarLogical) callbacks[Rf_ScalarLogical_x])(value);
+    return ((call_Rf_ScalarLogical) callbacks[Rf_ScalarLogical_x])(value);
 }
 
 SEXP Rf_allocVector3(SEXPTYPE t, R_xlen_t len, R_allocator_t* allocator) {
@@ -272,17 +272,17 @@ SEXP Rf_allocVector3(SEXPTYPE t, R_xlen_t len, R_allocator_t* allocator) {
 
 SEXP Rf_allocArray(SEXPTYPE t, SEXP dims) {
     TRACE0();
-	return ((call_Rf_allocArray) callbacks[Rf_allocArray_x])(t, dims);
+    return ((call_Rf_allocArray) callbacks[Rf_allocArray_x])(t, dims);
 }
 
 SEXP Rf_alloc3DArray(SEXPTYPE t, int x, int y, int z) {
     TRACE0();
-	return UNIMPLEMENTED;
+    return UNIMPLEMENTED;
 }
 
 SEXP Rf_allocMatrix(SEXPTYPE mode, int nrow, int ncol) {
     TRACE0();
-	return ((call_Rf_allocMatrix) callbacks[Rf_allocMatrix_x])(mode, nrow, ncol);
+    return ((call_Rf_allocMatrix) callbacks[Rf_allocMatrix_x])(mode, nrow, ncol);
 }
 
 SEXP Rf_allocList(int x) {
@@ -297,7 +297,7 @@ SEXP Rf_allocSExp(SEXPTYPE t) {
 
 void Rf_defineVar(SEXP symbol, SEXP value, SEXP rho) {
     TRACE0();
-	((call_Rf_defineVar) callbacks[Rf_defineVar_x])(symbol, value, rho);
+    ((call_Rf_defineVar) callbacks[Rf_defineVar_x])(symbol, value, rho);
 }
 
 void Rf_setVar(SEXP x, SEXP y, SEXP z) {
@@ -307,75 +307,75 @@ void Rf_setVar(SEXP x, SEXP y, SEXP z) {
 
 SEXP Rf_dimgets(SEXP x, SEXP y) {
     TRACE0();
-	return unimplemented("Rf_dimgets");
+    return unimplemented("Rf_dimgets");
 }
 
 SEXP Rf_dimnamesgets(SEXP x, SEXP y) {
     TRACE0();
-	return unimplemented("Rf_dimnamesgets");
+    return unimplemented("Rf_dimnamesgets");
 }
 
 SEXP Rf_eval(SEXP expr, SEXP env) {
     TRACE0();
-	return ((call_Rf_eval) callbacks[Rf_eval_x])(expr, env);
+    return ((call_Rf_eval) callbacks[Rf_eval_x])(expr, env);
 }
 
 SEXP Rf_findFun(SEXP symbol, SEXP rho) {
     TRACE0();
-	return ((call_Rf_findFun) callbacks[Rf_findFun_x])(symbol, rho);
+    return ((call_Rf_findFun) callbacks[Rf_findFun_x])(symbol, rho);
 }
 
 SEXP Rf_findVar(SEXP sym, SEXP rho) {
     TRACE0();
-	return ((call_Rf_findVar) callbacks[Rf_findVar_x])(sym, rho);
+    return ((call_Rf_findVar) callbacks[Rf_findVar_x])(sym, rho);
 }
 
 SEXP Rf_findVarInFrame(SEXP rho, SEXP sym) {
     TRACE0();
-	return ((call_Rf_findVarInFrame) callbacks[Rf_findVarInFrame_x])(rho, sym);
+    return ((call_Rf_findVarInFrame) callbacks[Rf_findVarInFrame_x])(rho, sym);
 }
 
 SEXP Rf_findVarInFrame3(SEXP rho, SEXP sym, Rboolean b) {
     TRACE0();
-	return ((call_Rf_findVarInFrame3) callbacks[Rf_findVarInFrame3_x])(rho, sym, b);
+    return ((call_Rf_findVarInFrame3) callbacks[Rf_findVarInFrame3_x])(rho, sym, b);
 }
 
 SEXP Rf_getAttrib(SEXP vec, SEXP name) {
     TRACE0();
-	SEXP result = ((call_Rf_getAttrib) callbacks[Rf_getAttrib_x])(vec, name);
-//	printf("Rf_getAttrib: %p\n", result);
-	return result;
+    SEXP result = ((call_Rf_getAttrib) callbacks[Rf_getAttrib_x])(vec, name);
+//    printf("Rf_getAttrib: %p\n", result);
+    return result;
 }
 
 SEXP Rf_setAttrib(SEXP vec, SEXP name, SEXP val) {
     TRACE0();
-	return ((call_Rf_setAttrib) callbacks[Rf_setAttrib_x])(vec, name, val);
+    return ((call_Rf_setAttrib) callbacks[Rf_setAttrib_x])(vec, name, val);
 }
 
 SEXP Rf_duplicate(SEXP x) {
     TRACE0();
-	return ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 1);
+    return ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 1);
 }
 
 SEXP Rf_shallow_duplicate(SEXP x) {
     TRACE0();
-	return ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 0);
+    return ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 0);
 }
 
 R_xlen_t Rf_any_duplicated(SEXP x, Rboolean from_last) {
     TRACE0();
-	return (R_xlen_t) ((call_Rf_any_duplicated) callbacks[Rf_any_duplicated_x])(x, from_last);
+    return (R_xlen_t) ((call_Rf_any_duplicated) callbacks[Rf_any_duplicated_x])(x, from_last);
 }
 
 SEXP Rf_duplicated(SEXP x, Rboolean y) {
     TRACE0();
-	unimplemented("Rf_duplicated");
-	return NULL;
+    unimplemented("Rf_duplicated");
+    return NULL;
 }
 
 SEXP Rf_applyClosure(SEXP x, SEXP y, SEXP z, SEXP a, SEXP b) {
     TRACE0();
-	return unimplemented("Rf_applyClosure");
+    return unimplemented("Rf_applyClosure");
 }
 
 void Rf_copyMostAttrib(SEXP x, SEXP y) {
@@ -384,54 +384,54 @@ void Rf_copyMostAttrib(SEXP x, SEXP y) {
 
 void Rf_copyVector(SEXP x, SEXP y) {
     TRACE0();
-	unimplemented("Rf_copyVector");
+    unimplemented("Rf_copyVector");
 }
 
 int Rf_countContexts(int x, int y) {
     TRACE0();
-	return (int) unimplemented("Rf_countContexts");
+    return (int) unimplemented("Rf_countContexts");
 }
 
 Rboolean Rf_inherits(SEXP x, const char * klass) {
     TRACE0();
-	return (Rboolean) ((call_Rf_inherits) callbacks[Rf_inherits_x])(x, ensure_string(klass));
+    return (Rboolean) ((call_Rf_inherits) callbacks[Rf_inherits_x])(x, ensure_string(klass));
 }
 
 Rboolean Rf_isObject(SEXP s) {
     TRACE0();
-	unimplemented("Rf_isObject");
-	return FALSE;
+    unimplemented("Rf_isObject");
+    return FALSE;
 }
 
 void Rf_PrintValue(SEXP x) {
     TRACE0();
-	unimplemented("Rf_PrintValue");
+    unimplemented("Rf_PrintValue");
 }
 
 SEXP Rf_install(const char *name) {
     TRACE0();
-	return ((call_Rf_install) callbacks[Rf_install_x])(ensure_string(name));
+    return ((call_Rf_install) callbacks[Rf_install_x])(ensure_string(name));
 }
 
 SEXP Rf_installChar(SEXP charsxp) {
     TRACE0();
-	return ((call_Rf_installChar) callbacks[Rf_installChar_x])(charsxp);
+    return ((call_Rf_installChar) callbacks[Rf_installChar_x])(charsxp);
 }
 
 Rboolean Rf_isNull(SEXP s) {
     TRACE0();
-	return (Rboolean) ((call_Rf_isNull) callbacks[Rf_isNull_x])(s);
+    return (Rboolean) ((call_Rf_isNull) callbacks[Rf_isNull_x])(s);
 }
 
 Rboolean Rf_isString(SEXP s) {
     TRACE0();
-	return (Rboolean) ((call_Rf_isString) callbacks[Rf_isString_x])(s);
+    return (Rboolean) ((call_Rf_isString) callbacks[Rf_isString_x])(s);
 }
 
 Rboolean R_cycle_detected(SEXP s, SEXP child) {
     TRACE0();
-	unimplemented("R_cycle_detected");
-	return 0;
+    unimplemented("R_cycle_detected");
+    return 0;
 }
 
 cetype_t Rf_getCharCE(SEXP x) {
@@ -443,18 +443,18 @@ cetype_t Rf_getCharCE(SEXP x) {
 
 const char *Rf_reEnc(const char *x, cetype_t ce_in, cetype_t ce_out, int subst) {
     TRACE0();
-	// TODO proper implementation
-	return x;
+    // TODO proper implementation
+    return x;
 }
 
 int Rf_ncols(SEXP x) {
     TRACE1(x);
-	return (int) ((call_Rf_ncols) callbacks[Rf_ncols_x])(x);
+    return (int) ((call_Rf_ncols) callbacks[Rf_ncols_x])(x);
 }
 
 int Rf_nrows(SEXP x) {
     TRACE1(x);
-	return (int) ((call_Rf_nrows) callbacks[Rf_nrows_x])(x);
+    return (int) ((call_Rf_nrows) callbacks[Rf_nrows_x])(x);
 }
 
 SEXP Rf_protect(SEXP x) {
@@ -484,64 +484,64 @@ void Rf_unprotect_ptr(SEXP x) {
 
 void R_FlushConsole(void) {
     TRACE0();
-	// ignored
+    // ignored
 }
 
 void R_ProcessEvents(void) {
     TRACE0();
-	unimplemented("R_ProcessEvents");
+    unimplemented("R_ProcessEvents");
 }
 
 // Tools package support, not in public API
 SEXP R_NewHashedEnv(SEXP parent, SEXP size) {
     TRACE2(parent, size);
-	return ((call_R_NewHashedEnv) callbacks[R_NewHashedEnv_x])(parent, size);
+    return ((call_R_NewHashedEnv) callbacks[R_NewHashedEnv_x])(parent, size);
 }
 
 SEXP Rf_classgets(SEXP vec, SEXP klass) {
     TRACE2(vec, klass);
-	return ((call_Rf_classgets) callbacks[Rf_classgets_x])(vec, klass);
+    return ((call_Rf_classgets) callbacks[Rf_classgets_x])(vec, klass);
 }
 
 const char *Rf_translateChar(SEXP x) {
     TRACE1(x);
-	// TODO: proper implementation
-	const char *result = CHAR(x);
-	return result;
+    // TODO: proper implementation
+    const char *result = CHAR(x);
+    return result;
 }
 
 const char *Rf_translateChar0(SEXP x) {
     TRACE1(x);
-	// TODO: proper implementation
-	const char *result = CHAR(x);
-	return result;
+    // TODO: proper implementation
+    const char *result = CHAR(x);
+    return result;
 }
 
 const char *Rf_translateCharUTF8(SEXP x) {
     TRACE1(x);
-	// TODO: proper implementation
-	const char *result = CHAR(x);
-	return result;
+    // TODO: proper implementation
+    const char *result = CHAR(x);
+    return result;
 }
 
 SEXP Rf_lengthgets(SEXP x, R_len_t y) {
     TRACE1(x);
-	return ((call_Rf_lengthgets) callbacks[Rf_lengthgets_x])(x, y);
+    return ((call_Rf_lengthgets) callbacks[Rf_lengthgets_x])(x, y);
 }
 
 SEXP Rf_xlengthgets(SEXP x, R_xlen_t y) {
     TRACE1(x);
-	return unimplemented("Rf_xlengthgets");
+    return unimplemented("Rf_xlengthgets");
 }
 
 SEXP R_lsInternal(SEXP env, Rboolean all) {
     TRACE1(env);
-	return R_lsInternal3(env, all, TRUE);
+    return R_lsInternal3(env, all, TRUE);
 }
 
 SEXP R_lsInternal3(SEXP env, Rboolean all, Rboolean sorted) {
     TRACE0();
-	return ((call_R_lsInternal3) callbacks[R_lsInternal3_x])(env, all, sorted);
+    return ((call_R_lsInternal3) callbacks[R_lsInternal3_x])(env, all, sorted);
 }
 
 SEXP Rf_namesgets(SEXP x, SEXP y) {
@@ -551,12 +551,12 @@ SEXP Rf_namesgets(SEXP x, SEXP y) {
 
 SEXP TAG(SEXP e) {
     TRACE0();
-	return ((call_TAG) callbacks[TAG_x])(e);
+    return ((call_TAG) callbacks[TAG_x])(e);
 }
 
 SEXP PRINTNAME(SEXP e) {
     TRACE0();
-	return ((call_PRINTNAME) callbacks[PRINTNAME_x])(e);
+    return ((call_PRINTNAME) callbacks[PRINTNAME_x])(e);
 }
 
 SEXP CAAR(SEXP e) {
@@ -573,12 +573,12 @@ SEXP CDAR(SEXP e) {
 
 SEXP CADR(SEXP e) {
     TRACE0();
-	return ((call_CADR) callbacks[CADR_x])(e);
+    return ((call_CADR) callbacks[CADR_x])(e);
 }
 
 SEXP CDDR(SEXP e) {
     TRACE0();
-	return ((call_CDDR) callbacks[CDDR_x])(e);
+    return ((call_CDDR) callbacks[CDDR_x])(e);
 }
 
 SEXP CDDDR(SEXP e) {
@@ -589,7 +589,7 @@ SEXP CDDDR(SEXP e) {
 
 SEXP CADDR(SEXP e) {
     TRACE0();
-	return ((call_CADDR) callbacks[CADDR_x])(e);
+    return ((call_CADDR) callbacks[CADDR_x])(e);
 }
 
 SEXP CADDDR(SEXP e) {
@@ -617,22 +617,22 @@ void SET_MISSING(SEXP x, int v) {
 
 void SET_TAG(SEXP x, SEXP y) {
     TRACE0();
-	((call_SET_TAG) callbacks[SET_TAG_x])(x, y);
+    ((call_SET_TAG) callbacks[SET_TAG_x])(x, y);
 }
 
 SEXP SETCAR(SEXP x, SEXP y) {
     TRACE0();
-	return ((call_SETCAR) callbacks[SETCAR_x])(x, y);
+    return ((call_SETCAR) callbacks[SETCAR_x])(x, y);
 }
 
 SEXP SETCDR(SEXP x, SEXP y) {
     TRACE0();
-	return ((call_SETCDR) callbacks[SETCDR_x])(x, y);
+    return ((call_SETCDR) callbacks[SETCDR_x])(x, y);
 }
 
 SEXP SETCADR(SEXP x, SEXP y) {
     TRACE0();
-	return ((call_SETCADR) callbacks[SETCADR_x])(x, y);
+    return ((call_SETCADR) callbacks[SETCADR_x])(x, y);
 }
 
 SEXP SETCADDR(SEXP x, SEXP y) {
@@ -660,38 +660,38 @@ SEXP FORMALS(SEXP x) {
 
 SEXP BODY(SEXP x) {
     TRACE0();
-	return unimplemented("BODY");
+    return unimplemented("BODY");
 }
 
 SEXP CLOENV(SEXP x) {
     TRACE0();
-	return unimplemented("CLOENV");
+    return unimplemented("CLOENV");
 }
 
 int RDEBUG(SEXP x) {
     TRACE0();
-	return ((call_RDEBUG) callbacks[RDEBUG_x])(x);
+    return ((call_RDEBUG) callbacks[RDEBUG_x])(x);
 }
 
 int RSTEP(SEXP x) {
     TRACE0();
-	return ((call_RSTEP) callbacks[RSTEP_x])(x);
+    return ((call_RSTEP) callbacks[RSTEP_x])(x);
 }
 
 int RTRACE(SEXP x) {
     TRACE0();
-	unimplemented("RTRACE");
+    unimplemented("RTRACE");
     return 0;
 }
 
 void SET_RDEBUG(SEXP x, int v) {
     TRACE0();
-	((call_SET_RDEBUG) callbacks[SET_RDEBUG_x])(x, v);
+    ((call_SET_RDEBUG) callbacks[SET_RDEBUG_x])(x, v);
 }
 
 void SET_RSTEP(SEXP x, int v) {
     TRACE0();
-	((call_SET_RSTEP) callbacks[SET_RSTEP_x])(x, v);
+    ((call_SET_RSTEP) callbacks[SET_RSTEP_x])(x, v);
 }
 
 void SET_RTRACE(SEXP x, int v) {
@@ -716,17 +716,17 @@ void SET_CLOENV(SEXP x, SEXP v) {
 
 SEXP SYMVALUE(SEXP x) {
     TRACE0();
-	return ((call_SYMVALUE) callbacks[SYMVALUE_x])(x);
+    return ((call_SYMVALUE) callbacks[SYMVALUE_x])(x);
 }
 
 SEXP INTERNAL(SEXP x) {
     TRACE0();
-	return unimplemented("INTERNAL");
+    return unimplemented("INTERNAL");
 }
 
 int DDVAL(SEXP x) {
     TRACE0();
-	unimplemented("DDVAL");
+    unimplemented("DDVAL");
     return 0;
 }
 
@@ -737,7 +737,7 @@ void SET_DDVAL(SEXP x, int v) {
 
 void SET_SYMVALUE(SEXP x, SEXP v) {
     TRACE0();
-	((call_SET_SYMVALUE) callbacks[SET_SYMVALUE_x])(x, v);
+    ((call_SET_SYMVALUE) callbacks[SET_SYMVALUE_x])(x, v);
 }
 
 void SET_INTERNAL(SEXP x, SEXP v) {
@@ -747,28 +747,28 @@ void SET_INTERNAL(SEXP x, SEXP v) {
 
 SEXP FRAME(SEXP x) {
     TRACE0();
-	return unimplemented("FRAME");
+    return unimplemented("FRAME");
 }
 
 SEXP ENCLOS(SEXP x) {
     TRACE0();
-	return ((call_ENCLOS) callbacks[ENCLOS_x])(x);
+    return ((call_ENCLOS) callbacks[ENCLOS_x])(x);
 }
 
 SEXP HASHTAB(SEXP x) {
     TRACE0();
-	return unimplemented("HASHTAB");
+    return unimplemented("HASHTAB");
 }
 
 int ENVFLAGS(SEXP x) {
     TRACE0();
-	unimplemented("ENVFLAGS");
+    unimplemented("ENVFLAGS");
     return 0;
 }
 
 void SET_ENVFLAGS(SEXP x, int v) {
     TRACE0();
-	unimplemented("SET_ENVFLAGS");
+    unimplemented("SET_ENVFLAGS");
 }
 
 void SET_FRAME(SEXP x, SEXP v) {
@@ -778,32 +778,32 @@ void SET_FRAME(SEXP x, SEXP v) {
 
 void SET_ENCLOS(SEXP x, SEXP v) {
     TRACE0();
-	unimplemented("SET_ENCLOS");
+    unimplemented("SET_ENCLOS");
 }
 
 void SET_HASHTAB(SEXP x, SEXP v) {
     TRACE0();
-	unimplemented("SET_HASHTAB");
+    unimplemented("SET_HASHTAB");
 }
 
 SEXP PRCODE(SEXP x) {
     TRACE0();
-	return ((call_PRCODE) callbacks[PRCODE_x])(x);
+    return ((call_PRCODE) callbacks[PRCODE_x])(x);
 }
 
 SEXP PRENV(SEXP x) {
     TRACE0();
-	return ((call_PRENV) callbacks[PRENV_x])(x);
+    return ((call_PRENV) callbacks[PRENV_x])(x);
 }
 
 SEXP PRVALUE(SEXP x) {
     TRACE0();
-	return ((call_PRVALUE) callbacks[PRVALUE_x])(x);
+    return ((call_PRVALUE) callbacks[PRVALUE_x])(x);
 }
 
 int PRSEEN(SEXP x) {
     TRACE0();
-	return ((call_PRSEEN) callbacks[PRSEEN_x])(x);
+    return ((call_PRSEEN) callbacks[PRSEEN_x])(x);
 }
 
 void SET_PRSEEN(SEXP x, int v) {
@@ -850,41 +850,66 @@ R_xlen_t XLENGTH(SEXP x) {
 
 R_xlen_t XTRUELENGTH(SEXP x) {
     TRACE0();
-	unimplemented("XTRUELENGTH");
-	return 0;
+    unimplemented("XTRUELENGTH");
+    return 0;
 }
 
 int IS_LONG_VEC(SEXP x) {
     TRACE0();
-	unimplemented("IS_LONG_VEC");
-	return 0;
+    unimplemented("IS_LONG_VEC");
+    return 0;
 }
 
 int LEVELS(SEXP x) {
     TRACE0();
-	unimplemented("LEVELS");
-	return 0;
+    unimplemented("LEVELS");
+    return 0;
 }
 
 int SETLEVELS(SEXP x, int v) {
     TRACE0();
-	unimplemented("SETLEVELS");
-	return 0;
+    unimplemented("SETLEVELS");
+    return 0;
+}
+
+int *INTEGER(SEXP x) {
+    TRACE0();
+    return ((call_INTEGER) callbacks[INTEGER_x])(x);
+}
+
+int *LOGICAL(SEXP x){
+    TRACE0();
+    return ((call_LOGICAL) callbacks[LOGICAL_x])(x);
+}
+
+double *REAL(SEXP x){
+    TRACE0();
+    return ((call_REAL) callbacks[REAL_x])(x);
+}
+
+Rbyte *RAW(SEXP x) {
+    TRACE0();
+    return ((call_RAW) callbacks[RAW_x])(x);
 }
 
 Rcomplex *COMPLEX(SEXP x) {
     TRACE0();
-	return (Rcomplex*) unimplemented("COMPLEX");
+    return ((call_COMPLEX) callbacks[COMPLEX_x])(x);
+}
+
+const char * R_CHAR(SEXP x) {
+    TRACE0();
+    return ((call_R_CHAR) callbacks[R_CHAR_x])(x);
 }
 
 SEXP STRING_ELT(SEXP x, R_xlen_t i) {
     TRACE0();
-	return ((call_STRING_ELT) callbacks[STRING_ELT_x])(x, i);
+    return ((call_STRING_ELT) callbacks[STRING_ELT_x])(x, i);
 }
 
 SEXP VECTOR_ELT(SEXP x, R_xlen_t i) {
     TRACE0();
-	return ((call_VECTOR_ELT) callbacks[VECTOR_ELT_x])(x, i);
+    return ((call_VECTOR_ELT) callbacks[VECTOR_ELT_x])(x, i);
 }
 
 void SET_STRING_ELT(SEXP x, R_xlen_t i, SEXP v) {
@@ -894,28 +919,28 @@ void SET_STRING_ELT(SEXP x, R_xlen_t i, SEXP v) {
 
 SEXP SET_VECTOR_ELT(SEXP x, R_xlen_t i, SEXP v) {
     TRACE0();
-	return ((call_SET_VECTOR_ELT) callbacks[SET_VECTOR_ELT_x])(x, i, v);
+    return ((call_SET_VECTOR_ELT) callbacks[SET_VECTOR_ELT_x])(x, i, v);
 }
 
 SEXP *STRING_PTR(SEXP x) {
     TRACE0();
-	unimplemented("STRING_PTR");
-	return NULL;
+    unimplemented("STRING_PTR");
+    return NULL;
 }
 
 SEXP * NORET VECTOR_PTR(SEXP x) {
     TRACE0();
-	unimplemented("VECTOR_PTR");
+    unimplemented("VECTOR_PTR");
 }
 
 SEXP Rf_asChar(SEXP x) {
     TRACE0();
-	return ((call_Rf_asChar) callbacks[Rf_asChar_x])(x);
+    return ((call_Rf_asChar) callbacks[Rf_asChar_x])(x);
 }
 
 SEXP Rf_PairToVectorList(SEXP x) {
     TRACE0();
-	return ((call_Rf_PairToVectorList) callbacks[Rf_PairToVectorList_x])(x);
+    return ((call_Rf_PairToVectorList) callbacks[Rf_PairToVectorList_x])(x);
 }
 
 SEXP Rf_VectorToPairList(SEXP x){
@@ -928,28 +953,28 @@ SEXP Rf_asCharacterFactor(SEXP x){
 
 int Rf_asLogical(SEXP x) {
     TRACE0();
-	return ((call_Rf_asLogical) callbacks[Rf_asLogical_x])(x);
+    return ((call_Rf_asLogical) callbacks[Rf_asLogical_x])(x);
 }
 
 int Rf_asInteger(SEXP x) {
     TRACE0();
-	return ((call_Rf_asInteger) callbacks[Rf_asInteger_x])(x);
+    return ((call_Rf_asInteger) callbacks[Rf_asInteger_x])(x);
 }
 
 double Rf_asReal(SEXP x) {
     TRACE0();
-	return ((call_Rf_asReal) callbacks[Rf_asReal_x])(x);
+    return ((call_Rf_asReal) callbacks[Rf_asReal_x])(x);
 }
 
 Rcomplex Rf_asComplex(SEXP x) {
     TRACE0();
-	unimplemented("Rf_asComplex");
-	Rcomplex c; return c;
+    unimplemented("Rf_asComplex");
+    Rcomplex c; return c;
 }
 
 int TYPEOF(SEXP x) {
     TRACE0();
-	return (int) ((call_TYPEOF) callbacks[TYPEOF_x])(x);
+    return (int) ((call_TYPEOF) callbacks[TYPEOF_x])(x);
 }
 
 SEXP ATTRIB(SEXP x) {
@@ -959,7 +984,7 @@ SEXP ATTRIB(SEXP x) {
 
 int OBJECT(SEXP x) {
     TRACE0();
-	return (int) ((call_OBJECT) callbacks[OBJECT_x])(x);
+    return (int) ((call_OBJECT) callbacks[OBJECT_x])(x);
 }
 
 int MARK(SEXP x) {
@@ -970,7 +995,7 @@ int MARK(SEXP x) {
 
 int NAMED(SEXP x) {
     TRACE0();
-	return (int) ((call_NAMED) callbacks[NAMED_x])(x);
+    return (int) ((call_NAMED) callbacks[NAMED_x])(x);
 }
 
 int REFCNT(SEXP x) {
@@ -991,7 +1016,7 @@ void SET_TYPEOF(SEXP x, int v) {
 
 SEXP SET_TYPEOF_FASTR(SEXP x, int v) {
     TRACE0();
-	return ((call_SET_TYPEOF_FASTR) callbacks[SET_TYPEOF_FASTR_x])(x, v);
+    return ((call_SET_TYPEOF_FASTR) callbacks[SET_TYPEOF_FASTR_x])(x, v);
 }
 
 void SET_NAMED(SEXP x, int v) {
@@ -1006,114 +1031,114 @@ void SET_ATTRIB(SEXP x, SEXP v) {
 
 void DUPLICATE_ATTRIB(SEXP to, SEXP from) {
     TRACE0();
-	((call_DUPLICATE_ATTRIB) callbacks[DUPLICATE_ATTRIB_x])(to, from);
+    ((call_DUPLICATE_ATTRIB) callbacks[DUPLICATE_ATTRIB_x])(to, from);
 }
 
 void R_qsort_I  (double *v, int *II, int i, int j) {
     TRACE0();
-	unimplemented("R_qsort_I");
+    unimplemented("R_qsort_I");
 }
 
 void R_qsort_int_I(int *iv, int *II, int i, int j) {
     TRACE0();
-	unimplemented("R_qsort_int_I");
+    unimplemented("R_qsort_int_I");
 }
 
 R_len_t R_BadLongVector(SEXP x, const char *y, int z) {
     TRACE0();
-	return (R_len_t) unimplemented("R_BadLongVector");
+    return (R_len_t) unimplemented("R_BadLongVector");
 }
 
 int IS_S4_OBJECT(SEXP x) {
     TRACE0();
-	return (int) ((call_IS_S4_OBJECT) callbacks[IS_S4_OBJECT_x])(x);
+    return (int) ((call_IS_S4_OBJECT) callbacks[IS_S4_OBJECT_x])(x);
 }
 
 void SET_S4_OBJECT(SEXP x) {
     TRACE0();
-	((call_SET_S4_OBJECT) callbacks[SET_S4_OBJECT_x])(x);
+    ((call_SET_S4_OBJECT) callbacks[SET_S4_OBJECT_x])(x);
 }
 
 void UNSET_S4_OBJECT(SEXP x) {
     TRACE0();
-	((call_UNSET_S4_OBJECT) callbacks[UNSET_S4_OBJECT_x])(x);
+    ((call_UNSET_S4_OBJECT) callbacks[UNSET_S4_OBJECT_x])(x);
 }
 
 Rboolean R_ToplevelExec(void (*fun)(void *), void *data) {
     TRACE0();
-	return (Rboolean) unimplemented("R_ToplevelExec");
+    return (Rboolean) unimplemented("R_ToplevelExec");
 }
 
 SEXP R_ExecWithCleanup(SEXP (*fun)(void *), void *data,
-		       void (*cleanfun)(void *), void *cleandata) {
+               void (*cleanfun)(void *), void *cleandata) {
     TRACE0();
-	return unimplemented("R_ExecWithCleanup");
+    return unimplemented("R_ExecWithCleanup");
 }
 
 /* Environment and Binding Features */
 void R_RestoreHashCount(SEXP rho) {
     TRACE0();
-	unimplemented("R_RestoreHashCount");
+    unimplemented("R_RestoreHashCount");
 }
 
 Rboolean R_IsPackageEnv(SEXP rho) {
     TRACE0();
-	unimplemented("R_IsPackageEnv");
+    unimplemented("R_IsPackageEnv");
 }
 
 SEXP R_PackageEnvName(SEXP rho) {
     TRACE0();
-	return unimplemented("R_PackageEnvName");
+    return unimplemented("R_PackageEnvName");
 }
 
 SEXP R_FindPackageEnv(SEXP info) {
     TRACE0();
-	return unimplemented("R_FindPackageEnv");
+    return unimplemented("R_FindPackageEnv");
 }
 
 Rboolean R_IsNamespaceEnv(SEXP rho) {
     TRACE0();
-	return (Rboolean) unimplemented("R_IsNamespaceEnv");
+    return (Rboolean) unimplemented("R_IsNamespaceEnv");
 }
 
 SEXP R_FindNamespace(SEXP info) {
     TRACE0();
-	return ((call_R_FindNamespace) callbacks[R_FindNamespace_x])(info);
+    return ((call_R_FindNamespace) callbacks[R_FindNamespace_x])(info);
 }
 
 SEXP R_NamespaceEnvSpec(SEXP rho) {
     TRACE0();
-	return unimplemented("R_NamespaceEnvSpec");
+    return unimplemented("R_NamespaceEnvSpec");
 }
 
 void R_LockEnvironment(SEXP env, Rboolean bindings) {
     TRACE0();
-	unimplemented("R_LockEnvironment");
+    unimplemented("R_LockEnvironment");
 }
 
 Rboolean R_EnvironmentIsLocked(SEXP env) {
     TRACE0();
-	unimplemented("");
+    unimplemented("");
 }
 
 void R_LockBinding(SEXP sym, SEXP env) {
     TRACE0();
-	unimplemented("R_LockBinding");
+    unimplemented("R_LockBinding");
 }
 
 void R_unLockBinding(SEXP sym, SEXP env) {
     TRACE0();
-	unimplemented("R_unLockBinding");
+    unimplemented("R_unLockBinding");
 }
 
 void R_MakeActiveBinding(SEXP sym, SEXP fun, SEXP env) {
     TRACE0();
-	unimplemented("R_MakeActiveBinding");
+    unimplemented("R_MakeActiveBinding");
 }
 
 Rboolean R_BindingIsLocked(SEXP sym, SEXP env) {
     TRACE0();
-	return (Rboolean) ((call_R_BindingIsLocked) callbacks[R_BindingIsLocked_x])(sym, env);
+    return (Rboolean) ((call_R_BindingIsLocked) callbacks[R_BindingIsLocked_x])(sym, env);
 }
 
 Rboolean R_BindingIsActive(SEXP sym, SEXP env) {
@@ -1124,7 +1149,7 @@ Rboolean R_BindingIsActive(SEXP sym, SEXP env) {
 
 Rboolean R_HasFancyBindings(SEXP rho) {
     TRACE0();
-	return (Rboolean) unimplemented("R_HasFancyBindings");
+    return (Rboolean) unimplemented("R_HasFancyBindings");
 }
 
 Rboolean Rf_isS4(SEXP x) {
@@ -1134,169 +1159,169 @@ Rboolean Rf_isS4(SEXP x) {
 
 SEXP Rf_asS4(SEXP x, Rboolean b, int i) {
     TRACE0();
-	unimplemented("Rf_asS4");
+    unimplemented("Rf_asS4");
 }
 
 static SEXP R_tryEvalInternal(SEXP x, SEXP y, int *ErrorOccurred, int silent) {
     TRACE0();
-	unimplemented("R_tryEvalInternal");
+    unimplemented("R_tryEvalInternal");
 }
 
 SEXP R_tryEval(SEXP x, SEXP y, int *ErrorOccurred) {
     TRACE0();
-	return R_tryEvalInternal(x, y, ErrorOccurred, 0);
+    return R_tryEvalInternal(x, y, ErrorOccurred, 0);
 }
 
 SEXP R_tryEvalSilent(SEXP x, SEXP y, int *ErrorOccurred) {
     TRACE0();
-	return R_tryEvalInternal(x, y, ErrorOccurred, 1);
+    return R_tryEvalInternal(x, y, ErrorOccurred, 1);
 }
 
 double R_atof(const char *str) {
     TRACE0();
-	unimplemented("R_atof");
-	return 0;
+    unimplemented("R_atof");
+    return 0;
 }
 
 double R_strtod(const char *c, char **end) {
     TRACE0();
-	unimplemented("R_strtod");
-	return 0;
+    unimplemented("R_strtod");
+    return 0;
 }
 
 SEXP R_PromiseExpr(SEXP x) {
     TRACE0();
-	return ((call_R_PromiseExpr) callbacks[R_PromiseExpr_x])(x);
+    return ((call_R_PromiseExpr) callbacks[R_PromiseExpr_x])(x);
 }
 
 SEXP R_ClosureExpr(SEXP x) {
     TRACE0();
-	return unimplemented("R_ClosureExpr");
+    return unimplemented("R_ClosureExpr");
 }
 
 SEXP R_forceAndCall(SEXP e, int n, SEXP rho) {
     TRACE0();
-	return unimplemented("R_forceAndCall");
+    return unimplemented("R_forceAndCall");
 }
 
 SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot) {
     TRACE0();
-	return ((call_R_MakeExternalPtr) callbacks[R_MakeExternalPtr_x])(p, tag, prot);
+    return ((call_R_MakeExternalPtr) callbacks[R_MakeExternalPtr_x])(p, tag, prot);
 }
 
 void *R_ExternalPtrAddr(SEXP s) {
     TRACE0();
-	return ((call_R_ExternalPtrAddr) callbacks[R_ExternalPtrAddr_x])(s);
+    return ((call_R_ExternalPtrAddr) callbacks[R_ExternalPtrAddr_x])(s);
 }
 
 SEXP R_ExternalPtrTag(SEXP s) {
     TRACE0();
-	return ((call_R_ExternalPtrTag) callbacks[R_ExternalPtrTag_x])(s);
+    return ((call_R_ExternalPtrTag) callbacks[R_ExternalPtrTag_x])(s);
 }
 
 SEXP R_ExternalPtrProtected(SEXP s) {
     TRACE0();
-	return ((call_R_ExternalPtrProtected) callbacks[R_ExternalPtrProtected_x])(s);
+    return ((call_R_ExternalPtrProtected) callbacks[R_ExternalPtrProtected_x])(s);
 }
 
 void R_SetExternalPtrAddr(SEXP s, void *p) {
     TRACE0();
-	((call_R_SetExternalPtrAddr) callbacks[R_SetExternalPtrAddr_x])(s, p);
+    ((call_R_SetExternalPtrAddr) callbacks[R_SetExternalPtrAddr_x])(s, p);
 }
 
 void R_SetExternalPtrTag(SEXP s, SEXP tag) {
     TRACE0();
-	((call_R_SetExternalPtrTag) callbacks[R_SetExternalPtrTag_x])(s, tag);
+    ((call_R_SetExternalPtrTag) callbacks[R_SetExternalPtrTag_x])(s, tag);
 }
 
 void R_SetExternalPtrProtected(SEXP s, SEXP p) {
     TRACE0();
-	((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, p);
+    ((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, p);
 }
 
 void R_ClearExternalPtr(SEXP s) {
     TRACE0();
-	R_SetExternalPtrAddr(s, NULL);
+    R_SetExternalPtrAddr(s, NULL);
 }
 
 void R_RegisterFinalizer(SEXP s, SEXP fun) {
     TRACE0();
-	// TODO implement, but not fail for now
+    // TODO implement, but not fail for now
 }
 void R_RegisterCFinalizer(SEXP s, R_CFinalizer_t fun) {
     TRACE0();
-	// TODO implement, but not fail for now
+    // TODO implement, but not fail for now
 }
 
 void R_RegisterFinalizerEx(SEXP s, SEXP fun, Rboolean onexit) {
     TRACE0();
-	// TODO implement, but not fail for now
+    // TODO implement, but not fail for now
 
 }
 
 void R_RegisterCFinalizerEx(SEXP s, R_CFinalizer_t fun, Rboolean onexit) {
     TRACE0();
-	// TODO implement, but not fail for now
+    // TODO implement, but not fail for now
 }
 
 void R_RunPendingFinalizers(void) {
     TRACE0();
-	// TODO implement, but not fail for now
+    // TODO implement, but not fail for now
 }
 
 SEXP R_MakeWeakRef(SEXP key, SEXP val, SEXP fin, Rboolean onexit) {
     TRACE0();
-	unimplemented("R_MakeWeakRef");
+    unimplemented("R_MakeWeakRef");
 }
 
 SEXP R_MakeWeakRefC(SEXP key, SEXP val, R_CFinalizer_t fin, Rboolean onexit) {
     TRACE0();
-	unimplemented("R_MakeWeakRefC");
+    unimplemented("R_MakeWeakRefC");
 }
 
 SEXP R_WeakRefKey(SEXP w) {
     TRACE0();
-	unimplemented("R_WeakRefKey");
+    unimplemented("R_WeakRefKey");
 }
 
 SEXP R_WeakRefValue(SEXP w) {
     TRACE0();
-	unimplemented("R_WeakRefValue");
+    unimplemented("R_WeakRefValue");
 }
 
 void R_RunWeakRefFinalizer(SEXP w) {
     TRACE0();
-	// TODO implement, but not fail for now
+    // TODO implement, but not fail for now
 }
 
 SEXP R_do_slot(SEXP obj, SEXP name) {
     TRACE0();
-	return ((call_R_do_slot) callbacks[R_do_slot_x])(obj, name);
+    return ((call_R_do_slot) callbacks[R_do_slot_x])(obj, name);
 }
 
 SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) {
     TRACE0();
-	return ((call_R_do_slot_assign) callbacks[R_do_slot_assign_x])(obj, name, value);
+    return ((call_R_do_slot_assign) callbacks[R_do_slot_assign_x])(obj, name, value);
 }
 
 int R_has_slot(SEXP obj, SEXP name) {
     TRACE0();
-	return (int) unimplemented("R_has_slot");
+    return (int) unimplemented("R_has_slot");
 }
 
 SEXP R_do_MAKE_CLASS(const char *what) {
     TRACE0();
-	return ((call_R_do_MAKE_CLASS) callbacks[R_do_MAKE_CLASS_x])(what);
+    return ((call_R_do_MAKE_CLASS) callbacks[R_do_MAKE_CLASS_x])(what);
 }
 
 SEXP R_getClassDef (const char *what) {
     TRACE0();
-	return unimplemented("R_getClassDef");
+    return unimplemented("R_getClassDef");
 }
 
 SEXP R_do_new_object(SEXP class_def) {
     TRACE0();
-	return ((call_R_do_new_object) callbacks[R_do_new_object_x])(class_def);
+    return ((call_R_do_new_object) callbacks[R_do_new_object_x])(class_def);
 }
 
 static SEXP nfiGetMethodsNamespace() {
@@ -1306,7 +1331,7 @@ static SEXP nfiGetMethodsNamespace() {
 
 int R_check_class_etc (SEXP x, const char **valid) {
     TRACE0();
-	return R_check_class_etc_helper(x, valid, nfiGetMethodsNamespace);
+    return R_check_class_etc_helper(x, valid, nfiGetMethodsNamespace);
 }
 
 void R_PreserveObject(SEXP x) {
@@ -1321,22 +1346,22 @@ void R_ReleaseObject(SEXP x) {
 
 void R_dot_Last(void) {
     TRACE0();
-	unimplemented("R_dot_Last");
+    unimplemented("R_dot_Last");
 }
 
 Rboolean R_compute_identical(SEXP x, SEXP y, int flags) {
     TRACE0();
-	return (Rboolean) ((call_R_compute_identical) callbacks[R_compute_identical_x])(x, y, flags);
+    return (Rboolean) ((call_R_compute_identical) callbacks[R_compute_identical_x])(x, y, flags);
 }
 
 void Rf_copyListMatrix(SEXP s, SEXP t, Rboolean byrow) {
     TRACE0();
-	((call_Rf_copyListMatrix) callbacks[Rf_copyListMatrix_x])(s, t, byrow);
+    ((call_Rf_copyListMatrix) callbacks[Rf_copyListMatrix_x])(s, t, byrow);
 }
 
 void Rf_copyMatrix(SEXP s, SEXP t, Rboolean byrow) {
     TRACE0();
-	((call_Rf_copyMatrix) callbacks[Rf_copyMatrix_x])(s, t, byrow);
+    ((call_Rf_copyMatrix) callbacks[Rf_copyMatrix_x])(s, t, byrow);
 }
 
 int FASTR_getConnectionChar(SEXP conn) {
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
index d5c0f7669539e394352bb7823465a8fa0e476243..24de7551e03ff2933c240d6f964e7fb38c12ea32 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
@@ -96,27 +96,3 @@ void return_BYTE_EXISTING(long address) {
 void return_FREE(void *address) {
 //	free(address);
 }
-
-int *INTEGER(SEXP x) {
-	return ((call_INTEGER) callbacks[INTEGER_x])(x);
-}
-
-int *LOGICAL(SEXP x){
-	return ((call_LOGICAL) callbacks[LOGICAL_x])(x);
-}
-
-double *REAL(SEXP x){
-	((call_REAL) callbacks[REAL_x])(x);
-	return return_double;
-}
-
-Rbyte *RAW(SEXP x) {
-	((call_RAW) callbacks[RAW_x])(x);
-		return (Rbyte *) return_byte;
-}
-
-const char * R_CHAR(SEXP x) {
-	((call_R_CHAR) callbacks[R_CHAR_x])(x);
-	return return_byte;
-}
-
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index c3e78ba18bb188b3524a8d6601fba3bede23a608..4d1f4bf43f7ca73b1a5f008b0639b0fe279b0202 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -39,7 +39,6 @@ import java.nio.charset.CodingErrorAction;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.HashMap;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CharSXPWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java
similarity index 83%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CharSXPWrapper.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java
index 92763196ffc5a7d1515017bdf8db8fa535778c91..8178d4c0276ae70944915079cd7754463b8c30b2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CharSXPWrapper.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java
@@ -20,10 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi;
-
-import com.oracle.truffle.r.runtime.data.RObject;
-import com.oracle.truffle.r.runtime.data.RTruffleObject;
+package com.oracle.truffle.r.runtime.data;
 
 /**
  * Internally GNU R distinguishes "strings" and "vectors of strings" using the {@code CHARSXP} and
@@ -35,22 +32,30 @@ import com.oracle.truffle.r.runtime.data.RTruffleObject;
  * N.B. Use limited to RFFI implementations.
  */
 public final class CharSXPWrapper extends RObject implements RTruffleObject {
-    private final String contents;
+    private String contents;
 
     private CharSXPWrapper(String contents) {
         this.contents = contents;
     }
 
     public String getContents() {
-        return contents;
+        return NativeDataAccess.getData(this, contents);
     }
 
     @Override
     public String toString() {
-        return "CHARSXP(" + contents + ")";
+        return "CHARSXP(" + getContents() + ")";
     }
 
     public static CharSXPWrapper create(String contents) {
         return new CharSXPWrapper(contents);
     }
+
+    public long allocateNativeContents() {
+        try {
+            return NativeDataAccess.allocateNativeContents(this, contents);
+        } finally {
+            contents = null;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java
index 442e4ae68f063d340feac316fa8fd7b70b0b2177..8822d7b40175edbb0e8a889a5cde0896b4d3ec09 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java
@@ -24,9 +24,11 @@ package com.oracle.truffle.r.runtime.data;
 
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Field;
+import java.nio.charset.StandardCharsets;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 
+import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.Truffle;
@@ -86,19 +88,28 @@ public final class NativeDataAccess {
             this.id = counter.incrementAndGet();
         }
 
-        void allocateNative(Object source, long sourceLength, int len, int elementBase, int elementSize) {
+        void allocateNative(Object source, int len, int elementBase, int elementSize) {
             assert dataAddress == 0;
-            dataAddress = UnsafeAdapter.UNSAFE.allocateMemory(sourceLength * elementSize);
-            UnsafeAdapter.UNSAFE.copyMemory(source, elementBase, null, dataAddress, sourceLength * elementSize);
+            dataAddress = UnsafeAdapter.UNSAFE.allocateMemory(len * elementSize);
+            UnsafeAdapter.UNSAFE.copyMemory(source, elementBase, null, dataAddress, len * elementSize);
             this.length = len;
         }
 
+        void allocateNative(String source) {
+            assert dataAddress == 0;
+            byte[] bytes = source.getBytes(StandardCharsets.UTF_8);
+            dataAddress = UnsafeAdapter.UNSAFE.allocateMemory(bytes.length + 1);
+            UnsafeAdapter.UNSAFE.copyMemory(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, dataAddress, bytes.length + 1);
+            this.length = bytes.length + 1;
+        }
+
         @Override
         protected void finalize() throws Throwable {
             super.finalize();
             nativeMirrors.remove(id);
             // System.out.println(String.format("gc'ing %16x", id));
             if (dataAddress != 0) {
+                // System.out.println(String.format("freeing data at %16x", dataAddress));
                 UnsafeAdapter.UNSAFE.freeMemory(dataAddress);
                 assert (dataAddress = 0xbadbad) != 0;
             }
@@ -136,7 +147,8 @@ public final class NativeDataAccess {
             NativeMirror mirror = (NativeMirror) obj.getNativeMirror();
             if (mirror == null) {
                 obj.setNativeMirror(mirror = new NativeMirror());
-                // System.out.println(String.format("adding %16x = %s", mirror.id, obj));
+                // System.out.println(String.format("adding %16x = %s", mirror.id,
+                // obj.getClass().getSimpleName()));
                 nativeMirrors.put(mirror.id, new WeakReference<>(obj));
             }
             return mirror.id;
@@ -144,6 +156,11 @@ public final class NativeDataAccess {
         throw UnsupportedMessageException.raise(Message.AS_POINTER);
     }
 
+    public static Object toNative(Object obj) {
+        assert obj instanceof RObject : "non-RObjects will not be able to provide native pointers";
+        return obj;
+    }
+
     public static Object lookup(long address) {
         WeakReference<RObject> reference = nativeMirrors.get(address);
         if (reference == null) {
@@ -158,32 +175,171 @@ public final class NativeDataAccess {
         return result;
     }
 
-    static long getDataLength(RVector<?> vector) {
-        return ((NativeMirror) vector.getNativeMirror()).length;
+    private static final Assumption noIntNative = Truffle.getRuntime().createAssumption();
+    private static final Assumption noLogicalNative = Truffle.getRuntime().createAssumption();
+    private static final Assumption noDoubleNative = Truffle.getRuntime().createAssumption();
+    private static final Assumption noComplexNative = Truffle.getRuntime().createAssumption();
+    private static final Assumption noRawNative = Truffle.getRuntime().createAssumption();
+    private static final Assumption noCahrSXPNative = Truffle.getRuntime().createAssumption();
+
+    static int getData(RIntVector vector, int[] data, int index) {
+        if (noIntNative.isValid() || data != null) {
+            return data[index];
+        } else {
+            long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
+            assert address != 0;
+            return UnsafeAdapter.UNSAFE.getInt(address + index * Unsafe.ARRAY_INT_INDEX_SCALE);
+        }
+    }
+
+    static int getDataLength(RIntVector vector, int[] data) {
+        if (noIntNative.isValid() || data != null) {
+            return data.length;
+        } else {
+            return (int) ((NativeMirror) vector.getNativeMirror()).length;
+        }
+    }
+
+    static void setData(RIntVector vector, int[] data, int index, int value) {
+        if (noIntNative.isValid() || data != null) {
+            data[index] = value;
+        } else {
+            long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
+            assert address != 0;
+            UnsafeAdapter.UNSAFE.putInt(address + index * Unsafe.ARRAY_INT_INDEX_SCALE, value);
+        }
+    }
+
+    static byte getData(RLogicalVector vector, byte[] data, int index) {
+        if (noLogicalNative.isValid() || data != null) {
+            return data[index];
+        } else {
+            long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
+            assert address != 0;
+            return RRuntime.int2logical(UnsafeAdapter.UNSAFE.getInt(address + index * Unsafe.ARRAY_INT_INDEX_SCALE));
+        }
+    }
+
+    static int getDataLength(RLogicalVector vector, byte[] data) {
+        if (noLogicalNative.isValid() || data != null) {
+            return data.length;
+        } else {
+            return (int) ((NativeMirror) vector.getNativeMirror()).length;
+        }
+    }
+
+    static void setData(RLogicalVector vector, byte[] data, int index, byte value) {
+        if (noLogicalNative.isValid() || data != null) {
+            data[index] = value;
+        } else {
+            long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
+            assert address != 0;
+            UnsafeAdapter.UNSAFE.putInt(address + index * Unsafe.ARRAY_INT_INDEX_SCALE, RRuntime.logical2int(value));
+        }
+    }
+
+    static byte getData(RRawVector vector, byte[] data, int index) {
+        if (noRawNative.isValid() || data != null) {
+            return data[index];
+        } else {
+            long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
+            assert address != 0;
+            return UnsafeAdapter.UNSAFE.getByte(address + index * Unsafe.ARRAY_BYTE_INDEX_SCALE);
+        }
+    }
+
+    static int getDataLength(RRawVector vector, byte[] data) {
+        if (noRawNative.isValid() || data != null) {
+            return data.length;
+        } else {
+            return (int) ((NativeMirror) vector.getNativeMirror()).length;
+        }
+    }
+
+    static void setData(RRawVector vector, byte[] data, int index, byte value) {
+        if (noRawNative.isValid() || data != null) {
+            data[index] = value;
+        } else {
+            long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
+            assert address != 0;
+            UnsafeAdapter.UNSAFE.putInt(address + index * Unsafe.ARRAY_BYTE_INDEX_SCALE, value);
+        }
+    }
+
+    static double getData(RDoubleVector vector, double[] data, int index) {
+        if (noDoubleNative.isValid() || data != null) {
+            return data[index];
+        } else {
+            long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
+            assert address != 0;
+            return UnsafeAdapter.UNSAFE.getDouble(address + index * Unsafe.ARRAY_INT_INDEX_SCALE);
+        }
+    }
+
+    static int getDataLength(RDoubleVector vector, double[] data) {
+        if (noDoubleNative.isValid() || data != null) {
+            return data.length;
+        } else {
+            return (int) ((NativeMirror) vector.getNativeMirror()).length;
+        }
     }
 
-    static int getIntData(RVector<?> vector, int index) {
-        long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
-        assert address != 0;
-        return UnsafeAdapter.UNSAFE.getInt(address + index * Unsafe.ARRAY_INT_INDEX_SCALE);
+    static void setData(RDoubleVector vector, double[] data, int index, double value) {
+        if (noDoubleNative.isValid() || data != null) {
+            data[index] = value;
+        } else {
+            long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
+            assert address != 0;
+            UnsafeAdapter.UNSAFE.putDouble(address + index * Unsafe.ARRAY_INT_INDEX_SCALE, value);
+        }
     }
 
-    static void setIntData(RVector<?> vector, int index, int value) {
-        long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
-        assert address != 0;
-        UnsafeAdapter.UNSAFE.putInt(address + index * Unsafe.ARRAY_INT_INDEX_SCALE, value);
+    static RComplex getData(RComplexVector vector, double[] data, int index) {
+        if (noComplexNative.isValid() || data != null) {
+            return RComplex.valueOf(data[index * 2], data[index * 2 + 1]);
+        } else {
+            long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
+            assert address != 0;
+            return RComplex.valueOf(UnsafeAdapter.UNSAFE.getDouble(address + index * 2 * Unsafe.ARRAY_INT_INDEX_SCALE),
+                            UnsafeAdapter.UNSAFE.getDouble(address + (index * 2 + 1) * Unsafe.ARRAY_INT_INDEX_SCALE));
+        }
     }
 
-    static double getDoubleData(RVector<?> vector, int index) {
-        long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
-        assert address != 0;
-        return UnsafeAdapter.UNSAFE.getDouble(address + index * Unsafe.ARRAY_INT_INDEX_SCALE);
+    static int getDataLength(RComplexVector vector, double[] data) {
+        if (noComplexNative.isValid() || data != null) {
+            return data.length >> 1;
+        } else {
+            return (int) ((NativeMirror) vector.getNativeMirror()).length;
+        }
     }
 
-    static void setDoubleData(RVector<?> vector, int index, double value) {
-        long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
-        assert address != 0;
-        UnsafeAdapter.UNSAFE.putDouble(address + index * Unsafe.ARRAY_INT_INDEX_SCALE, value);
+    static void setData(RComplexVector vector, double[] data, int index, double re, double im) {
+        if (noComplexNative.isValid() || data != null) {
+            data[index * 2] = re;
+            data[index * 2 + 1] = im;
+        } else {
+            long address = ((NativeMirror) vector.getNativeMirror()).dataAddress;
+            assert address != 0;
+            UnsafeAdapter.UNSAFE.putDouble(address + index * 2 * Unsafe.ARRAY_INT_INDEX_SCALE, re);
+            UnsafeAdapter.UNSAFE.putDouble(address + (index * 2 + 1) * Unsafe.ARRAY_INT_INDEX_SCALE, im);
+        }
+    }
+
+    static String getData(CharSXPWrapper vector, String data) {
+        if (noCahrSXPNative.isValid() || data != null) {
+            return data;
+        } else {
+            NativeMirror mirror = (NativeMirror) vector.getNativeMirror();
+            long address = mirror.dataAddress;
+            assert address != 0;
+            int length = 0;
+            while (length < mirror.length && UnsafeAdapter.UNSAFE.getByte(address + length) != 0) {
+                length++;
+            }
+            byte[] bytes = new byte[length];
+            UnsafeAdapter.UNSAFE.copyMemory(null, address, bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, length);
+            return new String(bytes, StandardCharsets.UTF_8);
+        }
     }
 
     static long allocateNativeContents(RLogicalVector vector, byte[] data, int length) {
@@ -191,13 +347,12 @@ public final class NativeDataAccess {
         assert mirror != null;
         assert mirror.dataAddress == 0 ^ data == null;
         if (mirror.dataAddress == 0) {
-            // System.out.println(String.format("allocating native for logical vector %16x",
-            // mirror.id));
             int[] intArray = new int[data.length];
             for (int i = 0; i < data.length; i++) {
                 intArray[i] = RRuntime.logical2int(data[i]);
             }
-            ((NativeMirror) vector.getNativeMirror()).allocateNative(intArray, data.length, length, Unsafe.ARRAY_INT_BASE_OFFSET, Unsafe.ARRAY_INT_INDEX_SCALE);
+            noLogicalNative.invalidate();
+            mirror.allocateNative(intArray, length, Unsafe.ARRAY_INT_BASE_OFFSET, Unsafe.ARRAY_INT_INDEX_SCALE);
         }
         return mirror.dataAddress;
     }
@@ -207,9 +362,19 @@ public final class NativeDataAccess {
         assert mirror != null;
         assert mirror.dataAddress == 0 ^ data == null;
         if (mirror.dataAddress == 0) {
-            // System.out.println(String.format("allocating native for int vector %16x",
-            // mirror.id));
-            ((NativeMirror) vector.getNativeMirror()).allocateNative(data, data.length, length, Unsafe.ARRAY_INT_BASE_OFFSET, Unsafe.ARRAY_INT_INDEX_SCALE);
+            noIntNative.invalidate();
+            mirror.allocateNative(data, length, Unsafe.ARRAY_INT_BASE_OFFSET, Unsafe.ARRAY_INT_INDEX_SCALE);
+        }
+        return mirror.dataAddress;
+    }
+
+    static long allocateNativeContents(RRawVector vector, byte[] data, int length) {
+        NativeMirror mirror = (NativeMirror) vector.getNativeMirror();
+        assert mirror != null;
+        assert mirror.dataAddress == 0 ^ data == null;
+        if (mirror.dataAddress == 0) {
+            noRawNative.invalidate();
+            mirror.allocateNative(data, length, Unsafe.ARRAY_BYTE_BASE_OFFSET, Unsafe.ARRAY_BYTE_INDEX_SCALE);
         }
         return mirror.dataAddress;
     }
@@ -219,9 +384,30 @@ public final class NativeDataAccess {
         assert mirror != null;
         assert mirror.dataAddress == 0 ^ data == null;
         if (mirror.dataAddress == 0) {
-            // System.out.println(String.format("allocating native for double vector %16x",
-            // mirror.id));
-            ((NativeMirror) vector.getNativeMirror()).allocateNative(data, data.length, length, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
+            noDoubleNative.invalidate();
+            mirror.allocateNative(data, length, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
+        }
+        return mirror.dataAddress;
+    }
+
+    static long allocateNativeContents(RComplexVector vector, double[] data, int length) {
+        NativeMirror mirror = (NativeMirror) vector.getNativeMirror();
+        assert mirror != null;
+        assert mirror.dataAddress == 0 ^ data == null;
+        if (mirror.dataAddress == 0) {
+            noComplexNative.invalidate();
+            mirror.allocateNative(data, length, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, Unsafe.ARRAY_DOUBLE_INDEX_SCALE * 2);
+        }
+        return mirror.dataAddress;
+    }
+
+    static long allocateNativeContents(CharSXPWrapper vector, String contents) {
+        NativeMirror mirror = (NativeMirror) vector.getNativeMirror();
+        assert mirror != null;
+        assert mirror.dataAddress == 0 ^ contents == null;
+        if (mirror.dataAddress == 0) {
+            noCahrSXPNative.invalidate();
+            mirror.allocateNative(contents);
         }
         return mirror.dataAddress;
     }
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 26503bfece54f28770a35e3d24fdfa35c5995abc..207dc2d50e3bc6777cdbb15f068a4d92ad1455f1 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
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public final class RComplexVector extends RVector<double[]> implements RAbstractComplexVector {
 
-    private final double[] data;
+    private double[] data;
 
     RComplexVector(double[] data, boolean complete) {
         super(complete);
@@ -51,6 +51,7 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
 
     @Override
     protected RComplexVector internalCopy() {
+        assert data != null;
         return new RComplexVector(Arrays.copyOf(data, data.length), this.isComplete());
     }
 
@@ -61,7 +62,7 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
 
     @Override
     public int getLength() {
-        return data.length >> 1;
+        return NativeDataAccess.getDataLength(this, data);
     }
 
     @Override
@@ -81,22 +82,18 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
     @Override
     public void setDataAt(Object store, int index, RComplex value) {
         assert data == store;
-        double[] array = (double[]) store;
-        array[index << 1] = value.getRealPart();
-        array[(index << 1) + 1] = value.getImaginaryPart();
+        NativeDataAccess.setData(this, (double[]) store, index, value.getRealPart(), value.getImaginaryPart());
     }
 
     @Override
-    public RComplex getDataAt(Object store, int i) {
+    public RComplex getDataAt(Object store, int index) {
         assert data == store;
-        double[] doubleStore = (double[]) store;
-        int index = i << 1;
-        return RDataFactory.createComplex(doubleStore[index], doubleStore[index + 1]);
+        return NativeDataAccess.getData(this, (double[]) store, index);
     }
 
     @Override
-    public RComplex getDataAt(int i) {
-        return getDataAt(data, i);
+    public RComplex getDataAt(int index) {
+        return NativeDataAccess.getData(this, data, index);
     }
 
     @Override
@@ -107,8 +104,8 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
     @Override
     public boolean verify() {
         if (isComplete()) {
-            for (double d : data) {
-                if (d == RRuntime.DOUBLE_NA) {
+            for (int i = 0; i < getLength(); i++) {
+                if (getDataAt(i).isNA()) {
                     return false;
                 }
             }
@@ -118,6 +115,7 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
 
     @Override
     public double[] getDataCopy() {
+        assert data != null;
         return Arrays.copyOf(data, data.length);
     }
 
@@ -127,23 +125,23 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
      */
     @Override
     public double[] getDataWithoutCopying() {
+        assert data != null;
         return data;
     }
 
     @Override
     public RComplexVector copyWithNewDimensions(int[] newDimensions) {
+        assert data != null;
         return RDataFactory.createComplexVector(data, isComplete(), newDimensions);
     }
 
-    private RComplexVector updateDataAt(int i, RComplex right, NACheck rightNACheck) {
+    private RComplexVector updateDataAt(int index, RComplex value, NACheck rightNACheck) {
         assert !this.isShared();
-        int index = i << 1;
-        data[index] = right.getRealPart();
-        data[index + 1] = right.getImaginaryPart();
-        if (rightNACheck.check(right)) {
+        NativeDataAccess.setData(this, data, index, value.getRealPart(), value.getImaginaryPart());
+        if (rightNACheck.check(value)) {
             setComplete(false);
         }
-        assert !isComplete() || !RRuntime.isNA(right);
+        assert !isComplete() || !RRuntime.isNA(value);
         return this;
     }
 
@@ -153,6 +151,7 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
     }
 
     private double[] copyResizedData(int size, boolean fillNA) {
+        assert data != null;
         int csize = size << 1;
         double[] newData = Arrays.copyOf(data, csize);
         if (csize > this.getLength()) {
@@ -172,6 +171,7 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
 
     @Override
     protected RComplexVector internalCopyResized(int size, boolean fillNA, int[] dimensions) {
+        assert data != null;
         boolean isComplete = isComplete() && ((data.length >= size) || !fillNA);
         return RDataFactory.createComplexVector(copyResizedData(size, fillNA), isComplete, dimensions);
     }
@@ -189,9 +189,16 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
     @Override
     public void transferElementSameType(int toIndex, RAbstractVector fromVector, int fromIndex) {
         RAbstractComplexVector other = (RAbstractComplexVector) fromVector;
-        int toIndex2 = toIndex << 1;
         RComplex value = other.getDataAt(fromIndex);
-        data[toIndex2] = value.getRealPart();
-        data[toIndex2 + 1] = value.getImaginaryPart();
+        NativeDataAccess.setData(this, data, toIndex, value.getRealPart(), value.getImaginaryPart());
+    }
+
+    public long allocateNativeContents() {
+        try {
+            return NativeDataAccess.allocateNativeContents(this, data, getLength());
+        } finally {
+            data = null;
+            complete = false;
+        }
     }
 }
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 aba05f10a7db066f2269327c97f558ff8e5e7219..d1a8ced337293f4efa4ddd8a33aacd444a9308f2 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
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public final class RDoubleVector extends RVector<double[]> implements RAbstractDoubleVector {
 
-    private final double[] data;
+    private double[] data;
 
     RDoubleVector(double[] data, boolean complete) {
         super(complete);
@@ -68,6 +68,7 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
 
     @Override
     protected RDoubleVector internalCopy() {
+        assert data != null;
         return new RDoubleVector(Arrays.copyOf(data, data.length), this.isComplete());
     }
 
@@ -79,13 +80,13 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
     @Override
     public void setDataAt(Object store, int index, double value) {
         assert data == store;
-        ((double[]) store)[index] = value;
+        NativeDataAccess.setData(this, (double[]) store, index, value);
     }
 
     @Override
     public double getDataAt(Object store, int index) {
         assert data == store;
-        return ((double[]) store)[index];
+        return NativeDataAccess.getData(this, (double[]) store, index);
     }
 
     public RDoubleVector copyResetData(double[] newData) {
@@ -103,7 +104,7 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
 
     @Override
     public int getLength() {
-        return data.length;
+        return NativeDataAccess.getDataLength(this, data);
     }
 
     @Override
@@ -114,8 +115,8 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
     @Override
     public boolean verify() {
         if (isComplete()) {
-            for (double d : data) {
-                if (d == RRuntime.DOUBLE_NA) {
+            for (int i = 0; i < getLength(); i++) {
+                if (RRuntime.isNA(getDataAt(i))) {
                     return false;
                 }
             }
@@ -124,12 +125,13 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
     }
 
     @Override
-    public double getDataAt(int i) {
-        return data[i];
+    public double getDataAt(int index) {
+        return NativeDataAccess.getData(this, data, index);
     }
 
     @Override
     public double[] getDataCopy() {
+        assert data != null;
         return Arrays.copyOf(data, data.length);
     }
 
@@ -139,21 +141,23 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
      */
     @Override
     public double[] getDataWithoutCopying() {
+        assert data != null;
         return data;
     }
 
     @Override
     public RDoubleVector copyWithNewDimensions(int[] newDimensions) {
+        assert data != null;
         return RDataFactory.createDoubleVector(data, isComplete(), newDimensions);
     }
 
-    public RDoubleVector updateDataAt(int i, double right, NACheck valueNACheck) {
+    public RDoubleVector updateDataAt(int index, double value, NACheck valueNACheck) {
         assert !this.isShared();
-        data[i] = right;
-        if (valueNACheck.check(right)) {
+        NativeDataAccess.setData(this, data, index, value);
+        if (valueNACheck.check(value)) {
             complete = false;
         }
-        assert !isComplete() || !RRuntime.isNA(right);
+        assert !isComplete() || !RRuntime.isNA(value);
         return this;
     }
 
@@ -179,12 +183,14 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
     }
 
     private double[] copyResizedData(int size, boolean fillNA) {
+        assert data != null;
         double[] newData = Arrays.copyOf(data, size);
         return resizeData(newData, this.data, this.getLength(), fillNA);
     }
 
     @Override
     protected RDoubleVector internalCopyResized(int size, boolean fillNA, int[] dimensions) {
+        assert data != null;
         boolean isComplete = isComplete() && ((data.length >= size) || !fillNA);
         return RDataFactory.createDoubleVector(copyResizedData(size, fillNA), isComplete, dimensions);
     }
@@ -201,12 +207,20 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
 
     @Override
     public void transferElementSameType(int toIndex, RAbstractVector fromVector, int fromIndex) {
-        RAbstractDoubleVector other = (RAbstractDoubleVector) fromVector;
-        data[toIndex] = other.getDataAt(fromIndex);
+        NativeDataAccess.setData(this, data, toIndex, ((RAbstractDoubleVector) fromVector).getDataAt(fromIndex));
     }
 
     @Override
     public Object getDataAtAsObject(int index) {
         return getDataAt(index);
     }
+
+    public long allocateNativeContents() {
+        try {
+            return NativeDataAccess.allocateNativeContents(this, data, getLength());
+        } finally {
+            data = null;
+            complete = false;
+        }
+    }
 }
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 dd06073146befa544c177196ba38bf57e73bcfc0..42be6bdb5eeffc6592a4ce953a8da75b3f0c7aa5 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
@@ -74,27 +74,24 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
 
     @Override
     public int getDataAt(int index) {
-        return data == null ? NativeDataAccess.getIntData(this, index) : data[index];
+        return NativeDataAccess.getData(this, data, index);
     }
 
     @Override
     public int getDataAt(Object store, int index) {
         assert data == store;
-        return store == null ? NativeDataAccess.getIntData(this, index) : ((int[]) store)[index];
+        return NativeDataAccess.getData(this, (int[]) store, index);
     }
 
     @Override
     public void setDataAt(Object store, int index, int value) {
         assert data == store;
-        if (store == null) {
-            NativeDataAccess.setIntData(this, index, value);
-        } else {
-            ((int[]) store)[index] = value;
-        }
+        NativeDataAccess.setData(this, (int[]) store, index, value);
     }
 
     @Override
     protected RIntVector internalCopy() {
+        assert data != null;
         return new RIntVector(Arrays.copyOf(data, data.length), isComplete());
     }
 
@@ -113,7 +110,7 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
 
     @Override
     public int getLength() {
-        return data == null ? (int) NativeDataAccess.getDataLength(this) : data.length;
+        return NativeDataAccess.getDataLength(this, data);
     }
 
     @Override
@@ -125,7 +122,7 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
     public boolean verify() {
         if (isComplete()) {
             for (int i = 0; i < getLength(); i++) {
-                if (getDataAt(i) == RRuntime.INT_NA) {
+                if (RRuntime.isNA(getDataAt(i))) {
                     return false;
                 }
             }
@@ -151,16 +148,14 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
 
     @Override
     public RIntVector copyWithNewDimensions(int[] newDimensions) {
+        assert data != null;
         return RDataFactory.createIntVector(data, isComplete(), newDimensions);
     }
 
     public RIntVector updateDataAt(int index, int value, NACheck valueNACheck) {
         assert !this.isShared();
-        if (data == null) {
-            NativeDataAccess.setIntData(this, index, value);
-        } else {
-            data[index] = value;
-        }
+
+        NativeDataAccess.setData(this, data, index, value);
         if (valueNACheck.check(value)) {
             setComplete(false);
         }
@@ -213,13 +208,7 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
 
     @Override
     public void transferElementSameType(int toIndex, RAbstractVector fromVector, int fromIndex) {
-        RAbstractIntVector other = (RAbstractIntVector) fromVector;
-        if (data == null) {
-            NativeDataAccess.setIntData(this, toIndex, other.getDataAt(fromIndex));
-        } else {
-            data[toIndex] = other.getDataAt(fromIndex);
-        }
-        data[toIndex] = other.getDataAt(fromIndex);
+        NativeDataAccess.setData(this, data, toIndex, ((RAbstractIntVector) fromVector).getDataAt(fromIndex));
     }
 
     @Override
@@ -229,11 +218,7 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
 
     @Override
     public void setElement(int index, Object value) {
-        if (data == null) {
-            NativeDataAccess.setIntData(this, index, (int) value);
-        } else {
-            data[index] = (int) value;
-        }
+        NativeDataAccess.setData(this, data, index, (int) value);
     }
 
     public long allocateNativeContents() {
@@ -241,6 +226,7 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
             return NativeDataAccess.allocateNativeContents(this, data, getLength());
         } finally {
             data = null;
+            complete = false;
         }
     }
 }
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 b83a438aba7c54744e6cfb212ebd6e9af26834a3..14902799427cd5c0566c906eb610bbb48da21b92 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
@@ -77,17 +77,13 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
     @Override
     public void setDataAt(Object store, int index, byte value) {
         assert data == store;
-        if (store == null) {
-            NativeDataAccess.setIntData(this, index, RRuntime.logical2int(value));
-        } else {
-            ((byte[]) store)[index] = value;
-        }
+        NativeDataAccess.setData(this, (byte[]) store, index, value);
     }
 
     @Override
     public byte getDataAt(Object store, int index) {
         assert data == store;
-        return data == null ? (byte) NativeDataAccess.getIntData(this, index) : data[index];
+        return NativeDataAccess.getData(this, (byte[]) store, index);
     }
 
     @Override
@@ -111,7 +107,7 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
 
     @Override
     public int getLength() {
-        return data == null ? (int) NativeDataAccess.getDataLength(this) : data.length;
+        return NativeDataAccess.getDataLength(this, data);
     }
 
     @Override
@@ -123,7 +119,7 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
     public boolean verify() {
         if (isComplete()) {
             for (int i = 0; i < getLength(); i++) {
-                if (getDataAt(i) == RRuntime.LOGICAL_NA) {
+                if (RRuntime.isNA(getDataAt(i))) {
                     return false;
                 }
             }
@@ -133,16 +129,12 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
 
     @Override
     public byte getDataAt(int index) {
-        return data == null ? (byte) NativeDataAccess.getIntData(this, index) : data[index];
+        return NativeDataAccess.getData(this, data, index);
     }
 
     private RLogicalVector updateDataAt(int index, byte value, NACheck valueNACheck) {
         assert !this.isShared();
-        if (data == null) {
-            NativeDataAccess.setIntData(this, index, RRuntime.logical2int(value));
-        } else {
-            data[index] = value;
-        }
+        NativeDataAccess.setData(this, data, index, value);
         if (valueNACheck.check(value)) {
             setComplete(false);
         }
@@ -186,12 +178,7 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
 
     @Override
     public void transferElementSameType(int toIndex, RAbstractVector fromVector, int fromIndex) {
-        RAbstractLogicalVector other = (RAbstractLogicalVector) fromVector;
-        if (data == null) {
-            NativeDataAccess.setIntData(this, toIndex, RRuntime.logical2int(other.getDataAt(fromIndex)));
-        } else {
-            data[toIndex] = other.getDataAt(fromIndex);
-        }
+        NativeDataAccess.setData(this, data, toIndex, ((RAbstractLogicalVector) fromVector).getDataAt(fromIndex));
     }
 
     @Override
@@ -231,6 +218,7 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
             return NativeDataAccess.allocateNativeContents(this, data, getLength());
         } finally {
             data = null;
+            complete = false;
         }
     }
 }
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 1d680bc8bae69c9274ab42b77bf8f65557da1f14..fb6529e506d085bd21d1147de19e3a4a299fe00f 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
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public final class RRawVector extends RVector<byte[]> implements RAbstractRawVector {
 
-    private final byte[] data;
+    private byte[] data;
 
     RRawVector(byte[] data) {
         super(true);
@@ -67,35 +67,41 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
     }
 
     @Override
-    public byte getRawDataAt(int index) {
-        return data[index];
+    public byte[] getInternalStore() {
+        return data;
     }
 
     @Override
-    public byte getRawDataAt(Object store, int index) {
-        assert data == store;
-        return ((byte[]) store)[index];
+    public RRaw getDataAt(int index) {
+        return RDataFactory.createRaw(NativeDataAccess.getData(this, data, index));
     }
 
     @Override
-    public byte[] getInternalStore() {
-        return data;
+    public byte getRawDataAt(int index) {
+        return NativeDataAccess.getData(this, data, index);
+    }
+
+    @Override
+    public byte getRawDataAt(Object store, int index) {
+        assert data == store;
+        return NativeDataAccess.getData(this, (byte[]) store, index);
     }
 
     @Override
     public void setRawDataAt(Object store, int index, byte value) {
         assert data == store;
-        ((byte[]) store)[index] = value;
+        NativeDataAccess.setData(this, (byte[]) store, index, value);
     }
 
     @Override
     protected RRawVector internalCopy() {
+        assert data != null;
         return new RRawVector(Arrays.copyOf(data, data.length));
     }
 
     @Override
     public int getLength() {
-        return data.length;
+        return NativeDataAccess.getDataLength(this, data);
     }
 
     @Override
@@ -108,13 +114,9 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
         return true;
     }
 
-    @Override
-    public RRaw getDataAt(int i) {
-        return RDataFactory.createRaw(data[i]);
-    }
-
     @Override
     public byte[] getDataCopy() {
+        assert data != null;
         return Arrays.copyOf(data, data.length);
     }
 
@@ -124,11 +126,13 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
      */
     @Override
     public byte[] getDataWithoutCopying() {
+        assert data != null;
         return data;
     }
 
     @Override
     public RRawVector copyWithNewDimensions(int[] newDimensions) {
+        assert data != null;
         return RDataFactory.createRawVector(data, newDimensions);
     }
 
@@ -137,9 +141,9 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
         return this;
     }
 
-    public RRawVector updateDataAt(int i, RRaw right) {
+    public RRawVector updateDataAt(int index, RRaw value) {
         assert !this.isShared();
-        data[i] = right.getValue();
+        NativeDataAccess.setData(this, data, index, value.getValue());
         return this;
     }
 
@@ -149,6 +153,7 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
     }
 
     private byte[] copyResizedData(int size, boolean fillNA) {
+        assert data != null;
         byte[] newData = Arrays.copyOf(data, size);
         if (!fillNA) {
             // NA is 00 for raw
@@ -172,12 +177,20 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
 
     @Override
     public void transferElementSameType(int toIndex, RAbstractVector fromVector, int fromIndex) {
-        RAbstractRawVector other = (RAbstractRawVector) fromVector;
-        data[toIndex] = other.getRawDataAt(fromIndex);
+        NativeDataAccess.setData(this, data, toIndex, ((RAbstractRawVector) fromVector).getRawDataAt(fromIndex));
     }
 
     @Override
     public Object getDataAtAsObject(int index) {
         return getDataAt(index);
     }
+
+    public long allocateNativeContents() {
+        try {
+            return NativeDataAccess.allocateNativeContents(this, data, getLength());
+        } finally {
+            data = null;
+            complete = false;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
index 83dbd06f652fc392cbffe67925100887b6071adb..6eba171b149ef4343653812ae289948e71cc6311 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.runtime.ffi;
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.TempPathName;
+import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;