From c4d0a21a790bea67550f79d575b7e62ee64d4ea4 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Mon, 21 Nov 2016 16:12:28 -0800
Subject: [PATCH] misc rffi bug fixes

---
 .../fficall/src/jni/Rinternals.c                   |  2 +-
 .../truffle/r/nodes/builtin/base/foreign/DotC.java |  9 ++++++++-
 .../builtin/base/foreign/ForeignFunctions.java     |  3 ++-
 .../truffle/r/runtime/ffi/jni/CallRFFIHelper.java  | 14 +++++++++++++-
 4 files changed, 24 insertions(+), 4 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 c8ef247f6f..d097f37157 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -715,7 +715,7 @@ const char *Rf_translateCharUTF8(SEXP x) {
 SEXP Rf_lengthgets(SEXP x, R_len_t y) {
 	TRACE(TARGp, x);
 	JNIEnv *thisenv = getEnv();
-	invalidateCopiedObject(thisenv, x);
+	invalidateNativeArray(thisenv, x);
 	SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, CallRFFIHelperClass, Rf_lengthgetsMethodID, x, y);
 	return checkRef(thisenv, result);
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/DotC.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/DotC.java
index 60f28c4e3c..5b859523cf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/DotC.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/DotC.java
@@ -206,7 +206,14 @@ public abstract class DotC extends RBuiltinNode {
                     results[i] = RDataFactory.createIntVector((int[]) nativeArgs[i], RDataFactory.COMPLETE_VECTOR);
                     break;
                 case SCALAR_LOGICAL:
-                    results[i] = RDataFactory.createLogicalVector((byte[]) nativeArgs[i], RDataFactory.COMPLETE_VECTOR);
+                    // have to convert back from int[]
+                    int[] nativeIntArgs = (int[]) nativeArgs[i];
+                    byte[] nativeByteArgs = new byte[nativeIntArgs.length];
+                    for (int j = 0; j < nativeByteArgs.length; j++) {
+                        int nativeInt = nativeIntArgs[j];
+                        nativeByteArgs[j] = (byte) (nativeInt == RRuntime.INT_NA ? RRuntime.LOGICAL_NA : nativeInt & 0xFF);
+                    }
+                    results[i] = RDataFactory.createLogicalVector(nativeByteArgs, RDataFactory.COMPLETE_VECTOR);
                     break;
                 case VECTOR_DOUBLE:
                     results[i] = ((RAbstractDoubleVector) array[i]).materialize().copyResetData((double[]) nativeArgs[i]);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java
index bd01a896e5..14adfe090d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java
@@ -45,6 +45,7 @@ import com.oracle.truffle.r.library.parallel.ParallelFunctionsFactory.MCIsChildN
 import com.oracle.truffle.r.library.stats.CdistNodeGen;
 import com.oracle.truffle.r.library.stats.CompleteCases;
 import com.oracle.truffle.r.library.stats.CovcorNodeGen;
+import com.oracle.truffle.r.library.stats.CutreeNodeGen;
 import com.oracle.truffle.r.library.stats.Dbinom;
 import com.oracle.truffle.r.library.stats.DoubleCentreNodeGen;
 import com.oracle.truffle.r.library.stats.GammaFunctionsFactory.QgammaNodeGen;
@@ -383,8 +384,8 @@ public class ForeignFunctions {
                     return CdistNodeGen.create();
                 case "DoubleCentre":
                     return DoubleCentreNodeGen.create();
-
                 case "cutree":
+                    return CutreeNodeGen.create();
                 case "isoreg":
                 case "monoFC_m":
                 case "numeric_deriv":
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 f1818466bd..add58098c4 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
@@ -79,6 +79,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.ffi.RFFIUtils;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 import com.oracle.truffle.r.runtime.nodes.DuplicationHelper;
+import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.rng.RRNG;
 
 /**
@@ -86,6 +87,13 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
  * R header files, e.g. {@code Rinternals.h} that are used by C/C++ code. For ease of
  * identification, we use method names that, as far as possible, match the names in the header
  * files. These methods should never be called from normal FastR code.
+ *
+ * TODO Many of the implementations here are incomplete and/or duplicate code that exists in the
+ * Truffle side of the implementation, i.e., {@link RNode} subclasses. A complete refactoring that
+ * accesses the Truffle implementations (possibly somewhat refactored owing to the fact that the
+ * Truffle side is driven by the builtins yet these functions don't not always map 1-1 to a builtin)
+ * is desirable. In some cases it may be possible to "implement" the functions in R (which is a
+ * simple way to achieve the above).
  */
 public class CallRFFIHelper {
 
@@ -183,12 +191,15 @@ public class CallRFFIHelper {
         if (RFFIUtils.traceEnabled()) {
             RFFIUtils.traceUpCall("Rf_asInteger", x);
         }
+        // TODO this is quite incomplete and really should be implemented with CastIntegerNode
         if (x instanceof Integer) {
             return ((Integer) x).intValue();
         } else if (x instanceof Double) {
             return RRuntime.double2int((Double) x);
         } else if (x instanceof Byte) {
             return RRuntime.logical2int((Byte) x);
+        } else if (x instanceof RLogicalVector) {
+            return RRuntime.logical2int(((RLogicalVector) x).getDataAt(0));
         } else {
             guaranteeInstanceOf(x, RIntVector.class);
             return ((RIntVector) x).getDataAt(0);
@@ -722,7 +733,8 @@ public class CallRFFIHelper {
             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");
+        guarantee(x instanceof RShareable || x instanceof RIntSequence || 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 if (x instanceof RIntSequence) {
-- 
GitLab