diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java
index 799d8b5699825997b8d063cdffcb99989e6c8f02..0bcce8f8e3b934861de5cc16ee14901e85000804 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java
@@ -29,6 +29,7 @@ import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceEnabled;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
@@ -40,6 +41,7 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.ffi.impl.common.RFFIUtils;
 import com.oracle.truffle.r.ffi.impl.nfi.TruffleNFI_CallFactory.TruffleNFI_InvokeCallNodeGen;
 import com.oracle.truffle.r.ffi.impl.upcalls.Callbacks;
+import com.oracle.truffle.r.ffi.impl.upcalls.FFIUnwrapNode;
 import com.oracle.truffle.r.ffi.impl.upcalls.FFIWrapNode;
 import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -234,18 +236,8 @@ public class TruffleNFI_Call implements CallRFFI {
         }
     }
 
-    public abstract static class TruffleNFI_InvokeCallBaseNode extends Node {
-
-        protected static FFIWrapNode[] createWrapArgumentNodes(int count) {
-            FFIWrapNode[] result = new FFIWrapNode[count];
-            for (int i = 0; i < count; i++) {
-                result[i] = FFIWrapNode.create();
-            }
-            return result;
-        }
-    }
-
-    public abstract static class TruffleNFI_InvokeCallNode extends TruffleNFI_InvokeCallBaseNode implements InvokeCallNode {
+    @ImportStatic(FFIWrapNode.class)
+    public abstract static class TruffleNFI_InvokeCallNode extends Node implements InvokeCallNode {
         private static final String[] SIGNATURES = new String[32];
 
         @Child private Node bindNode = Message.createInvoke(1).createNode();
@@ -277,7 +269,8 @@ public class TruffleNFI_Call implements CallRFFI {
         @Specialization(guards = {"args.length == cachedArgsLength", "nativeCallInfo.address.asTruffleObject() == cachedAddress"})
         protected Object invokeCallCached(NativeCallInfo nativeCallInfo, Object[] args,
                         @SuppressWarnings("unused") @Cached("args.length") int cachedArgsLength,
-                        @Cached("createWrapArgumentNodes(cachedArgsLength)") FFIWrapNode[] ffiWrapNodes,
+                        @Cached("create(cachedArgsLength)") FFIWrapNode[] ffiWrapNodes,
+                        @Cached("create()") FFIUnwrapNode unwrap,
                         @Cached("createExecute(cachedArgsLength)") Node executeNode,
                         @SuppressWarnings("unused") @Cached("nativeCallInfo.address.asTruffleObject()") TruffleObject cachedAddress,
                         @Cached("getFunction(cachedAddress, cachedArgsLength)") TruffleObject cachedFunction) {
@@ -286,7 +279,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 boolean isNullSetting = prepareCall(nativeCallInfo.name, args, ffiWrapNodes);
                 try {
                     result = ForeignAccess.sendExecute(executeNode, cachedFunction, args);
-                    return result;
+                    return unwrap.execute(result);
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
@@ -298,14 +291,15 @@ public class TruffleNFI_Call implements CallRFFI {
         @Specialization(limit = "99", guards = "args.length == cachedArgsLength")
         protected Object invokeCallCachedLength(NativeCallInfo nativeCallInfo, Object[] args,
                         @Cached("args.length") int cachedArgsLength,
-                        @Cached("createWrapArgumentNodes(cachedArgsLength)") FFIWrapNode[] ffiWrapNodes,
+                        @Cached("create(cachedArgsLength)") FFIWrapNode[] ffiWrapNodes,
+                        @Cached("create()") FFIUnwrapNode unwrap,
                         @Cached("createExecute(cachedArgsLength)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
                 boolean isNullSetting = prepareCall(nativeCallInfo.name, args, ffiWrapNodes);
                 try {
                     result = ForeignAccess.sendExecute(executeNode, getFunction(nativeCallInfo.address.asTruffleObject(), cachedArgsLength), args);
-                    return result;
+                    return unwrap.execute(result);
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
@@ -319,14 +313,14 @@ public class TruffleNFI_Call implements CallRFFI {
         }
     }
 
-    private static class TruffleNFI_InvokeVoidCallNode extends TruffleNFI_InvokeCallBaseNode implements InvokeVoidCallNode {
+    private static class TruffleNFI_InvokeVoidCallNode extends Node implements InvokeVoidCallNode {
         private static final String CallVoid1Sig = "(object): void";
         private static final String CallVoid0Sig = "(): void";
         @Child private Node bindNode = Message.createInvoke(1).createNode();
         @Child private Node execute0Node = Message.createExecute(0).createNode();
         @Child private Node execute1Node = Message.createExecute(1).createNode();
-        @Children private final FFIWrapNode[] ffiWrapNodes0 = createWrapArgumentNodes(0);
-        @Children private final FFIWrapNode[] ffiWrapNodes1 = createWrapArgumentNodes(1);
+        @Children private final FFIWrapNode[] ffiWrapNodes0 = FFIWrapNode.create(0);
+        @Children private final FFIWrapNode[] ffiWrapNodes1 = FFIWrapNode.create(1);
 
         @Override
         public void execute(NativeCallInfo nativeCallInfo, Object[] args) {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java
index 2ae0b803e372d6040849900704aa52227a2efc0f..4f5e750db634c1e28547793d18fd298b9212e6d1 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java
@@ -66,4 +66,12 @@ public abstract class FFIWrapNode extends Node {
     public static FFIWrapNode create() {
         return FFIWrapNodeGen.create();
     }
+
+    public static FFIWrapNode[] create(int count) {
+        FFIWrapNode[] result = new FFIWrapNode[count];
+        for (int i = 0; i < count; i++) {
+            result[i] = FFIWrapNode.create();
+        }
+        return result;
+    }
 }