From e36ea522715af25c8ec6e09df2c44d0e26e3c97d Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 22 Feb 2018 22:03:10 +0100
Subject: [PATCH] TryRfEvalNode: support errorFlag also with NFI

---
 .../r/ffi/impl/nodes/TryRfEvalNode.java       | 52 +++++++++++++++----
 1 file changed, 42 insertions(+), 10 deletions(-)

diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/TryRfEvalNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/TryRfEvalNode.java
index 7048ab7c49..7783c59bf9 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/TryRfEvalNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/TryRfEvalNode.java
@@ -22,35 +22,67 @@
  */
 package com.oracle.truffle.r.ffi.impl.nodes;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter;
 import com.oracle.truffle.r.runtime.RErrorHandling;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RNull;
 
 public final class TryRfEvalNode extends FFIUpCallNode.Arg4 {
-    @Child RfEvalNode rfEvalNode = RfEvalNode.create();
-    @Child Node writeErrorFlagNode = Message.WRITE.createNode();
+    @Child private RfEvalNode rfEvalNode = RfEvalNode.create();
+    @Child private Node isNullNode = Message.IS_NULL.createNode();
+    @Child private Node writeErrorFlagNode;
+    @Child private Node isPointerNode;
+    @Child private Node asPointerNode;
 
     @Override
     public Object executeObject(Object expr, Object env, Object errorFlag, Object silent) {
         Object handlerStack = RErrorHandling.getHandlerStack();
         Object restartStack = RErrorHandling.getRestartStack();
+        boolean ok = true;
+        Object result = RNull.instance;
         try {
             // TODO handle silent
             RErrorHandling.resetStacks();
-            return rfEvalNode.executeObject(expr, env);
+            result = rfEvalNode.executeObject(expr, env);
         } catch (Throwable t) {
-            try {
-                ForeignAccess.sendWrite(writeErrorFlagNode, (TruffleObject) errorFlag, 0, 1);
-            } catch (InteropException e) {
-                // Ignore it, when using NFI, e.g., the errorFlag TO does not support the WRITE
-                // message
-            }
-            return null;
+            ok = false;
+            result = RNull.instance;
         } finally {
             RErrorHandling.restoreStacks(handlerStack, restartStack);
         }
+        TruffleObject errorFlagTO = (TruffleObject) errorFlag;
+        if (!ForeignAccess.sendIsNull(isNullNode, errorFlagTO)) {
+            if (isPointerNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                isPointerNode = insert(Message.IS_POINTER.createNode());
+            }
+            if (ForeignAccess.sendIsPointer(isPointerNode, errorFlagTO)) {
+                if (asPointerNode == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    asPointerNode = insert(Message.AS_POINTER.createNode());
+                }
+                long errorFlagPtr;
+                try {
+                    errorFlagPtr = ForeignAccess.sendAsPointer(asPointerNode, errorFlagTO);
+                } catch (UnsupportedMessageException e) {
+                    throw RInternalError.shouldNotReachHere("IS_POINTER message returned true, AS_POINTER should not fail");
+                }
+                UnsafeAdapter.UNSAFE.putInt(errorFlagPtr, ok ? 0 : 1);
+            } else {
+                try {
+                    ForeignAccess.sendWrite(writeErrorFlagNode, errorFlagTO, 0, 1);
+                } catch (InteropException e) {
+                    throw RInternalError.shouldNotReachHere("Rf_tryEval errorFlag should be either pointer or support WRITE message");
+                }
+            }
+        }
+        return result;
     }
 }
-- 
GitLab