From 2ffceff9e893cfcea70e7c851008ad296b2fd9f8 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 27 Mar 2017 10:59:23 +0200
Subject: [PATCH] Using RExternalPtr to represent native address instead of a
 long.

---
 .../fficall/src/jni/Connections.c             | 30 +++++++---------
 .../r/nodes/ffi/JavaUpCallsRFFIImpl.java      |  5 +--
 .../r/nodes/ffi/TracingUpCallsRFFIImpl.java   |  2 +-
 .../r/runtime/conn/NativeConnections.java     | 36 +++++++------------
 .../truffle/r/runtime/ffi/StdUpCallsRFFI.java |  2 +-
 5 files changed, 29 insertions(+), 46 deletions(-)

diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Connections.c b/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
index 5b2f516c15..0cf9704787 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
@@ -81,7 +81,7 @@ void init_connections(JNIEnv *env) {
 	getOpenModeMethodID = checkGetMethodID(env, UpCallsRFFIClass, "getOpenModeString", "(Ljava/lang/Object;)Ljava/lang/String;", 0);
 
 	/* int R_new_custom_connection(String, String, String) */
-	newCustomConnectionMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_new_custom_connection", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;J)Ljava/lang/Object;", 0);
+	newCustomConnectionMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_new_custom_connection", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 }
 
 static char *connStringToChars(JNIEnv *env, jstring string) {
@@ -190,7 +190,8 @@ SEXP R_new_custom_connection(const char *description, const char *mode, const ch
 	jstring jsDescription = (*thisenv)->NewStringUTF(thisenv, description);
 	jstring jsMode = (*thisenv)->NewStringUTF(thisenv, mode);
 	jstring jsClassName = (*thisenv)->NewStringUTF(thisenv, class_name);
-	ans = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, newCustomConnectionMethodID, jsDescription, jsMode, jsClassName, (jlong)new);
+	jobject addrObj = R_MakeExternalPtr(new, R_NilValue, R_NilValue);
+	ans = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, newCustomConnectionMethodID, jsDescription, jsMode, jsClassName, addrObj);
 	if (ans) {
 
 		new->class = (char *) malloc(strlen(class_name) + 1);
@@ -236,19 +237,12 @@ SEXP R_new_custom_connection(const char *description, const char *mode, const ch
  * Position 0 is the lower part and position 1 is the higher part of the address.
  * This currently assumes max. 64-bit addresses !
  */
-static Rconnection convertToAddress(SEXP intVec) {
-	if(!Rf_isVector(intVec)) {
+static Rconnection convertToAddress(SEXP addrObj) {
+	if(!inherits(addrObj, "externalptr")) {
 		error(_("invalid address object"));
 	}
+    return (Rconnection) R_ExternalPtrAddr(addrObj);
 
-	// convert integer vector to array
-    int *arr = INTEGER(intVec);
-
-    // bit-fiddle address
-    jlong ptr = (jlong) arr[1];
-    ptr = (ptr<<32) | ((jlong)arr[0] & 0xFFFFFFFFl);
-
-    return (Rconnection) ptr;
 }
 
 /*
@@ -279,7 +273,7 @@ SEXP __GetFlagNativeConnection(SEXP rConnAddrObj, jstring jname) {
 	}
 	free(name);
 
-	return Rf_ScalarLogical(result);
+	return ScalarLogical(result);
 }
 
 /*
@@ -290,7 +284,7 @@ SEXP __GetFlagNativeConnection(SEXP rConnAddrObj, jstring jname) {
 SEXP __OpenNativeConnection(SEXP rConnAddrObj) {
 	Rconnection con = convertToAddress(rConnAddrObj);
 	Rboolean success = con->open(con);
-	return Rf_ScalarLogical(success);
+	return ScalarLogical(success);
 }
 
 /*
@@ -317,7 +311,7 @@ SEXP __ReadNativeConnection(SEXP rConnAddrObj, jbyteArray bufObj, SEXP nVec) {
 	size_t nread = con->read(tmp_buf, 1, n, con);
 	// copy back and release buffer
 	(*thisenv)->ReleaseByteArrayElements(thisenv, bufObj, tmp_buf, JNI_COMMIT);
-	return Rf_ScalarInteger(nread);
+	return ScalarInteger(nread);
 }
 
 /*
@@ -333,7 +327,7 @@ SEXP __WriteNativeConnection(SEXP rConnAddrObj, jbyteArray bufObj, SEXP nVec) {
 	size_t nwritten = con->write(bytes, 1, n, con);
 	// just release buffer
 	(*thisenv)->ReleaseByteArrayElements(thisenv, bufObj, bytes, JNI_ABORT);
-	return Rf_ScalarInteger(nwritten);
+	return ScalarInteger(nwritten);
 }
 
 /*
@@ -343,11 +337,11 @@ SEXP __WriteNativeConnection(SEXP rConnAddrObj, jbyteArray bufObj, SEXP nVec) {
  */
 SEXP __SeekNativeConnection(SEXP rConnAddrObj, SEXP whereObj, SEXP originObj, SEXP rwObj) {
 	Rconnection con = convertToAddress(rConnAddrObj);
-    double where = adDouble(whereObj);
+    double where = asReal(whereObj);
     int origin = asInteger(originObj);
     int rw = asInteger(rwObj);
 	double oldPos = con->seek(con, where, origin, rw);
-	return Rf_ScalarReal(oldPos);
+	return ScalarReal(oldPos);
 }
 
 size_t R_ReadConnection(Rconnection con, void *buf, size_t n) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java
index 70bc2ec622..c06af8b64f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java
@@ -1204,13 +1204,14 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object R_new_custom_connection(Object description, Object mode, Object className, long readAddr) {
+    public Object R_new_custom_connection(Object description, Object mode, Object className, Object connAddrObj) {
         // TODO handle encoding properly !
         String strDescription = (String) description;
         String strMode = (String) mode;
         String strClassName = (String) className;
+        RExternalPtr connAddr = guaranteeInstanceOf(connAddrObj, RExternalPtr.class);
         try {
-            return new NativeRConnection(strDescription, strMode, strClassName, readAddr).asVector();
+            return new NativeRConnection(strDescription, strMode, strClassName, connAddr).asVector();
         } catch (IOException e) {
             return InvalidConnection.instance.asVector();
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java
index 7cdfff95c3..b89d83cc56 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java
@@ -742,7 +742,7 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object R_new_custom_connection(Object description, Object mode, Object className, long readAddr) {
+    public Object R_new_custom_connection(Object description, Object mode, Object className, Object readAddr) {
         RFFIUtils.traceUpCall("R_new_custom_connection", description, mode, className, readAddr);
         return delegate.R_new_custom_connection(description, mode, className, readAddr);
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java
index cb0f5f655d..e6e7baa075 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java
@@ -38,6 +38,7 @@ import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
 import com.oracle.truffle.r.runtime.conn.RConnection.SeekMode;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
@@ -75,9 +76,9 @@ public class NativeConnections {
     public static class NativeRConnection extends BaseRConnection {
         private final String customConClass;
         private final String description;
-        private final long addr;
+        private final RExternalPtr addr;
 
-        public NativeRConnection(String description, String modeString, String customConClass, long addr) throws IOException {
+        public NativeRConnection(String description, String modeString, String customConClass, RExternalPtr addr) throws IOException {
             super(ConnectionClass.NATIVE, modeString, AbstractOpenMode.Read);
             this.customConClass = Objects.requireNonNull(customConClass);
             this.description = Objects.requireNonNull(description);
@@ -117,7 +118,7 @@ public class NativeConnections {
             return customConClass;
         }
 
-        public long getNativeAddress() {
+        public RExternalPtr getNativeAddress() {
             return addr;
         }
 
@@ -135,8 +136,7 @@ public class NativeConnections {
             NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(GET_FLAG_NATIVE_CONNECTION);
             RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
 
-            RIntVector addrVec = convertAddrToIntVec(addr);
-            Object result = nativeCallTarget.call(ni, new Object[]{addrVec, name});
+            Object result = nativeCallTarget.call(ni, new Object[]{addr, name});
             if (result instanceof RLogicalVector) {
                 return ((RLogicalVector) result).getDataAt(0) == RRuntime.LOGICAL_TRUE;
             }
@@ -151,7 +151,7 @@ public class NativeConnections {
      * @param rw seek mode (read=1, write=2, last)
      * @return the old cursor position
      */
-    private static long seekSingleMode(long addr, long offset, SeekMode seekMode, int rw) {
+    private static long seekSingleMode(RExternalPtr addr, long offset, SeekMode seekMode, int rw) {
         RDoubleVector where = RDataFactory.createDoubleVectorFromScalar(offset);
         RIntVector seekCode;
         switch (seekMode) {
@@ -172,8 +172,7 @@ public class NativeConnections {
 
         NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(SEEK_NATIVE_CONNECTION);
         RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
-        RIntVector addrVec = convertAddrToIntVec(addr);
-        Object result = nativeCallTarget.call(ni, new Object[]{addrVec, where, seekCode, rwCode});
+        Object result = nativeCallTarget.call(ni, new Object[]{addr, where, seekCode, rwCode});
         if (result instanceof RDoubleVector) {
             return (long) ((RDoubleVector) result).getDataAt(0);
         }
@@ -286,12 +285,11 @@ public class NativeConnections {
         }
     }
 
-    private static void openNative(long addr) throws IOException {
+    private static void openNative(RExternalPtr addr) throws IOException {
         NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(OPEN_NATIVE_CONNECTION);
         RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
 
-        RIntVector addrVec = convertAddrToIntVec(addr);
-        Object result = nativeCallTarget.call(ni, new Object[]{addrVec});
+        Object result = nativeCallTarget.call(ni, new Object[]{addr});
         if (!(result instanceof RLogicalVector && ((RLogicalVector) result).getDataAt(0) == RRuntime.LOGICAL_TRUE)) {
             throw new IOException("could not open connection");
         }
@@ -309,8 +307,7 @@ public class NativeConnections {
         public int read(ByteBuffer dst) throws IOException {
             NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(READ_NATIVE_CONNECTION);
             RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
-            RIntVector vec = NativeConnections.convertAddrToIntVec(base.addr);
-            Object call = nativeCallTarget.call(ni, new Object[]{vec, dst.array(), dst.remaining()});
+            Object call = nativeCallTarget.call(ni, new Object[]{base.addr, dst.array(), dst.remaining()});
 
             if (call instanceof RIntVector) {
                 int nread = ((RIntVector) call).getDataAt(0);
@@ -331,8 +328,7 @@ public class NativeConnections {
         public void close() throws IOException {
             NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(CLOSE_NATIVE_CONNECTION);
             RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
-            RIntVector vec = NativeConnections.convertAddrToIntVec(base.addr);
-            nativeCallTarget.call(ni, new Object[]{vec});
+            nativeCallTarget.call(ni, new Object[]{base.addr});
         }
 
         @Override
@@ -340,8 +336,7 @@ public class NativeConnections {
             NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(WRITE_NATIVE_CONNECTION);
             RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
 
-            RIntVector vec = NativeConnections.convertAddrToIntVec(base.addr);
-            Object result = nativeCallTarget.call(ni, new Object[]{vec, src.array(), src.remaining()});
+            Object result = nativeCallTarget.call(ni, new Object[]{base.addr, src.array(), src.remaining()});
 
             if (result instanceof RIntVector) {
                 return ((RIntVector) result).getDataAt(0);
@@ -350,11 +345,4 @@ public class NativeConnections {
             throw RInternalError.shouldNotReachHere("unexpected result type");
         }
     }
-
-    static RIntVector convertAddrToIntVec(long addr) {
-        int high = (int) (addr >> 32);
-        int low = (int) addr;
-        RIntVector vec = RDataFactory.createIntVector(new int[]{low, high}, true);
-        return vec;
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java
index 82a1e81ff4..dceb6d282d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java
@@ -254,7 +254,7 @@ public interface StdUpCallsRFFI {
 
     Object R_CHAR(Object x);
 
-    Object R_new_custom_connection(@RFFICstring Object description, @RFFICstring Object mode, @RFFICstring Object className, long readAddr);
+    Object R_new_custom_connection(@RFFICstring Object description, @RFFICstring Object mode, @RFFICstring Object className, Object readAddr);
 
     int R_ReadConnection(int fd, byte[] buf);
 
-- 
GitLab