From 1852ed272e886f0268c254d92b4e28c2b61668af Mon Sep 17 00:00:00 2001
From: Adam Welc <adam.welc@oracle.com>
Date: Tue, 11 Oct 2016 18:01:34 -0700
Subject: [PATCH] Support for creating shallow duplicates on the native side.

---
 .../fficall/src/jni/Rinternals.c                    | 11 +++++++++--
 .../truffle/r/runtime/ffi/jni/CallRFFIHelper.java   | 13 +++++++++----
 2 files changed, 18 insertions(+), 6 deletions(-)

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 a5c4ac637f..2b3a43d94c 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -150,7 +150,7 @@ void init_internals(JNIEnv *env) {
 	Rf_allocateVectorMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_allocateVector", "(II)Ljava/lang/Object;", 1);
 	Rf_allocateMatrixMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_allocateMatrix", "(III)Ljava/lang/Object;", 1);
 	Rf_allocateArrayMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_allocateArray", "(ILjava/lang/Object;)Ljava/lang/Object;", 1);
-	Rf_duplicateMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_duplicate", "(Ljava/lang/Object;)Ljava/lang/Object;", 1);
+	Rf_duplicateMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_duplicate", "(Ljava/lang/Object;I)Ljava/lang/Object;", 1);
 	Rf_anyDuplicatedMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_anyDuplicated", "(Ljava/lang/Object;I)I", 1);
 	Rf_NewHashedEnvMethodID = checkGetMethodID(env, CallRFFIHelperClass, "Rf_createNewEnv", "(Lcom/oracle/truffle/r/runtime/env/REnvironment;Ljava/lang/String;ZI)Lcom/oracle/truffle/r/runtime/env/REnvironment;", 1);
 	RprintfMethodID = checkGetMethodID(env, CallRFFIHelperClass, "printf", "(Ljava/lang/String;)V", 1);
@@ -382,7 +382,14 @@ SEXP Rf_setAttrib(SEXP vec, SEXP name, SEXP val) {
 SEXP Rf_duplicate(SEXP x) {
 	TRACE(TARGp, x);
 	JNIEnv *thisenv = getEnv();
-	SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_duplicateMethodID, x);
+	SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_duplicateMethodID, x, 1);
+	return checkRef(thisenv, result);
+}
+
+SEXP Rf_shallow_duplicate(SEXP x) {
+	TRACE(TARGp, x);
+	JNIEnv *thisenv = getEnv();
+	SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_duplicateMethodID, x, 0);
 	return checkRef(thisenv, result);
 }
 
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java
index 3d6bbf5431..90b4c432b5 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java
@@ -703,12 +703,17 @@ public class CallRFFIHelper {
         }
     }
 
-    public static Object Rf_duplicate(Object x) {
+    public static Object Rf_duplicate(Object x, int deep) {
         if (RFFIUtils.traceEnabled()) {
-            RFFIUtils.traceUpCall("Rf_duplicate", x);
+            RFFIUtils.traceUpCall("Rf_duplicate", x, deep);
+        }
+        guarantee(x != null, "unexpected type: null instead of " + x.getClass().getSimpleName());
+        guarantee(x instanceof RShareable || x instanceof RExternalPtr, "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of RShareable or RExternalPtr");
+        if (x instanceof RShareable) {
+            return deep == 1 ? ((RShareable) x).deepCopy() : ((RShareable) x).copy();
+        } else {
+            return ((RExternalPtr) x).copy();
         }
-        guaranteeInstanceOf(x, RAbstractVector.class);
-        return ((RAbstractVector) x).copy();
     }
 
     public static int Rf_anyDuplicated(Object x, int fromLast) {
-- 
GitLab