diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
index ca7edff095299b703d0ef15956476e5cbcf0a44d..2ab399a437127e09285780f687d2c59ea3fe03ec 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -148,7 +148,7 @@ void init_internals(JNIEnv *env) {
 	SET_VECTOR_ELT_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "SET_VECTOR_ELT", "(Ljava/lang/Object;ILjava/lang/Object;)V", 1);
 	RAW_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "RAW", "(Ljava/lang/Object;)[B", 1);
 	REAL_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "REAL", "(Ljava/lang/Object;)[D", 1);
-	LOGICAL_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "LOGICAL", "(Ljava/lang/Object;)[I", 1);
+	LOGICAL_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "LOGICAL", "(Ljava/lang/Object;)[B", 1);
 	INTEGER_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "INTEGER", "(Ljava/lang/Object;)[I", 1);
 	STRING_ELT_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "STRING_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 1);
 	VECTOR_ELT_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "VECTOR_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 1);
@@ -1024,10 +1024,16 @@ int *LOGICAL(SEXP x){
 	JNIEnv *thisenv = getEnv();
 	jint *data = (jint *) findCopiedObject(thisenv, x);
 	if (data == NULL) {
-	    jintArray intArray = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, LOGICAL_MethodID, x);
-	    int len = (*thisenv)->GetArrayLength(thisenv, intArray);
-	    data = (*thisenv)->GetIntArrayElements(thisenv, intArray, NULL);
-	    addCopiedObject(thisenv, x, LGLSXP, intArray, data);
+	    jbyteArray byteArray = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, LOGICAL_MethodID, x);
+	    int len = (*thisenv)->GetArrayLength(thisenv, byteArray);
+	    jbyte* internalData = (*thisenv)->GetByteArrayElements(thisenv, byteArray, NULL);
+	    data = malloc(len * sizeof(int));
+	    for (int i = 0; i < len; i++) {
+	    	char value = internalData[i];
+	    	data[i] = value == 0 ? FALSE : value == 1 ? TRUE : NA_INTEGER;
+	    }
+	    (*thisenv)->ReleaseByteArrayElements(thisenv, byteArray, internalData, JNI_ABORT);
+	    addCopiedObject(thisenv, x, LGLSXP, byteArray, data);
 	}
 	return data;
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
index e26fc56a969deb22b707ace5f6c5acda2b2aeb29..f009ca873b9f5227f8689deadb794c71fcaae750 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -97,11 +97,24 @@ jmp_buf *getErrorJmpBuf() {
 void releaseCopiedVector(JNIEnv *env, CopiedVector cv) {
     if (cv.obj != NULL) {
 	switch (cv.type) {
-	    case INTSXP: case LGLSXP: {
-		    jintArray intArray = (jintArray) cv.jArray;
-		    (*env)->ReleaseIntArrayElements(env, intArray, (jint *)cv.data, 0);
-		    break;
-	    }
+        case INTSXP: {
+	        jintArray intArray = (jintArray) cv.jArray;
+	        (*env)->ReleaseIntArrayElements(env, intArray, (jint *)cv.data, 0);
+	        break;
+        }
+
+        case LGLSXP: {
+        	// for LOGICAL, we need to convert back to 1-byte elements
+	        jintArray byteArray = (jbyteArray) cv.jArray;
+    	    int len = (*env)->GetArrayLength(env, byteArray);
+    	    jbyte* internalData = (*env)->GetByteArrayElements(env, byteArray, NULL);
+    	    int* data = (int*) cv.data;
+    	    for (int i = 0; i < len; i++) {
+    	    	internalData[i] = data[i] == NA_INTEGER ? 255 : (jbyte) data[i];
+    	    }
+    	    (*env)->ReleaseByteArrayElements(env, byteArray, internalData, 0);
+	        break;
+        }
 
 	    case REALSXP: {
 		    jdoubleArray doubleArray = (jdoubleArray) cv.jArray;
@@ -137,14 +150,14 @@ void invalidateCopiedObject(JNIEnv *env, SEXP oldObj) {
 		CopiedVector cv = copiedVectors[i];
 		if ((*env)->IsSameObject(env, cv.obj, oldObj)) {
 #if TRACE_COPIES
-			printf("invalidateCopiedObject(%p): found\n", x);
+			printf("invalidateCopiedObject(%p): found\n", oldObj);
 #endif
 			releaseCopiedVector(env, cv);
 			copiedVectors[i].obj = NULL;
 		}
 	}
 #if TRACE_COPIES
-	printf("invalidateCopiedObject(%p): not found\n", x);
+	printf("invalidateCopiedObject(%p): not found\n", oldObj);
 #endif
 }
 
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
index b7aec853d767aabed18efe3c1f21770f95626615..0f111ee0ce09b054d39da5f04230805375193a3b 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
@@ -460,21 +460,11 @@ public class CallRFFIHelper {
         }
     }
 
-    private static int toWideLogical(byte v) {
-        return RRuntime.isNA(v) ? Integer.MIN_VALUE : v;
-    }
-
-    public static int[] LOGICAL(Object x) {
+    public static byte[] LOGICAL(Object x) {
         if (x instanceof RLogicalVector) {
-            // TODO: this should not actually copy...
-            RLogicalVector vector = (RLogicalVector) x;
-            int[] array = new int[vector.getLength()];
-            for (int i = 0; i < vector.getLength(); i++) {
-                array[i] = toWideLogical(vector.getDataAt(i));
-            }
-            return array;
+            return ((RLogicalVector) x).getDataWithoutCopying();
         } else if (x instanceof Byte) {
-            return new int[]{toWideLogical((Byte) x)};
+            return new byte[]{(Byte) x};
         } else {
             throw unimplemented();
         }
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
index bc33e2a7a9f060afbd1732784cf35e579373f3f3..0505d5234162ca2c32319731fdb6df0c03d99b85 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
@@ -14,6 +14,10 @@ rffi.populateIntVector <- function(n) {
 	.Call("populateIntVector", as.integer(n), PACKAGE = "testrffi")
 }
 
+rffi.populateLogicalVector <- function(n) {
+	.Call("populateLogicalVector", as.integer(n), PACKAGE = "testrffi")
+}
+
 rffi.createExternalPtr <- function(addr, tag, prot) {
 	.Call("createExternalPtr", as.integer(addr), tag, prot, PACKAGE = "testrffi")
 }
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
index 1ed65e33a74d52c799dea0eeacaf1ae27740674e..25fe3356810e70836458d28314814a8a274940dc 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
@@ -63,6 +63,18 @@ SEXP populateIntVector(SEXP n) {
     return v;
 }
 
+SEXP populateLogicalVector(SEXP n) {
+    SEXP v;
+    int intN = INTEGER_VALUE(n);
+    PROTECT(v = allocVector(LGLSXP, intN));
+    int i;
+    for (i = 0; i < intN; i++) {
+    	LOGICAL(v)[i] = i == 0 ? TRUE : i == 1 ? NA_INTEGER : FALSE;
+    }
+    UNPROTECT(1);
+    return v;
+}
+
 SEXP createExternalPtr(SEXP addr, SEXP tag, SEXP prot) {
 	return R_MakeExternalPtr((void *) (long) INTEGER_VALUE(addr), tag, prot);
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 87e927a0a235c4e7ea39c6da5d15208e866a6e90..65b59b9e53af5db08ba70a9328f361095818e250 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -107383,7 +107383,7 @@ Error: unexpected '*' in:
 
 
 ##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFICall
-#{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.addInt(2L, 3L); r2 <- rffi.addDouble(2, 3); v <- rffi.populateIntVector(5); v2 <- rffi.dotCModifiedArguments(c(0,1,2,3)); v3<-rffi.isRString(character(0)); detach("package:testrffi"); list(r1, r2, v, v2, v3) }
+#{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.addInt(2L, 3L); r2 <- rffi.addDouble(2, 3); v <- rffi.populateIntVector(5); v2 <- rffi.dotCModifiedArguments(c(0,1,2,3)); v3<-rffi.isRString(character(0)); v4 <- rffi.populateLogicalVector(5); detach("package:testrffi"); list(r1, r2, v, v2, v3, v4) }
 [[1]]
 [1] 5
 
@@ -107410,6 +107410,9 @@ Error: unexpected '*' in:
 [[5]]
 [1] TRUE
 
+[[6]]
+[1]  TRUE    NA FALSE FALSE FALSE
+
 
 ##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFIExternal
 #{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.dotExternalAccessArgs(1L, 3, c(1,2,3), c('a', 'b'), 'b', TRUE, as.raw(12)); detach("package:testrffi"); list(r1) }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRFFIPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRFFIPackage.java
index 6887a110500e809be5c19a3c22c4aede418de022..ea44a093b98e03e0f15478121257f3d3d7e2c06f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRFFIPackage.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRFFIPackage.java
@@ -51,7 +51,7 @@ public class TestRFFIPackage extends TestRPackages {
                         new String[]{TestRPackages.libLoc()}));
         assertEval(TestBase.template(
                         "{ library(\"testrffi\", lib.loc = \"%0\"); r1 <- rffi.addInt(2L, 3L); r2 <- rffi.addDouble(2, 3); v <- rffi.populateIntVector(5); v2 <- rffi.dotCModifiedArguments(c(0,1,2,3)); " +
-                                        "v3<-rffi.isRString(character(0)); detach(\"package:testrffi\"); list(r1, r2, v, v2, v3) }",
+                                        "v3<-rffi.isRString(character(0)); v4 <- rffi.populateLogicalVector(5); detach(\"package:testrffi\"); list(r1, r2, v, v2, v3, v4) }",
                         new String[]{TestRPackages.libLoc()}));
     }